Screen Brightens when Faders are Moved - Teensy 4.1


Well-known member
Hi all,

I've got a fader and LCD screen and it works well. I added a light sensor, and now when I drag a fader, the screen brightens.

There is no code that connects the two together. The sketch is very large and would not be easy to share.

If I disconnect the light sensor, the screen does not brighten when a fader is dragged.

I can't figure out what's going on.

I'm attaching the schematic and if anyone has any suggestions I would appreciate it.

I did have a thought to use a voltage regulator that I already have on board to isolate the light sensor, but I don't know if that would do anything.

Thanks for any thoughts,


Interestingly enough, if I leave the light sensor connected and simply disable the line that changes the backlight level, there is no screen brightening when faders are dragged.

Disabling this line:

analogWrite(BackLightPin, BackLightLevel);

And the problem's gone.

Of course, then the screen doesn't automatically brighten or dim according to ambient light either.

Thanks for any thoughts,

You're driving the LCD backlight (LEDs) from a GPIO pin directly. Backlight LEDs tend to need more current than a GPIO pin can provide, so anything happening in the same circuit will affect the current to the backlight. If the backlight is white, the 3.3 volt level you supply to the backlight LEDs is not above their forward drop, so the voltage is limiting the current flowing through the LEDs and is stopping the LEDs from burning out. Any small change in that voltage level – which is expected when pins in the same supply group change state! – will then directly change the current and the observed brightness, because LED light output depends on the LED current.

What you should do, is use a transistor as a switch to control the backlight.

If the backlight is on when the pin is high, it is connected to the LED anode, and you need a "high-side switch" transistor, a PNP BJT or P-channel enhancement mode MOSFET.
If the backlight is on when the pin is low, it is connected to the LED cathode, and you need a "low-side switch", an NPN BJT or N-channel enhancement mode MOSFET.

Depending on which, I would use either a PNP BJT, or an N-channel MOSFET, plus two or three resistors. One resistor limits the base current or gate switching current spike, and the other limits the current to the backlight LEDs. With the N-channel MOSFET, I'd also add a 10k resistor between gate and ground, to ensure the backlight is off when the Teensy pin is an input, for example during startup.

If you have 5V available – and you do: VIN –, and the backlight is connected to the LED anode, I'd use that 5V (and a PNP BJT like BC857,235) instead of the 3.3V for the backlight. If the voltage drop over the LEDs is V_L, the desired current in amperes is I_L, and the voltage source is V=5 V, the needed resistance is R = (V - V_L) / I_L. White LED forward drop is about 3.3V, and if the datasheet says the backlight maximum current is say 20mA = 0.020 A, a suitable resistance for 5V would be 85 ohms. Choose the next larger standard resistance; 100 ohms would limit the current to 17 mA. This way, you can also use the PWM output on pin 8 to control the brightness of the backlight. I'd use a frequency around 1000 Hz, because I despise flicker.

If the backlight is connected to the LED cathode, you'd need voltage level shifters (say, TXU0304 and TXU0102) to translate the data signals between 5V and 3.3V logic levels, and power it from 5V (VIN).

(I haven't considered your circuit at all beyond the backlight. You might consider using different colors for signal and power lines to make reading the schematic easier.)
Hi Nominal Animal,

Wow! What a response! I really appreciate you taking all that time to share so in-depth!!

Your solution seems very intricate and adds a lot of parts to the project. What about if I simply add another voltage regulator just for the LED backlight, and derive current from VIN. Wouldn't this effectively isolate the LED backlight from the Teensy GPIO current?

Hey I really appreciate your time and expertise. Many thanks!!

Just an update - I'm using the ResponsiveAnalogRead lib (who isn't?). I've dinked around with the settings for a couple of hours and found a good set of numbers that suppresses the screen flicker while still allowing a reasonable sensitivity on the light sensor.

I'm not married to this solution because it does limit the light sensor sensitivity range. It works pretty well, but I think it could be better. And I'm still intrigued by Nominal Animal's ideas and also the concept of adding a dedicated voltage reg just for the LED backlight, to see if that would allow me to use the full range of sensitivity the light sensor offers.

Oh I didn't mention, I've already got 5 buttons which have 3 LEDs each (RGB)! And I'm using a dedicated VR just for them. So I wouldn't want to use the same VR for the backlight as the 15 LEDs already hooked up to it.

Thanks again for any other ideas/support. This forum is always amazing.

Your solution seems very intricate and adds a lot of parts to the project.
No, just a single three-pin SOT-23 part, and two or three resistors. You can dead-bug this, i.e. solder directly to wires, and put heatshrink on top to keep it well contained.
(SOT-23 (SOT23-3) is just 2.9mm by 1.3mm body, with one leg in the middle of one side, and two legs on the opposite side with 1.9mm between them. Not hard to solder by hand, even though it is so small. Just take care with static charges and don't burn them when soldering. I keep BC847C,215 (NPN BJT), BC857C,215 (PNP BJT), and NX138AKR (N-channel enh. MOSFET) in stock, as they're suitable for that and for putting on own boards made at JLCPCB or PCBWay –– I bought 100 of each from Mouser for the price of couple of cups of coffee.)

