Driving an LED Matrix



LED Matrices

I've had these LED matrix modules laying around for many years and for some reason never got around to using them. They are very old. If memory serves, they are some of the original prototypes invented by Alexander Graham Bell in 1492. Today I finally got around to playing with them. I hooked up a single module to an AtMega32 and made it scroll text and do simple graphical things. Here's a video of it in action:





Each module contains 64 LEDs arranged in an 8x8 array. However, there are only 16 pins on the back of each module, meaning that the LEDs are not individually controllable. The cathodes of all the LEDs in each row are connected together and brought out to one pin. Similarly, all the anodes of each column are brought out to one pin. 8 rows equals 8 cathode pins, and 8 columns equals 8 anode pins.


To light any single LED, we provide power to the anode pin for the LED's entire column, and we also provide a path to ground through the cathode pin for the LED's entire row (hopefully using a current-limiting resistor somewhere in there so we don't burn out the LED). This is illustrated in the image below. The yellow line shows the column we've activated via the anode pin, and the blue line shows the row we've activated via the cathode pin. Wherever a yellow and blue line intersect, an LED will light.


But suppose we wanted to light two LEDs in the following pattern:


Can you figure out which pins to activate in order to light them up without lighting up any other LEDs? Don't spend too much time on this. It can't be done.

Here's why:
To get both LEDs lit, both column pins and both row pins must be active. The problem is that this creates a 2x2 matrix of active cells, meaning that all 4 LEDs in that little matrix will be lit, as illustrated by this image:


This is the price we pay for having only 16 pins to control 64 LEDs. In order to light up every LED desired, it's very likely that other unwanted LEDs will light up as well. To keep those unwanted LEDs from being lit we have to cycle through the array lighting only a few LEDs at a time (a single row for instance, or a single column). If we cycle through the whole array quickly enough, the eye can't tell that only a few LEDs are lit at once so it looks like all the desired LEDs are on constantly.

On the down side, we lose some brightness because no LED can be lit 100% of the time. In fact, if we activate only 1 column of LEDs at a time, each LED is illuminated at most 1/8th of the time.

After we've let our one little column glow for a while, we'll switch to the next column and give it a chance. Then we'll move on to the next, until all columns have had a chance to glow. Then we'll start over at the first column again. If this process happens quickly enough (say, several hundred times a second), then the display is flicker-free. It just doesn't look quite as bright as it might otherwise. However, since our duty cycle for each LED is only 1/8th of what it would be normally, we can lower the value of our current-limiting resistors a bit. This will allow more current to flow through the LED, making it brighter, but it will be on for such a short time that there will be no damaging heat build-up from the higher current. Of course if we over do it we may shorten the life of the LEDs this way.

Now since we are driving only one column at a time, we know that no more than 8 LEDs can be lit at one time. This means we only need 8 current-limiting resistors for all 64 LEDs. We put one resistor on each row pin as illustrated below:

If we had chosen to drive one row at a time rather than one column, we'd simply have put the resistors on the column pins to get the same effect.

You may have noticed in my images that some LEDs appear much brighter than the others. Specifically, the more lit LEDs a column has, the dimmer the LEDs in that column get. It's particularly noticeable in the following image in which all the columns have two LEDs lit except the 5th, which has 7 and is consequently much dimmer.

This happens because I'm driving the LEDs directly from an MCU's I/O pins. There is a limit to how much current each I/O pin can supply, and when several LEDs are lit, they need more current than the pin can supply. They have to share what little current is available, and so they are all dimmer. This problem can be eliminated by driving each column with a transistor or an LED driver chip rather than directly with an MCU pin.

That covers how to put a static image on the display. But how do we make it scroll? Well, we just change the static image periodically, where "periodically" means "much less often than our column-by-column refresh loop". For instance, our refresh loop may iterate 400 times a second (a very flexible number), while our image-changing loop may iterate only a few times a second; maybe just 5-10 times per second for scrolling text or 30 times per second for video-like animation.

(to be continued...)