# How to achieve constant current for LED when voltage is variable in MCU

I am using STM8S003F3 to drive 1 RGB LED. Link of RGB LED :- http://in.element14.com/broadcom-limited/asmb-mtb1-0a3a2/led-hb-rgb-0-09w-plcc-4/dp/2401106

To power the microcontroller and LED I am using Lithium polymer battery whose specs are 3.7V and 300mAh.

The voltage at full charge is 4.2V and it starts dropping with discharge percentage and drains at around 3.1V. The input voltage at MCU will drop correspondingly and the output voltage at the GPIO will also drop.

Value of Limiting resistor for LED at 4.2V.

R = (4.2-3.1)/0.02 (20mA) = 55 ohm

When the battery discharge the voltage will drop, then the current going through LED will be less, hence it will get less brighter.

At 3.3v

I = (3.3-3.1)/55 = 3.6 mA

The led will not be visible and will be dull.

How to maintain constant brightness (i.e 20mA) even with drop in voltage?

One Solution is to use LDO which will maintain constant voltage and hence the current will be stable. But as I have very less space in circuit and due BOM cost, I am hesitant to use LDO.

• Use a more efficient LED that is bright at 3.6mA – Misunderstood Mar 17 '17 at 21:05
• Any Link or suggestion for the Part number of LED? – RS System Mar 17 '17 at 21:06
• What color, case style, and budget? – Misunderstood Mar 17 '17 at 21:24
• Use this circuit, but replace R2 with two ordinary diodes in series. electronics.stackexchange.com/questions/281359/… – mkeith Mar 17 '17 at 21:32
• I'm betting you can find a brighter LED at about the same cost for the one you are using now. – Misunderstood Mar 17 '17 at 22:02

Yes, this is a problem. I have had to deal with it before with blue LED's on single cell lithium battery systems. In my case, I did have a regulated 3.3V available, but I wanted to drive the blue LED directly from VBATT without varying brightness. Anyway, here is how to fix (or improve) it.

simulate this circuit – Schematic created using CircuitLab

Voltage at base will be relatively fixed because of the two diodes. So the voltage at R3 will be relatively fixed. So the collector current will be relatively insensitive to VBATT. You can adjust R3 to adjust the current in the diode. R3 will have approximately 0.6V across it. So the current through D3 will be approximately 0.6/R3.

Note that Q1 is not operating as a saturated switch. This is a linear, analog circuit. D1 and D2 could be in a single SOT23 package to save space.

• This is a very nice solution, but it's probably good to point out that because there is 0.6 V across R3, there is then 0.6 V less for the diode, and then likely 0.6 more for the transistor since it's in its linear region. Vf for OPs LED seems to be 3.1 volt, so I don't think this circuit will work as-is in his case. – pipe Mar 17 '17 at 21:54
• Hey, @pipe, in practice, the circuit works pretty well. If you compare it to what the OP is doing now, it will maintain a much brighter LED down to much lower voltages. The BJT will eventually go into saturation when the input voltage is low, so, no, there will not be 0.6V from collector to emitter. – mkeith Mar 17 '17 at 21:59
• OP may need to use a smaller R3 if 20 mA is really desired. – mkeith Mar 17 '17 at 21:59
• Aah, good point, my upvote was justified. :) – pipe Mar 17 '17 at 22:06
• Could you explain why the BJT would go into saturation when the input voltage is low? I imagined it would be the other way round. – TisteAndii Mar 17 '17 at 22:13

OK. You want a solution which does not use extra active parts. Challenge accepted!...

simulate this circuit – Schematic created using CircuitLab

Output a PWM on a microcontroller pin. Your microcontroller has an ADC. Use it to measure voltage on R1 here. Adjust PWM according to ADC reading to ensure constant current, essentially implementing feedback loop in software.

Bonus: intensity can be dimmed.

If L1 has high enough value depending on PWM frequency, you get a crude buck converter, which has higher efficiency than simple resistive drive. In this case reduce R1 value.