Is the backlight on when Teensy pin 8 is HIGH, or when it is LOW?

You can get ten Nexperia BC857C,235:s from Mouser for less than 0.70€ (if you fill the free-shipping limit of 50€/$60 in parts). That's total, not apiece. I recommend against ordering ICs from eBay, since a lot of sellers there sell rejects and fake ICs, and it's difficult to verify what you got. My local components store (Partco) sells them for 0.15€ apiece; if you have a local parts store that sells to private customers, I recommend you support them.

What about if I simply add another voltage regulator just for the LED backlight, and derive current from VIN.
Uh, regulator would be bigger, and need input and output bypass capacitors, wouldn't it? And for constant LED brightness, a current regulator (as opposed to voltage regulator) would be better.
If it was under 10mA, LM334 would work. I bet the backlight wants much more than that, on the order of 50 mA.

Do you have a datasheet or link to the display you're using?

Typically the BL pin has no current limiting at all, or allows way too high a current (when sufficiently high voltage is supplied to BL, say 4.0 V or more).
With a resistor limiting the current –– between the voltage source and the LCD module BL pin ––, any slight change in the 5V or VIN voltage would cause a minimal, non-perceptible, brightness change in the backlight intensity. As it is, the 3.3V you supply to it is under the LED threshold voltage, so the LEDs themselves limit the current. But I'm not sure until I see its datasheet/manual.
Hi Nominal, thank you again for the clear response!

I actually already have a voltage regulator on the PCB, and it's good for 1A. So I see no problem with using it for the LCD screen instead of taxing the Teensy pin. No extra parts - just change a connection and it's done. Hopefully that would solve the issue.

Also, I think I'd need to see a schematic of what you are proposing - but I do not want to ask you to take the time to do that, as you've already been very generous with your time and knowledge.

Many thanks!

To drive LEDs, you do need to limit the current somehow. I fear that if you connect BL directly to 5V, it will burn out the backlight LEDs, unless the module contains a limiting resistor in itself.

Bipolar junction transistors or MOSFETs can be used for this purpose. Since you want to use PWM to adjust the brightness, I'd recommend a BJT. Depending on whether the BL pin is connected to the backlight led anodes (left below) or cathodes (right), you use a PNP or an NPN BJT:
I suspect the case is the left one, i.e. BL pin is connected to positive voltage to turn the backlight on.

To set R1, you need to know the approximate forward voltage of the LEDs, VIN (=5 V), and the current you want to drive the LEDs at. These are specified in the display module datasheet/manual/specifications, which you still haven't provided, so I cannot tell you any specific value. VIN must be about 1V higher than the LED forward voltage, because the BJT will drop some, and R1 the rest. If V_L is the LED forward voltage drop in volts, VIN is in volts, and I_L is the current in amps, then R1=(VIN-V_L-0.7)/I_L in ohms.

For example, if V_L is 3.3V and I_L is 40mA, then R1=(5-3.3-0.7)/0.040=25Ω. It will dissipate about (VIN-V_L-0.7)²/R1 watts (40mW), so a 1/16W or 1/10W resistor is sufficient (but higher power capability is of course okay).

Another example: V_L is 1.6V and I_L is 20mA, then R1=(5-1.6-0.7)/0.020=135Ω. It will dissipate about (5-1.6-0.7)²/135 = 54mW, so a 1/10W resistor is sufficient.

If the display module already contains a current-limiting resistor, you simply subtract its value from R1.

R2 is set based on the selected transistor current gain, hFE, and the GPIO voltage (here 3.3V). I would not use BC857C,215 for more than 50mA or so, and its minimum current gain is 400. Therefore, the base of the transistor may need 50mA/400 = 0.125mA for that PNP BJT to conduct. These figures are listed in the transistor datasheets. Higher currents typically reduces the voltage drop over the BJT a bit, but you don't want to draw too much current from a GPIO pin, only a few milliamps at most. If I is the current we want to limit to, and V is our GPIO voltage level (3.3 V), then R2 = V/I.
The smallest value of R2 I'd use would be 1kΩ, which limits the GPIO pin current to 3.3mA. Depending on the transistor hFE (and experiments!), I'd use 10kΩ, 6.8kΩ, 4.7kΩ, 3.3kΩ, 2.2kΩ, or 1kΩ, in that order of testing. On Teensy LC, 3.x, 4.x they correspond to 0.3mA, 0.5mA, 0.7mA, 1mA, 1.5mA, and 3.3mA.
Thank you so much Nominal Animal. It's actually amazing how incredibly smart you are with all this - wow!

