Most of the time when I’m driving an LED, I do it with a simple ballast resistor, and that’s all there is to it. Lately, however, I’ve been working on a few LED matrix projects, and while it’s certainly possible to use the same simple resistor approach, this leads to a very dim display. (Since any given LED’s duty cycle is 1/N max, they appear much dimmer than they normally would.)
The good news is that there’s a straightforward solution to this problem. LEDs have a rated forward current, but they also have a rated peak current, specified at a given pulse width and duty cycle. For instance, these red LEDs are rated for 30mA forward current and 185mA peak in 0.1 ms pulses at 10% duty cycle. Why is this stat useful? As long as you stick to the pulse width and duty cycle parameters, you can intermittently drive an LED at an excess current and get a brighter light without burning it out.
There is a risk in using this setup, though. If for some reason your PWM signal were to lock up in the “high” state, then the pulse width limitations would be exceeded and you’ll probably fry the LED in an instant. This means you need to be especially cautious during development – crashing your microcontroller at the wrong time can be costly!
While the theory of this is straight-forward, I wanted to test how it actually looks in practice before I integrated it into my design. If it was only moderately brighter, I didn’t want to spend the energy (and money) on adding an array of transistors to my board.
I decided to throw together a test setup that would allow me to compare brightness of an LED at its full-on steady current, one PWM’d with a ballast resistor to keep it at its steady current, and one at peak current and PWM’d. This sets up a comparison between the maximum brightness, the brightness of the same LED in a naively driven matrix, and finally the same LED over-driven.
The LEDs I’m using here are surface mount in a 1206 package. Saying that they are very small is an understatement. They are by no means breadboard compatible, so the first step was creating a simple breakout board.
I used a piece of pre-drilled perfboard with a solid copper pour on one side to make the breakout. I marked off a few columns of 6 holes each so that it would span the IC gutter on a breadboard, then cut the piece out with a pair of aircraft snips. Next, I used a utility knife and a straightedge to score the copper and separate the columns from each other, and then did one horizontal stroke to make a grid of 1×3 hole pads.
Next, I soldered two rows of 0.1″ header to the top and bottom of the board for mating with the breadboard. Then, I hand-soldered 6 LEDs, 3 red and 3 green, onto the board. (Judicious use of continuity tester and solder sucker not optional.) Finally, I used a file to chop one corner as an orientation indicator and then cleaned up the rough edges.
To prove that everything was working, I started out by connecting the steady current resistor and probed all the LEDs. Everything lit up fine. With the baseline established, the next step was to set up the PWM signal. According to this page, the Arduino’s built-in analogWrite() PWM runs at about 500Hz, which is too slow for the target pulse width. Since I didn’t need crazy precision or performance here, I decided to quickly write up an Arduino sketch that toggled the output pin manually and used delayMicros() to set the interval. The sketch turned out to be pretty simple:[gist https://gist.github.com/bryanduxbury/7729613]
To verify that this was giving the output I expected, I hooked up the output pin to my handy DSO Nano. On the first try I ended up with a 996 Hz frequency and good pulse width. The error in the frequency is probably due to the fact that there’s overhead to toggling pins and calling delayMicros(). I suspect I could dial it into precisely 1000 Hz by guess and test on the delay durations, but it’s not that important at this point. In the real production scenario, I’ll be using a hardware timer and it’ll be worth getting it exactly right.
Connecting the PWM output to the second LED was straight forward, though I did add a NPN transistor in between the output pin and the LED so that it could drive all the PWM inputs without any worries about current draw.
The over-driven LED was the most complicated to set up. I plugged the peak current number into an LED resistor calculator, and it told me I needed a 12 ohm, 2 watt resistor. Yikes! I certainly don’t have anything like that on hand. Rather than putting a whole ton of resistors in parallel, I wired up a simple constant current LED driver circuit using some common transistors and resistors. I’ll leave the discussion of that driver circuit for another time, but the cool thing about it is that it allows the transistors to do all the heavy wattage dissipation while the resistors see a tiny load.
With everything wired up, I powered it on to assess the results:
I would say that the PWM-only LED is substantially dimmer, and the overdriven LED is almost but not quite as bright as the steady-on LED. This turned out to be exactly the sort of obvious difference I was looking for. It seems well worth adding the additional circuitry to get a much brighter display.