Alternate solution: remove L1, C1 and simply adjust PWM current depending on battery voltage, measured by ADC. This also ensures constant brightness, but micro's output current rating may not be enough.

• How do you measure battery voltage if there is no regulator or reference? – AngeloQ Mar 19 '17 at 0:41
• @AngeloQ, I guess we don't know if the micro has an ADC. But quite a few micros have an internal reference and ADC. – mkeith Mar 19 '17 at 7:11
• @mkeith the part (STM8S003F3) has an ADC but no reference channel as far as I can tell. Since OP is apparently running the MCU directly from the battery (no regulator) I don't think battery level sensing can be done. – AngeloQ Mar 19 '17 at 12:59
• Hm, I had checked it had an ADC but not a reference... – peufeu Mar 19 '17 at 13:07
• I see. Well, there is a way to still sense the battery voltage if you are willing to add an external reference. What you do is feed the external reference to the ADC input. Then you reverse the calculation. In other words, VADC / VBATT * 1023 = ADC_RESULT. Then solve for VBATT, since you know VADC. But the OP needs to have some kind of epiphany first. – mkeith Mar 19 '17 at 16:19

As you mentioned, using a regulated voltage source for the LEDs is one way to do it. There are some very small and inexpensive low power LDOs that might work. There are other methods, but probably not much that will take up less space than an LDO. You could use a Zener and resistor to provide regulated voltage, but it won't be as efficient, and still probably won't use much less space than a small LDO. To make that more efficient you could add a transistor to do voltage following, but again the footprint will grow.

I doubt you could do anything smaller or cheaper than using something like this LDO.

If you are doing an RGB LED, then it sounds like you're already feeding the LEDs using a PWM signal. (Quick scan shows this MCU can do 4 channels of PWM?).

The absolutely simplest HW solution would only need 2 resistors but take a bit of SW work. Basically, 1) set the LED current limit resistors for the lowest battery voltage, 2) measure the battery voltage with the ADC, and 3) adjust the PWM so that the duty cycle maintains a 20 mA max average no matter the battery voltage.

So you get duty-cycle = Idesired / ((Vbatt - Vled) / Rled)

Example for 4.2 Volts and your 3.1V led and 10 Ohm resistor:

duty-cycle = 20 mA/ ((4.2 Volts - 3.1 Volts) / 10 Ohms) = 18% duty cycle

simulate this circuit – Schematic created using CircuitLab

• You have used regulator in your circuit, that what I don't want to use. – RS System Mar 18 '17 at 15:50
• The regulator is not essential to this scheme. The point is to measure the voltage and compensate for the varying brightness by adjusting the duty cycle. So when VBATT is low, you would use a higher duty cycle. When VBATT is high, a lower duty cycle. – mkeith Mar 19 '17 at 7:09
• mkeith is correct. I did not mean "put a regulator in". I am showing that this simple scheme 1) requires measurement of battery voltage, 2) leakage current through the divider resistor would be an issue (use high value R), 3) you need some sort of voltage reference for your ADC. For ADC vref, you can a) use your regulated voltage if using a VREG, b) use an internal Vref if the MCU has one, or c) use an external Vref. Also with this scheme you need to consider the peak current. If the PWM turns 3 LEDs on same time, that's 300 mA peak at 4.2V. All designs have some sort of trade-off . – Vince Patron Mar 19 '17 at 18:54

## UPDATE & Recommendations

This solution I believe will give you more than 7 hours with a 300mAh battery. Likely a lot more.

The LEDs are rated at 20mA but the max is 50mA. You could probably run the LEDs at 40mA for 7 hours on 300mAh. I do not think even 20mA will be necessary with the Cree LEDs.

Because the green will be on when the battery is fully charged, green's higher forward voltage will be less of an issue. Both amber an red have lower forward voltages.

The green max forward voltage (Vf) is 4.0v. My experience with Cree is that the forward voltage is usually below typical. You must be aware if you get a green LED with a 4v Vf, it's not going to work when the battery discharges to 4.05v. The datasheet is not that clear. I has a peak max current also. The graphs of Vf shows Vf to be much less at 20mA and you probably can driver it at less than 20mA. I would not worry about it.