I do have current limiting resistors in the design. Before I go the route you're suggesting, is it possible that simply using the voltage regulator off VIN with current limiting resistors, that this would isolate the LCD from the MCU and resolve the screen brightness variances?

I am humbly grateful for your time and expertise.

Me hobbyist only. I can't even tell if you're being kind, or sniping at me. ;)

I do have current limiting resistors in the design. Before I go the route you're suggesting, is it possible that simply using the voltage regulator off VIN with current limiting resistors, that this would isolate the LCD from the MCU and resolve the screen brightness variances?
I don't think so, because powering the LCD backlight from a GPIO pin is the key problem, I believe.

If you use a multimeter in milliAmps mode, using its probes to replace the wire from Teensy pin 8 to display BL pin, you'll see how much current is sourced/sunk from the Teensy pin.
As you can see from the Teensy Technical Specs Comparison Table, 10mA is the recommended maximum.
I bet your module is drawing more, say 30mA perhaps?

(However, I could be wrong, because you still haven't described exactly which LCD module you're using, so I could check. I can't find any LCD modules with the 9-pin pinout you have, to make an educated guess. Most directly connect the backlight pin to the LEDs, some have current-limiting resistor; and only very few rare ones have a BJT or MOSFET making it safe to use a GPIO pin for it.)

The BJT transistor and R2 limit the Teensy pin current draw to much less, to well within safe limits. The BJT transistor itself acts like an amplifier, letting much more current flow across it (from VIN to backlight LEDs), but only when the Teensy pin is high. It is how one safely drives higher-current LEDs from a GPIO pin, with the ability to PWM its brightness.

(There are also circuits using two e.g. BJTs for a constant current supply, PWM'ble using a third BJT or MOSFET. These keep the LED brightness the same even when the temperature changes or VIN varies, as long as the supply is at least one volt higher than the LED forward voltage.)
Hi Nominal - that makes a lot of sense!

I had this LCD custom made by a company in China. That's why it has 9 pins - I wanted the extra "read" pin that most LCDs lack.

I have reached out to the company to ask their engineers if the LCD already has current limiting resistors installed.

I take very seriously your suggestions and your wisdom - please don't think otherwise - and I also greatly appreciate the time you've taken to be so clear with me.

Truly, thank you.

I will post back further here, and I very well may go ahead with your solution.

Again, thank you so much.

Oh by the way - I was totally not "sniping" at you! I'm genuinely appreciative of your thoughtful support. And you are the only one to respond, so I'm even more grateful.

Regarding your comment that I'd be driving the LCD backlight from a GPIO pin - well no. The VIN pin is special; it's where the 5V from the USB is brought out. So while technically yes I'm "using a GPIO pin" - in reality it's a parallel circuit so it's not being driven from the Teensy, if that makes sense. At least, that's my understanding of it.

Thanks again and as I said I'll post back with what the manufacturer says.
Regarding your comment that I'd be driving the LCD backlight from a GPIO pin - well no. The VIN pin is special
Your schematic shows Teensy pin 8 connected to the LCD module BL pin.

There are several ways that BL might be connected:
1. Direct connection to backlight LED anodes, cathodes to ground, optionally with a current-limiting resistor in between.
2. Direct connection to backlight LED cathodes, anodes to module VCC, optionally with a current-limiting resistor in between.
3. Connected to a BJT base or MOSFET gate controlling the voltage from VCC to the LEDs with a current-limiting resistor.
4. Connected to a BJT base or MOSFET gate controlling a constant current source or sink to the LEDs, powered from the module VCC.
5. Connected to the display controller that provides a current-controlled source to the backlight LEDs, powered from the module VCC.
6. Connected to a separate LED backlight constant current IC, powering the LEDs from the module VCC.

My favourite display modules from BuyDisplay expose the backlight LEDs using LEDA and LEDK pins, with the LEDs in parallel. The voltage drop is typically 3.2-3.4V, and the typical current depends on the size of the module (the number of LEDs) but is between 30mA and 120mA. If you put 3.2V or more across the LEDA and LEDK pins without limiting the current, the backlight LEDs will burn, and the module unusable. I don't want to give you advice that will cause you to accidentally destroy your display module!

Several of the BuyDisplay modules that come with a board and use ST77xx controllers, like this one, actually contain an NPN BJT (marked J3Y) connected to the BLK pin, plus the two resistors (R1=10Ω, R2=1kΩ) as in my above diagram on the board. R3=10kΩ is a pull-down resistor from BLK to ground, so that the backlight is off when the BLK pin is not connected. The last component on the board is a supply bypass capacitor, helping stabilize the VCC to the module.

Connecting the display module VCC to your externally regulated 3.3V (instead of Teensy 3.3V) should be safe. It might fix your brightness issue, but I suspect not.
Connecting the display module VCC to 5V/VIN is not safe, unless the manufacturer/vendor explicitly said it is. The abovelinked display module would fry, for example.

(The pinout of that BuyDisplay module is similar to your module, except that the pin named SDA is actually both MOSI and MISO. It's a bit annoying to deal with, but the simplest option is to use a say 10kΩ resistor between SDA and MOSI, and SDA directly to MISO. If you use the same SPI bus for other stuff, you can use a 74AHC2G125 or 74LVC2G125 to detach those MOSI and MISO from the SPI bus whenever the display CS is high, so that MOSI and MISO are not tied together through that 1kΩ resistor for other devices. The annoying part is that to receive data from the display module, you must switch the MOSI pin from SPI to GPIO (input) – or use a Schottky diode instead of the resistor and remember to write zeroes. I assume you didn't want that, and desired one with separate MOSI and MISO pins.)

Can you tell us what components there are on the display module board? Could you post a picture? Comparing to the backside of the abovementioned display module may be useful.
Hi Nominal, thanks so much. I was trying to attach the PDF datasheet but I can't seem to find a way here.

So I'll attach several images of the data sheet that I hope will be relevant.

Thank you so much for all your incredible time and attention. You are amazing.


Screen Shot 2023-11-01 at 7.20.45 AM.jpg
Screen Shot 2023-11-01 at 7.20.35 AM.jpg
Screen Shot 2023-11-01 at 7.21.09 AM.jpg
Screen Shot 2023-11-01 at 7.21.43 AM.jpg
Screen Shot 2023-11-01 at 7.21.53 AM.jpg
Also, since this was a custom screen, I'm in talks with the manufacturer over these issues, and I'll post back when they have responded.
Excellent! Those provide all the information we need!

(I have designed one similar board like the one you have, for someone who wanted to use BuyDisplay ER-TFT028A2 on a Seek Reveal Pro (replacing the TM024HDH71 display), using the ILI9341 controller (yours uses ST7789; both common). The ER-TFT028A2 is my favourite display module, being 2.8", cheap, IPS panel, configurable connection, Tear Effect pin, well documented. My board looks funky, because the two flat flex cables come in on top of each other, and one is folded at 90 degrees, with the connectors positioned carefully to allow the existing flex cable lengths to fit just perfect. I never found out whether it was useful or not, though: the discussion is here at the EEVBlog Forums. There, too, the LED backlight was the final open question!)

From your board picture, you can see that the BL pin is connected directly to pin 33 on the display module, eighth pin counting from left. This is the common anode pin A on the display module Flat Flex Cable, per the datasheet pages you shared. The three pairwise LED cathodes are all connected to ground – they have to be, or the backlight would never work at all. (On the other side of the board, the display module is connected to the board using 3M double-sided tape, and there is not enough room there for components.)

Thus, the BL pin is the backlight LED anode (+) pin. Connecting it to 5V will destroy the LEDs, because there is no current limiting at all. The forward voltage of the LEDs (in parallel) is between 2.8V and 3.4V, and therefore any slight variation in the 3.3V you're currently feeding to it will hugely affect its brightness. Finally, if I read your schematic correctly, and Teensy pin 8 is directly connected to the BL pin on the module, you're trying to drive the up to 120mA backlight from a Teensy I/O pin!
You are right on all accounts!

Since these were custom made screens with PCBs, I reached out to the manufacturer with these issues as well. Here is their proposed solution so far:

Screen backlight solution

It is recommended to place the system power supply interface on the main PCB board without powering through the Teensy board. It is also recommended not to directly supply 5V to the Teensy board. Instead, use DC-DC to step down the 5V to 3.3V and supply it to the Teensy board. At the same time, add at least 2*22uF. Capacitors are used to eliminate power supply ripple, or power supply fluctuations caused by changes in system load.

At the same time, our screen backplane will change the constant current drive screen backlight. You can output a PWM signal on the original BL pin to control the brightness of the screen. The frequency of PWM is preferably greater than 20khz and the maximum is not more than 100khz.

Also here's a pic of the proposed changes to their PCB board:

The PCB board they made for me had NO electronics on it! LOL. I thought I was getting this all done and ready to hookup, and merely they routed the LCD cable through the board and attached a cable and called it a day. But I chalk this up to my poor communication with them; they are a reputable company. They just didn't understand what I needed; my fault.

From what I understand they are saying they are adding a constant current driver chip - over my head. But somehow it will ensure no runaway amps sneak through and wreck the screen. Now whether this fixes the screen brightening/dimming, I don't know. As I mentioned, I have actually solved the brightening/dimming issue through the AnalogRead library, changing some parameters, but this seems a goofy solution and doesn't address the real issue: I didn't know what I was doing and hooked it up poorly. I'd rather hook it up right.

I have asked the manufacturer to mark up my schematic and tell me exactly what they are trying to say I need to do; I'll post back the updated schematic if/when they do that.

I can't thank you enough Nominal; I so appreciate your expertise.
You should probably tell them you do have 5V also available; there is no need to power the backlights from the 3.3V supply.

Here is what I would suggest, as a hobbyist myself (click to embiggen):
I consider the above schematic to be obvious and well known, in the public domain.

There are two new separate pads, LED_VCC (=VIN) and LED_GND. They form a separate power circuit from the display, so you might wish to use normal wires and through hole pads for them. If you use a flat flex cable, note that the current on each pin is up to 120mA; you might wish to use a pair of pins for each then, depending on what FFC you use between Teensy and this module.

There are five added components:
  • A 1 kΩ current-limiting resistor on the BL pin.
    This makes sure only a few milliamps (3.3mA) is drawn from the Teensy pin 8.
    Typically the current is less than a milliamp, though.
    It only dissipates a few milliWatts, so any resistor will do; and it doesn't need to be precise, either.
  • An N-channel enhancement mode MOSFET, Toshiba SSM3K345R,LF.
    This acts as a low-side switch for the LED backlight, and dissipates some of the heat.
    Exact amount of heat depends on the actual LED forward voltage and LED_VCC as well as the LED current; but I'd like it do deal with up to 400mW without problems.
    (If you use some other MOSFET, you may need to adjust the LED current limiting resistance below as well.)
  • LED current-limiting resistor of 13Ω.
    This dissipates something like 190mW (P=I²R) at 120mA current, so I would actually prefer splitting it into two 0805/1206 resistors in series or parallel, say two 250mW 26.1Ω ±1% thick-film ones in 1206 in parallel. (Even if one fails, the display will simply become much dimmer.)
    Lower resistances will yield higher LED currents!
  • An NPN BJT, Nexperia BC847C,235 or BC847,215.
    This handles just a few milliamps of current, and controls the voltage drop over the LED current-limiting 13Ω resistance, so that the LED current is linearly dependent on the voltage on the MOSFET gate and BJT collector (within a certain linear range, dropping to zero near 0.6 volts). Thus, the choice of the NPN BJT and N-channel MOSFET chosen, also affect the LED current-limiting resistance you need.
  • An LM4040 2.5V shunt voltage reference.
    This limits the voltage from the BL pin to 2.5V. The 1 kΩ resistor limits the current to within the range this reference can handle, allowing BL pin voltages between 2.5V and 5.0V to produce the same LED current. The shunt drops the excess.
At JLCPCB assembly service, SSM3K345R,LF (C146369) costs $0.21, the BC847C,215 (C8664) $0.02, LM4040B25FTA (C460725) $0.38, the 1 kΩ resistor is $0.01, and two 26.1 Ω thick film 250mW resistors (like C346129) are $0.01 apiece, for a total of about $0.64, including the LM4040-2.5. You can get the components from Digikey or Mouser, too, for around $1.50 or so.

The LM4040B25FTA is 2.5V±0.2%, i.e. 2.5±0.005V, which limits the fluctuation in the LED current to ±0.3mA; at most ±0.25% variance in current, which should be imperceptible.
Varying LED_VCC from 5.0V to 5.25V varies the LED current from 116.8mA to 118.0mA, so overall, we'd expect this circuit to yield a ±1mA constant current, regardless of fluctuations in the voltages. Dropping LED_VCC down from 5.0V will decrease the LED current, however.

(If you need a lower LED_VCC, then using LM4040-2.048V, and LED current limiting resistance of 9.2Ω to 9.3Ω, for example two 18.4Ω or three 27.7Ω in parallel, will give you that.)

I simulated this circuit in KiCAD 7 (ngspice engine) using two (IS=2.659E-20 N=2.63815 RS=8.14349) SPICE diode models in parallel; modeling a backlight that consumes 45mA current at 3.0V, 84mA at 3.2V, 105mA at 3.3V, and 126mA at 3.3V. Of course, since this is a constant current driver circuit, the actual forward voltages do not matter, as long as they are within the 2.8V and 3.4V specified in the datasheet at the 120mA typical driving current. Using the specified components above (except omitting the LM4040, and just ramping and PWM'ing the BL pin to 2.5V), the simulation gives the abovementioned numbers (117mA LED current), and PWM'ing seems to work fine even at 30kHz frequency (the pulse corners getting a bit rounded), in case you want to avoid flicker and possible PWM noise from components.

Now, many proper electrical engineers and designers will tell you the above is way overkill. To me, it is a cheap way to get a stable, well-controlled, high-frequency PWM'ble backlight circuit, based on a well-known voltage-controlled constant current N-MOSFET + NPN BJT sink. At $0.64 at JLCPCB for the added components, maybe 1.50€ at Mouser/Digikey in singles and much less in batches, I think it is worth it.

Another variant is to replace the LM4040 with a small microcontroller with built-in DAC (and slave SPI support), connected to the SPI SCK and MOSI (and perhaps MISO) lines, and changing the BL pin to backlight-CS, adding its own regulator from LCD_VCC to 3.3V to be used as a voltage reference and microcontroller power. Then, the 8-bitter could be programmed to produce not just constant backlight level (settable via SPI), but also backlight fade-ins and fade-outs and soft pulses for notification/effect, just by sending the corresponding command via SPI. The exact maximum DAC output value would be around 75% (2.5/3.3) or 62% (2.048/3.3), and could be programmed in Flash/EEPROM, so that Teensy telling "full brightness" would yield the exact same display brightness on different modules in case you manufacture several of these. Sure, that variant sounds like madness, doesn't it? But, for example an ATtiny414 only costs under 0.70€ in singles at Mouser ($1 at JLCPCB assembly), would draw about 5mA when running at 12-14 MHz, can be a SPI slave, and has an 8-bit DAC. A good linear regulator (30mA or more, with good stability!) with the bypass capacitors would likely cost the same! So, say a total of $2.50 in components (much less if you make many), giving you much more freedom with Teensy timers (since BL would become just another CS pin, asserted low when talking to the backlight ATtiny414, and not tied up with PWM generation). Food for thought!
I realized I forgot to post links to good articles on the web describing the constant current sink using BJT and MOSFET the above schematic is based on; with the LM4040 just very precisely limiting the backlight control voltage to 2.5V and thus the current over the LEDs. Apologies!

The main article is at Radio Locman, by Donald Boughton (International Rectifier company): Circuit achieves constant current over wide range of terminal voltages, specifically the MOSFET variant. I came across this circuit at EEVblog forums when a member referred to the Radio Locman article. The second schematic is excellent for when one wants a voltage controlled current source (say, driven from a DAC with an internal reference). As the control voltage needs less than a milliamp of current, I just plonked down LM4040-2.5 to easily cap the high voltage (and maximum current) to where the BJT and MOSFET still operate in the linear range at the desired maximum current. (As 3.3V is not enough to saturate the MOSFET+BJT, we do need to limit the voltage on BL to a precise value, to get a precise LED current.)

Typical issues and problems when using the aforementioned circuit (without the LM4040 shunt regulator to limit the control voltage) are discussed in this question, issue with constant current sink, at

While a separate voltage regulator could be used (via say a BJT or MOSFET high-side switch), 3.3V is too high a control voltage here, putting the MOSFET and BJT above their linear region. 2.0V to 2.5V is optimal for the control voltage here. (Using a normal voltage regulator instead of a shunt regulator here is problematic, because most linear regulators need more current (than a shunt regulator) to flow to keep the output voltage stable, plus they need additional components like supply bypass capacitors. A shunt regulator like LM4040 is pretty much optimal choice here, I think.)

It is also very easy to similate in LTspice, KiCAD, etc.; you just need to find the SPICE/PSPICE/LTSPICE models for the MOSFET and BJT you intend to use.

The shunt regulator will drop the excess voltage (3.3V-2.5V ≃ 0.8V) from the control (PWM) signal, as long as there is a suitable current flow (0.1mA = 100µA to 15mA). We're drawing the current from the Teensy I/O pin, so let's try to keep it below 5mA (10mA is the recommended maximum). We definitely should add a 0603/0805 resistor pads for a burden resistor parallel to the LM4040 (value between 2.2kΩ and 10kΩ; I recommend 4.7kΩ here), as explained in this Adafruit blog post: to ensure sufficient current (about 0.2mA to 1mA would be nice; 10kΩ gives you about 0.25mA, 4.7kΩ about 0.5mA, and 2.2kΩ about 1.5mA) whenever the BL pin is high, but the MOSFET has already switched to the new state. This current is on top of the MOSFET switching spike, which is less than 2mA in this circuit according to simulations. (The MOSFET gate acts like a capacitor, and only draws or sinks current in a "spike" whenever it switches; other than that, the MOSFET is a voltage-controlled device.)

Because I didn't model the LM4040 2.5V shunt regulator in my simulations, I forgot about that, sorry! The exact value (4.7kΩ being "best guess") would be nice to check in a practical circuit.
Me hobbyist, makes errors and forgets stuff.
Thank you so much Nominal for your mind-blowing, detailed, thorough, thoughtful and helpful replies! I'm blown away actually.

I will take your suggestions on board and see how to proceed. At the moment I'm speaking with the company's engineers - since they make the LCD and also they made the board, I thought I would ask their advice here too.

It's a drink from a fire hydrant for sure, and I'm not as technical as some here so it's a lot to take in, but I'm truly grateful for your time and expertise.
Apologies for spamming the thread, for the content firehose, and posting such annoyingly long posts, but here's the LM4048-2.048V (or any other 2.048V shunt voltage regulator that works in the 0.2mA - 10mA range)-based circuit, with component-by component explanation.

I am posting this only because I myself wish I'd seen something like this posted a few years ago, when I started trying to drive these small display backlight circuits, in my Teensy display projects. (I like to use Teensy 4, because of its high-speed USB, to add human-readable status information to OpenWRT routers and such. Instead of asking whether a non-technical person sees LEDs flashing, I can just add a small display, that shows the key statistics –– upstream connectivity, current throughput, etc. –– in readable form, maybe with a button that lets them switch between displays, and even turning it off when not needed. If you have elderly family members living in very rural areas with occasional issues in network connections, you know what I'm trying to solve!)

Reminder: this circuit is specifically designed by a hobbyist, for us hobbyists to use; proper EEs and PCB designers can make it even better.

The components are chosen to provide just under 120mA LED current, when the LED forward voltage drop is between 3.0V and 3.4V, and LED_VIN is between 4.7V and 6V. (This will work outside that range, with either lower display current, or generating more heat at the MOSFET.) The differences in forward voltage drop between different LEDs in different devices does not really affect the current passed through those LEDs.

The BL pin yields a nearly linear current control between 0.9V (although the LEDs will start emitting a tiny bit of light at about 0.6V) and 2.5V. Voltages between 2.5V and 6V on the BL pin produce the same brightness, as they are clamped to 2.048V by the shunt voltage regulator U1. The BL pin can be PWM'd at up to tens of kHz. The current draw on the BL pin stays under 5mA even during switching; steady-high current draw is about 0.5mA.

Because the signal is such low power, and the LED current so high, the grounds for the two are drawn separately, to indicate how one should wire it to a display module. Essentially, LED_VIN and LED_GND form a completely separate, high-current circuit, that should have a single point ground connection to the signal ground at the power connector, and have conductors/traces thick/large enough for the 120mA current. (It's not that much current, but doing it correctly will give you a much more robust and reliable system, avoiding "signal ground lift" (where the inherent resistance in the ground traces and wires causes ground currents to lift the observed potential) that can be annoying to deal with in a circuit, especially if you have any analog signals like ADCs or potentiometers.)

Q1 is the main switching N-channel enhancement mode MOSFET, a Toshiba SSM3K345R,LF. It will dissipate half/most of the excess power not consumed by the LEDs as heat. Basically, at the 120mA current, the difference between LED_VIN and the LED forward voltage at that current, is mostly dissipated by Q1. The typical range is between 50mW and 250mW, but better design for up to 400mW of power being dissipated. With some heat-sinking copper area on a standard PCB, this one should do just fine.

Q2 is an NPN BJT, a Nexperia BC847C,215. It sets the voltage drop over the current-sense resistors R1 and R2. This handles only the bias current, which is small, and doesn't need to dissipate much heat.

The current-sense resistors R1 and R2, in parallel (thus R = R1//R2 = 1/(1/18.4Ω + 1/18.4Ω) = 9.2Ω), set the LED forward current. Smaller resistances yielding higher currents. Because 120mA flowing through the 9.2Ω resistance generates (P = R I²) about 130mW of waste heat, we split the resistance into two resistors in parallel, so each one dissipates half the heat. These should be fairly precise, say 1%, and rated for 250mW or more. As increasing resistance lowers the LED current, if one resistor fails, the LED current will drop (to around 62mA), and the remaining resistor will only dissipate around 75mW or so. A single resistor will also work, but 18.4Ω resistors are better stocked than 9.2Ω, and spreading the heat a bit more is a good thing for longevity anyway.

The 2.048V shunt voltage regulator U1, one of the common LM4040 ones at 2.048V voltage, will cap the voltage seen at the gate of Q1 and collector of Q2 to 2.048V. This is the component that ensures a constant LED current at varying voltages of LED_VIN. As the LED current is linear near that voltage, it does not need to be especially precise (as in be exactly 2.048V), as long as it is stable, and does not vary too much when the voltage on its cathode is above 2.1V or so. The LM4040 series can handle currents under 15mA, dissipating the excess voltage as heat.

R3 and R4 resistors have a dual purpose. On one hand, R4 limits the current draw from the BL pin to a couple of milliamps, and R3 ensures there is at least 0.4mA (400µA) of current flowing whenever the voltage at the gate of Q1 and collector of Q2 is at or above 2.048V, allowing the shunt voltage regulator to work. (The gate of the MOSFET acts like a capacitor, and only draws current when it is switching between conducting and non-conducting. In this circuit, when PWM'ing, it draws a short spike of less than 2mA. Thus, the current draw from the BL pin is expected to stay between 0.5mA and 2.5mA whenever the shunt voltage regulator needs to cap the voltage.)

On the other hand, resistors R3 and R4 form a voltage divider of ratio 4.7kΩ/(4.7kΩ+1kΩ) ≃ 0.825. This means that a voltage of 2.5V on the BL pin yields 2.5V × 4.7/5.7 ≃ 2.1V at the voltage shunt regulator, base of Q1, and collector of Q2. Even at 3.3V, the shunt voltage regulator only needs to drop about 0.7V, so it will not generate basically any heat either (perhaps 3mW), and is well within its operational range. Because of this, the exact values of R3 and R4 do not matter if you only do PWM. Only if you do voltage control using e.g. DAC output on the BL pin (0 - 2.5V), you do want R3 and R4 to have 1% or better precision, so you'll get similar brightness at specific DAC output voltages from each unit you create. R3 and R4 will dissipate very little heat, on the order of 10mW, so they're completely ordinary signal resistors.

While overkill for most use cases, consider the alternate circuit that uses a Tiny-1 series 8-pin AVR, ATtiny412 or similar, to control the backlight PWM/DAC via SPI, reusing the BL pin as a SPI /SS. Note that Mouser sells ATtiny412 in standard 8-pin surface mount package for 0.52€ in singles, so this is not an expensive option at all; we are talking about an increase of under USD $1 in parts cost, although the helper microcontroller also does need to be programmed, so installation/integration/firmware flashing will have an added step.

The one real downside is that ATtiny412 uses the same pin for reset, UPDI programming, and SPI /SS, so programming has to be done outside the circuit (because the reset and UPDI functionality has to be disabled). Running at 16 MHz, the SPI SCK can be up to 8 MHz or so, when communicating to the ATtiny412. Of course, one could use I²C or even UART at a specific baud rate, for example when using a parallel bus between Teensy and the display module instead of SPI bus. Also, the exact maximum current is adjustable via the R1//R2 resistors, of course (within LED forward voltage drop of 2.8V to 3.5V, and maximum current between 60mA and 150mA or so). The schematic (click to embiggen):

The blue pin, SPI_MISO, for sending data back to Teensy, is really not needed. PA2 can instead be used for UART_RXD (receiving commands via UART, at a predetermined baud rate), or even for a 10k potentiometer (one end connected to the voltage reference at pin PA7, one to the ATtiny412 GND pin, and the wiper to PA2), for "analog" control of the backlight intensity. (The backlight is still fully under the control of the ATtiny412, it can just scale its maximum brightness within a specified range determined by the potentiometer, but still adjust it back to black/unlit and so on as it wishes.)

While Tiny-1 series AVRs like ATtiny412 do have an internal 2.5V voltage reference, only its lower 80% would be safe to use, so I added the same LM4040-2.0 reference to its Vref pin. PWM'ing is basically alternately writing 0 and the desired maximum value, to the DAC DATA register, for example in a timer interrupt. (AVR architecture has lots of registers, and if you reserve two for this, you can do a super-lightweight interrupt handler that just writes one of the registers to DAC DATA, and swaps the values of the two registers using three exclusive-OR operations between the two. This is just five instructions: one store, three XORs, and IRET, so the overhead is tiny. You do need to temporarily block interrupts when changing the two levels, though, as the XOR swapping is not atomic.)

If one wants to use PWM and PWM only, then R4 can be connected to PA6 instead of VIN, and PA7 disconnected or used for e.g. UART RXD or as a GPIO pin. Then, the PWM output is clamped to 2.0V. One can allow both –– PA6 supports both DAC output and PWM via timers TCB0 and TCD0 ––, if one added an opamp like MCP6006 (MCP6006T-E/LT costs 0.27€ in singles at Mouser) to buffer the output in unity gain configuration, and connected its output to R4 instead of VIN, disconnecting PA7. The opamp would be powered using VIN ≃ 3.3V; it only needs to provide under 5mA of current. The DAC itself on these can supply very little current; load has to be 5kΩ or more, so a buffer is needed. Including the MOSFET gate current when switching, it would be marginal or not work through the resistor. Internal 2.5V reference would be used, because R3+R4 acts like a DAC voltage divider.) Thus, DAC 0V-2.5V would adjust the current (scaled to 0-2.048V), and TCB0/TCD0 PWM output would effectively have 2.048V when high, clamped by the voltage reference.
As you see, there are lots of ways to adjust the circuit for ones exact needs.

There are three reasons for using such a helper microcontroller. First is that any differences between units can be calibrated away using a light sensor in a dark room or box, as only the helper microcontroller needs to know what voltage to send to get the desired brightness. Second is that only single commands need to be sent, to change the backlight brightness level as desired. The third is that when touch display modules are used, giving feedback to the human user that the touch has been noted is difficult. I believe that a quarter-second smoothly-ramping intensity pulse –– brightening the display for a fraction of a second when the Teensy notes a touch that invokes some action or effect –– will do that better than e.g. a beeper.