so I'm making an animated LED brake light using arduino nano, similar to this: https://www.youtube.com/watch?v=d5Ohzg3JKq0&ab_channel=IMEEMADE
I have 18 channels, with differet amount of series LEDs and resistor. All LED + are wired together, intended for 14.5V input, with individual resistor after the last LED cathode:
14.5V -> + LED - -> R -> GND
I have some channels with 1 LED, 2 LED and 4 LED, all tuned with different resistors so that each channel "pulls" ~20mA at 14.5V. 12V works fine as well just ever so slightly dimmer. On a power supply, I can ground any channel without cross talk, or ground all and all LEDs light up evenly (from what my eyes can tell).
I had originally planned on providing 5V input to the arduino using a buck converter and sinking each channel to a digital output pin (D2-D19 or D2-D13 + A0-A5). I ended up providing 12V to Vin and 12V to the LEDs as well as the arduino did not work at all as expected with 14.5V to the LEDs and 12V to the Vin.
My problem is that with this setup, no matter what I do in code, when the arduino is connected to Vin and ground, some LEDs are always lit dimly (D2-D13 oddly). They do indeed get brighter when pinMode
is set to OUTPUT
and digitalWrite({pin}, LOW)
is called. But writing HIGH
or setting pinMode
to INPUT
doesn't turn them off, just leaves them dim. I've tried adjusting Vin between 7-12V, setting the regulator to 5V and connecting directly to 5V. No change in behavior. Only thing that gets the LEDs to stop lighting dimly is lowering input voltage to the LEDs themselves. But then I don't have enough to drive the 4 series LED channels...
I know this can work because in the video I linked, there are 4 series LEDs driven in the same manner (though red, I'm using white), but not much is explained with the use of the arduino.
What am I doing wrong or how can I make this work? I need at least 12V to the LED board to ensure the 4 series channels light up properly. I've already maxed out the digital channels on the arduino nano from what I've read, so I can't use one as input (instead of Vin or 5V) if that matters or split the 4 series into 2 channels, etc...
Thanks in advance!
2 Answers 2
You can't drive LEDs from a source greater than 5V as a low-side switch with an Arduino directly. To do so you need an "open drain" output.
You can create them on the Arduino by adding a single transistor (N-channel MOSFET with "logic level" threshold, or NPN BJT) which the Arduino switches:
schematic
simulate this circuit – Schematic created using CircuitLab
R2 just exists to keep M1 turned off when the Arduino's not actively driving it (i.e., while the bootloader runs, etc).
-
Thanks @Majenko! I assume I need a separate resistor for each mosfet to ground otherwise if the gate pins are connected in parallel with one resistor I assume switching one output pin on the arduino will trigger signal all of mosfets?user72995– user729952021年03月08日 16:21:00 +00:00Commented Mar 8, 2021 at 16:21
For what to do see Majenko's answer.
This is regarding why you're seeing what you're seeing, or the nature of "What am I doing wrong" part of your question, and so why you need do something like what Majenko is suggesting.
Internal to the microcontroller, are diodes that protect it from voltage transients seen at the GPIO pin. One of these connects from the GPIO pin to the VCC ("5V") pin(s) of the MCU. This is pretty much the case with about any MCU, and so just about any Arduino's pins, with variations for things like 5V tolerant 3.3V parts. The RESET pin on AVR-based Arduinos has an external diode on it for reasons that have to do with (not) wanting to enter high voltage programming.
When the GPIO is not OUTPUT-and-LOW, that is if it's HIGH, or INPUT, or INPUT_PULLUP, the current is going from your 12V nominal source, down through your load (LED and current limiting), into your GPIO pin, and through the protection diode onto the 5V rail of your Arduino. From there it will compete with your 5V regulator (or USB host's regulator) to try to power everything on the Arduino, e.g. your "L" LED, the the serial transceiver, the 3.3v regulator, the AVR itself, etc. and whatever else you have connected to "5V".
So, your GPIO pins are only rated to whatever-VCC-is plus about a diode drop; somewhere around 5.5V in this case. Above that voltage, the protection diode begins conducting and the GPIO doesn't appear high impedance to whatever is connected to it.
When you're lucky, there's enough resistance in your load to limit the current through the protection diode to:
less current than the continuous current rating of the protection diode, which is quite low, often under 1mA. Otherwise, while this is going on you are likely trying to kill the protection diode and whatever else it can take out with it.
less current than the Arduino can make use of. Otherwise the voltage at the "5V" well climb to the point of frying things. It will be backfeeding whatever is supposed to be regulating the 5V on the Arduino, which may or may not be a problem depending on the design of whatever regulator that is.
If you'd done this with a larger load, it probably would have just popped things on your Arduino. On the other end of the spectrum, putting a sufficiently large resistor in series with a GPIO pin is a common method of crudely accepting higher voltage input signals.
The circuit in Majenko's answer doesn't provide path would allow any current to speak of to travel from the 12V source into the GPIO pin.
-
Thanks for the explanation!user72995– user729952021年03月08日 16:24:59 +00:00Commented Mar 8, 2021 at 16:24
A7
as an input instead ofVin
:(