The price on an Amber Cree LED at Digikey is:
And Digikey can always be beat.

The LED driver is a constant Current source so no limiting resistor is needed. No matter the battery voltage, the LED will get the same current.
This driver is essentially a dynamic resistor that changes its value based on the battery voltage to provide exactly the desired current.

The discreet 20mA LEDs with sufficient flux are 2.7 x 3.0mm

The LED driver is smaller than one of the LEDs in an SOT-23 case.

The LED Datasheets
Cree CLM1B 50mA Red Amber
Cree CLM1B 20mA Green Blue

The Micrel (Microchip) 30mA MIC2860 is an inexpensive, very small, and simple linear LED driver in a 2.0 x 2.0mm footprint with two outputs. Probably costs about the same as your RGB LED.

The MIC2860 provides the highest possible efficiency by
eliminating switching losses present in traditional charge
pumps or inductive boost circuits. It features a typical
dropout of 52mV at 30.2mA per channel. This allows the
WLEDs to be driven directly from the battery eliminating
switching noise and losses present with the use of boost
circuitry.

Would replace the resistor.

Takes the same real estate as a SOT-23 transistor or diode.

The changes are to replace the RGB with 3 Cree CLM1B LEDs and replace the 56Ω Resistor with the Micrel Driver.

The Cree LEDs are Binned by Flux. That give you some flexibility when buying. Each color has its own bins so you can adjust the luminous flux by the part number.

Each row is a bin code used in two characters of the part number.

Because mcd is a Photometric quantity it is adjust for the human eye. You can get all LEDs with the same range of brightness.
If you buy all colors in the VA bin code the all colors have the same brightness. Red and Amber bins are identical.

Is there a reason you are using the STS STM8S003 Micro?

I think it is a little over kill and you do not need that many pins.
It is a fine device and the power is not bad.
I'm not up to date on all the processors out there.
I have always like Atmel AVR for apps like this.
The 14 pin ATtiny441 would do this job very well.
It would save real estate. The power savings would be negligible as both micros will average less than 1mA.

I am currently looking into the ATtiny817 which is a new part very similar to the Tiny441. Except the 817 has a DAC. I am going to see how well the DAC can control an LED Driver's analog current adjust and or switching frequency.

I was originally thinking a DAC could help you with the variety of luminous flux on the RGB LED. You could use the DAC to drive the Micrel Driver's current adjust pin with a different level for each color.

## End of Update and Recommendations

So the LED must be seen across a well lit room.

ASSUMPTIONS

There is only one LED turned on at a time.
LED color is controlled by 3 MCU pins connected to the color cathodes, sinking from a single 55Ω Resistor in the common anode path.
Both real estate and cost are major criteria.
Cost of the RGB LED is about \$0.20. Battery Discharge Rate is less than 0.2C.

THE PROBLEM

The 55Ω resistor.
Dissipates 1.1 Watt @ 20mA
Insufficient luminous flux at low battery @ 3.6mA

Discussion

The forward voltage of the LEDs is a huge factor after luminous flux.

Luminous flux and Forward Voltages

• Red: 540mcd 2.1v
• Green: 1600mcd 3.1v
• Blue: 350mcd 3.1v

The RGB is an economical and space saving way to get multiple colors.

The problem color is blue. Candela is a measurement of light based on the sensitivity of the human eye to each wavelength of colors.

