The figure below illustrates a method of current control. It shows four LEDs in a 2x2 arrangement; one would adapt the number of LEDs in series or parallel in accord with how one's array is wired, what voltages are available, LED current requirements, transistor power limitations, etc. [Edit: See transistor-power example calculation at end.]
Each separately-controlled group of LEDs would need one such circuit. Each circuit needs one control voltage (eg, from a DAC or a digital potentiometer voltage divider circuit) and needs one transistor per series chain.
Suppose the following conditions hold.
- Q1 and Q2 are equivalent transistors and Vbe is 0.7 V typ. (one diode drop)
- D1, D2, D3, D4 are equivalent LEDs
- Resistors R1, R2 are small and equal (eg 1–30Ω)
- V1 is some fixed DC voltage, eg about 1 V
- V > 2*Vf + Vbe + VR where Vf = typical forward voltage of D1...4
Under these conditions, V1 will drive current into the bases of Q1 and Q2, causing transistor-amplified current to flow through R1 and R2 and maintain the condition V1 = Vbe + VR1 = Vbe + VR2.
Here is a concrete example: Suppose we want 23 mA through each LED and that R1=R2=17Ω. VR = IR = 0.023 mA · 17 Ω = 0.391 V. If Vbe is about 0.7 V, then we set V1 = 0.7 + 0.391 V or about 1.09 V to get 23 mA through each LED. More generally, to get current I through the LEDs we solve V1 = Vbe + VR = 0.7 + IR = 0.7 + I·17.
The amount of current required from the V1 voltage source depends on transistor hFE or β.
Eg, if β is about 100 and ILED is 20 mA then each transistor will need about 20/100 mA or about 200 μA of base drive. This amount of current probably could be delivered by a voltage divider based on an AD5206 (the digital potentiometer chip that's used in the SPIDigitalPot tutorial mentioned in the question).
The AD5206 digital potentiometer datasheet shows an absolute maximum rating for Package Power Dissipation of (TJMAX-TA)/θJA. If ambient TA is 25℃ and θJA is 70°C/W (as for a SOIC package) this gives (150-25)/70 = 1.8 W max package power. However, it would be reasonable to limit dissipation to under half a watt. In the 10 KΩ version of the AD5206, that means a little less than 2.9 mA maximum per channel. [I = √(0.5 W /(6 channels * 10000Ω)).] If several low-beta transistors are used to drive several strings of LEDs, 2.8 mA might be marginal.
Only a small fraction of the current through a voltage divider can be drawn off without upsetting the division ratio. A unity gain buffer amplifier [as in the following figure] can be used to increase linearity of voltage-divider output by providing a high-impedance connection to the divider.
(In the figure above, R1 and R2 are not related to R1 and R2 of the previous figure. Here, R2 represents a digitally-variable resistor. Choose R1 and R3 so that V1's range is from slightly below Vbe to slightly above Vbe + ImaxR, where Imax is the maximum LED current desired. For example: Suppose V=5 V, that R2's total resistance is 10 KΩ, that R is 15Ω, that Vbe is 0.7 V, and Imax is 25 mA. Let RT = R1+R2+R3. Now R3/RT = Vbe/V = 0.7/5 = 0.14, and R1/RT = (V - Vbe - ImaxR)/V = (5 - 0.7 - 0.025·15)/5 = 3.925/5 = 0.785. Thus R1+R3 = 0.925·RT, whence 0.075·RT = R2 = 10 KΩ, giving RT = 133 KΩ, R1 = 105 KΩ, and R3 = 19 KΩ. With these R1 and R2 values, each digital pot step should give a change in LED current of 25/256 mA, or about 98 μA.)
[Edit: When V1 is set to less than VBE, no current will flow through the LEDs. That is, to turn off the controlled LEDs, set V1 to VBE or less.]
PWM with RC filter:
It may be worthwhile to experiment with using a PWM-driven low pass RC filter to supply V1, possibly avoiding need for buffer amplifiers and digital potentiometers. See eg “Arduino’s AnalogWrite – Converting PWM to a Voltage”
by Scott Daniels at provideyourown.com, and also see the filter-calculation page it refers to. You might need an oscilloscope to verify the design and its quality of results, and might need to use several RC filter stages in a row to adequately filter out ripple, but it can be done, at the cost of slower response to control changes.
Transistor-power example calculations:
Letting VCE, ICE, VBE, and IBE represent collector-to-emitter and base-to-emitter voltages and currents, transistor power dissipation is VCE·ICE+VBE·IBE. Because VBE·IBE is likely to be sub-milliwatt, we ignore it in following, taking P ≅ VCE·ICE.
In the LED-driving circuit, VCE = V – VLEDs – Vsense, where VLEDs is the series voltage across the chain of LEDs the transistor controls, and Vsense is the voltage across the sense resistor (ie, across R1 or R2 in the top figure).
In general, it is a good idea to keep Vsense small (under a volt) to allow a wider compliance range – ie, so that LED current is the same over a wider range of variation of supply voltage V. Thus, the approximation VCE ≅ V – VLEDs is reasonable.
Here is a concrete example: Suppose we have eight LEDs in series, and they are white LEDs with about 3.6 V forward drop at 20 mA. [LEDs of different colors may have different drops; eg see LED color chart at oksolar.com.] Then VLEDs = 8·3.6 V = 28.8 V. We need V(BR)CEO > V > VLEDs + VBE + Vsense, where V(BR)CEO = collector-emitter breakdown voltage (which is 40 V min. for 2N3904 or 2N2222). Allowing a volt for Vsense and 0.7 V for VBE we have V > 28.8 + 0.7 + 1 = 30.5 V. Let's suppose V=32 V. Then P < (32–28.8)·0.020 W = 64 mW. Thus a small general purpose NPN transistor will work, for example a 2N3904 (rated at 350 mW to 1 W, depending on package, before derating for ambient and heatsinking) or a 2N2222 (similarly rated).
For a second example, suppose VLEDs = 8·1.7 V = 13.6 V (for, eg, eight infrared LEDs at 50 mA) and V=32 V. Then P ≅ (32–13.6)·0.050 W = 920 mW, so a larger (and heatsinked) transistor would be needed. Or, V could be decreased, say to 16 V, giving P ≅ (16–13.6)·0.050 W = 120 mW, allowing use of a small transistor.
For a third example, suppose eight LEDs are paralleled (rather than seriesed), that VLEDs = 2.0 V at 20 mA, that Vsense is about 0.4 V at desired operating point, and that V=5 V. The transistor will need to drop 5-2-0.4 V = 2.6 V at 160 mA, which is 416 mW, probably large enough to require a heatsink. [Note: if LEDs are placed in parallel and driven by a single transistor, some of them probably will be dimmer than others; “current hogging” may occur in some of the LEDs, making them brighter than the others. However, many cheap flashlights connect LEDs in parallel without individual current control.]