Cascading three 5940 LED drivers with Arduino
So sixteen LEDs fading up and down aren't enough? How about 48?
My earlier post showed a rough project using three Texas Instruments 5940 chips, but didn't include much detail. Some of you have been asking for a bit more info, so here goes:
Cascading additional 5940s to get more LED ports:
THE HARDWARE
Connections: [Internet Explorer will not render this table and the following text correctly. Use Firefox or Safari. Thanks.]
| FROM... | ...TO FROM... | ...TO FROM... | ...TO |
| Arduino Pin | First 5940 | Second 5940 | Third 5940 |
| 2 | VPRG [pin 27] | VPRG [27] | VPRG [27] |
| 3 | SIN [26] | ||
| 4 | XLAT [24] | XLAT [24] | XLAT [24] |
| 5 | BLANK [23] | BLANK [23] | BLANK [23] |
| 6 | DCPRG [19] | DCPRG [19] | DCPRG [19] |
| 7 | SCLK [25] | SCLK [25] | SCLK [25] |
| 8 | GSCLK [18] | GSCLK [18] | GSCLK [18] |
| SOUT [17] | SIN [26] | ||
| SOUT [17] | SIN [26] |
• The IREF pin [20] of each 5940 should have its own 2K ohm (approx) resistor run to ground.
• The VCC [21] and GND [22] pin of each chip should also be connected to +5V and ground as usual.
Refer to page 6 and 17 of the PDF for the TLC5940 NT from Texas Instruments for pin and connection diagrams.
[My design only used 45 LEDs so you do not see connections from pin 15 (the 16th LED port), but of course that is possible. I also ignored the XERR port.]
You'll also notice that I chose to supply power directly to the chips (and to the Arduino) because I was not sure if the current required to light all the LEDs would exceed what the Arduino could handle if I used the on-board power supply.
THE CODE [Engineers, please excuse my street-level description!]
The essential logic of driving the 5940 goes like this: 1. Push the "gray levels" (how bright you want each port to be) into the chip. 2. Pulse the chip's greyscale clock, which causes the chip to update each port based on its assigned grey level.) In my code, this is done with 1. setGreys() and 2. feedPorts().
Think of the greyscale storage register in the chip as a row of 16 seats in an auditorium, where the last, 16th, seat is up against a wall. When the crowd files in, the usher has each patron fill up the row by moving all the way to the end. So the first person into the row gets the last, 16th seat. Short version: you have to load the data into the chip "backwards". In my code, that means reading the "fadeLevel" array starting at the last item (see setGreys()). [Of course you could just wire your LEDs backwards, but why add to the confusion?]
What's great about the design of this chip is: if you want more than 16 ports, you just chain together more chips as described above. Then when you do the cyclical setGreys()/feedPorts() updating, you push all the data into the first chip; if you give it more than 16 chunks of data, the data "spill out" of the SOUT port of the first chip and into the SIN port of the next chip.
So, let's say, if my fadeLevels array has 48 items in it, the last 16 items are for chip 3. (The code takes care of sending them "backwards" through the chips, so that the data shows up at the desired ports.)
Here is how the key parts of my existing code would change if you were using 3 chips:
When initialzing:
int fadeLevel[] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int fadeState[] = {
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
When looping through the data, the list size changes from my original example, obviously, from 16 to 48 (or, since the arrays are zero-indexed, the 15 changes to 47). Be careful if you decide to edit the old code because some of my arrays are used for binary data manipulation and should not change size.
I have a PDE file available, as a complete example. Contact me and I'd be happy to shoot you a copy.
One detail: The code uses direct port addressing to update the 5940 as fast as possible. This page from the Arduino reference explains the concept.
- peterM's blog
- Login or register to post comments