Lime green (555nm) is the color the eye is most sensitive to according to CIE (Commission Internationale d'Eclairage). All other color sensitivities can be specified as a percentage or ratio compared to 555nm Lime Green.

Blue is 7.7x less sensitive and Red 3.4x.

If only two colors are needed then Green and Amber or Red and Amber would be the color combinations of choice.

Red LEDs are AlGaInP/GaAs
Blue LEDs are GaInN
Green is a deep blue GaInN LED pushing a green phosphor
Amber can be either a red or blue LED pushing phosphor.

AlGaInP/GaAs has a lower forward voltage than GaInN.

Cyan would be better than blue
Lime green better than green.
Amber and Orange better than Red

POSSIBLE SOLUTIONS

Add two resistors and put then in the cathode path
The red can be recalculated with its lower forward voltage
Green current can be reduced at least 50%

Resistor is actually 56Ω standard value.
Current 3.1v LED 19.6mA

Current Power per Color

Red  158mW 37.5ma     0mcd
Green 83mW   20mA  1600mcd
Blue  83mW   20mA   350mcd


Max current is 25mA, @ 55Ω
Red forward current = 37.5mA
LED burns out mcd = 0.

Single Resistor must be recalculated for Red

Two possible values for Red resistor, 82 and 100.

Red LED

 82 25.6mA 108mW 690mcd
100 21.0mA  88mW 570mcd


Green LED

 82 13.4mA  57mW  1070mcd
100 10.0mA  46mW   800mcd


Blue LED

 82 13.4mA  57mW 235mcd
100 10.0mA  46mW 175mcd


Looking like a new RGB will be needed. For sure if blue is required and 235 mcd at full charge is insufficient.

If Red and Green are all that is needed, 82Ω is the only viable resistor. And at that red is being pushed over its max forward current.

I do not know where to go from here mainly because I do not know if blue is needed or if the current RGB LED is actually going to work.

It is likely the cost will increase and the PCB will get bigger.

You need to run the numbers with min and max, not typical. There is nothing typical about LEDs.
Red Forward Voltage range is 1.8v - 2.6v
Green and Blue 2.8v - 3.6v

I was hoping this would lead to a point where I would introduce another solution but things when down hill. The red will not work at 56Ω

Minimum next attempt is separate resistors.

PWM may be necessary. It is possible the micro can blink the LEDs at a fast enough rate. Not a good way to go.

Driving LED with a resistor in a battery powered circuit is seldom a good idea.

But an LED driver may be necessary. The current would need to be adjusted for each color used.

Another solution would be to raise the capacity of the battery and raise the cutoff discharge voltage.

Possibly you may have to use discreet LEDs rather than an RGB.

You should look into using cyan and amber colors. The may be multi-color LEDs other than RGB.

When selecting an LED you must test it in a well lit room and find the minimum mcd that will work. Start with blue.

An LED driver would most likely be the right solution.

Gives you the flexibility to double up two LED with less luminous flux, or just use one output.

• That's a very bright LED and it might be hard to notice changes in intensity. OP is talking about 20mA. I think regardless of how efficient an LED is, going from 3.6 to 20mA will cause a visible change. – AngeloQ Mar 17 '17 at 21:28
• Problem is, he's not willing to spend on an LDO. – AngeloQ Mar 17 '17 at 21:29
• @AngeloQ his main concern seemed to be real estate. No a 16mA change on this 50 lumen 750mA LED is not visible. – Misunderstood Mar 17 '17 at 21:34
• I read it that way first also, but in rereading, OP wrote 'and due BOM cost', so I'm not sure what the critical factor is. Are you talking about your Cree LED? I'm assuming OP is talking about a generic low power indicator LED. – AngeloQ Mar 17 '17 at 21:40
• @AngeloQ Yes I understand that, I manufactured a product for 20 years with an indicator LED. Never changed the resistor over all those years but it sure did get brighter. A battery powered device should have an efficient LED. On Digikey most were between 40 mcd and 150 mcd, then there was one 400 mcd which was 3 cents (qty 1) more than the cheapest. He just needs it to be efficient enough to be seen @ 3mA. – Misunderstood Mar 17 '17 at 21:51

well, a few ways of doing it:

1) put a sense resistor there. you can use the voltage over the sense resistor to turn on / off the led. this can be done via a comparator, or adc.

2) the first approach but plus an inductor with the led. this is essentially a dc/dc converter;

3) put a (slow) light sensor on the led and pwm the led to maintain a constant output from the light sensor.

...