RGB LED Matrix + 4017 Decoder + TLC5940

I had the 4017 counter outputs sourcing the rows of the LED matrix. 2 columns of the matrix were connected to 6 channels of a TLC5940 LED driver (~2k limiting resistor hooked to the 5940). With this configuration, I was getting very low current through the array (expecting 20mA but got something like 2mA).

I thought the 4017 counter maybe couldn't source enough current, so... since I had a uln2803a darlington transistor array lying around, I decided to try to use it to get more current into the rows of the RGB matrix.

I hooked the "COM" to +5 from my Arduino Nano, hooked "GND" to ground from the nano, pins the 4017 outputs are connected to 1 - 8 of the uln2803a, and finally pins 11 - 18 of the uln2803a go to the row pins of the RGB matrix.

Now I get NOTHING out of the matrix.... I get 11mV between the tlc5940 and the matrix when each row is pulsed. 4.4V at the 4017 pin that is pulsed.

Any ideas, folks?

Thanks so much in advance...

I am not sure from your description exactly what the arrangement is. Maybe you can post a quick schematic. This link shows how I multiplexed a TLC5940:-



Both the ULN2803A, and the TLC5940 parts sink current when they are active, so you are essentially grounding both sides of the LEDs.


Thanks for the replies...


I'm not totally sure I understand your comment... anyway you can expound upon it?


Sorry, no easy way to generate a nice schematic right now... but I want to do basically the same as you have in your schematic, except, I'm using a 4017 decade counter that sets 1 of it's output pins high (+5V) in sequence when it's clocked (by 1 digital out of the Arduino).

However, when I used the outputs of the 4017 to directly drive the rows of the matrix, very little current went through (i.e. diim LEDs). I assumed the 4017 just couldn't provide enough current... it was this hypothesis that led me to use the 4017 as an input to my darlington array, and then use the outputs of the darlington array to source the rows of my LED matrix. (which of course led to no action on the matrix at all... the reason I'm here)

If I understood your drawing and explanation, your rows light up when the arduino pin that's connected to the particular matrix row is set LOW. This is the opposite of what my decade counter is doing... is there an alternate transistor array I should try that basically is a negative of yours?

Also, why not just source the rows directly from the pins of the Arduino? Is the +5V that's connected to your transistors in your diagram being supplied by the Arduino's +5V source?

As you can tell... there are probably some fundamentals that just aren't second nature to me yet... but I'm getting there.

Thanks folks!!!


In your original circuit, the LEDs are being lit because the 4017 outputs are sourcing current (going high), while the TLC5940 outputs are sinking current (going low).

In your new circuit, when the 4017 outputs go high, they turn on the darlington driver which then sinks current (goes low). And since the TLC5940 outputs are also sinking current (going low), there is no current actually going through your LEDs.



OK... I understand now... so apparently the darlington array does the opposite of what I wanted it to do...

If I inverted the the 4017 output somehow, would that send the outputs of the darlington array high (i.e. sourcing current)? Or, could I use a shift register to get the same effect by shifting out the following to the darlington in sequence?: 01111111 10111111 11011111 ...... 11111110

I guess I need some sort decade counter that can source at least 120-180mA. Btw, my array is made up of 8 rows by 2 columns of RGBs. 120-180mA per row would allow 20-30mA through each color of the 2 columns at the same time... correct? This config would allow only 14 wires to be connected to the array.

If I did a 2 row by 8 column array, I'd need 26 wires for the array. As well, each row source would have to light up 24 LEDs at 20-30mA max a piece which give a grand total of 480-720mA for each row when lit... kinda huge, right?

How do most folks deal with this? Is this all even possible from a little 'ol Arduino nano and TLC5940? I basically want to control 2 rows of 8 RGB LEDs, be able to fade them (TLC5940s), use as few wires for the matrix as possible (multiplexing), and as little power as possible.

There's gotta be light at the end of this tunnel... wow, that was an unfortunately bad pun.



To use darlington drivers you will need to switch to PNP parts that source current. Like: http://www.allegromicro.com/en/Products/Part_Numbers/2981/2981.pdf.


lso, why not just source the rows directly from the pins of the Arduino?

Because an Arduino pin can only provide 40mA and that is not enough for all the LEDs in the column. So you need something to pull up the power to the +ve line. That is why you need a PNP transistor or in my case a P-channel FET.

Try and learn about the difference between sourcing and sinking current as this is the key point here with a matrix. In one dimension you need to source current and in the other you need to sink it.

Thanks guys... admittedly I'm shaky on transistors... I'll take the advice an run with it...


Alright.... I picked up a DN2982A-T source driver.... much better results. I'm getting around 14mA through each color of the RGB array into the TLC5940. I'm still using the 4017 counter to pulse each row in succession (8 rows). I've got a 2.1k resistor between pin 20 on the 5940 and ground to limit the current the 5940 sinks to I believe 20mA. The 4017 counter is providing ~4.7V and .008mA to the input side of the 2982 source driver. The 2982 also applies 3.3V to the array row when it's pulsed.

My current "issues":

1) I want higher current through each LED... what is limiting this in my setup?

2) Also, I am getting flicker when an entire column is pulsed in succession at high speed (i.e. no delay() fuction used.... or delay(0)).

I am using an analogRead() to get the voltage from a 500k pot I have connected to the Arduino to test this type of functionality. I am planning on using this method in my project to capture a value that will be used for the color information to be displayed in the array. Right now, I have the value captured being assigned to a delay() function just to slow down and speed up the pulsing of each row of the array (to verify I had things connected correctly and "witness" the POV effect).

Since this project is going in a guitar, and the pot used will be concentrically stacked with a pot that will actually control guitar signal, I am basically limited to 250k being the lowest value of dual-stacked pot I can find.

My current solution (with the above issues) requires 14 data lines going to the array. If I can't figure the flicker issue out and make it not noticeable to the human eye, I will have to reconfigure to pulsing only 2 rows and sinking 8 columns (24 lines) into 2 5940s. This would require 26 data lines, but should theoretically cut the flicker down by 1/4 (and would be conceptually easier for me to program)

Any clues regarding the flicker or current issue, given the above constraints?

Thanks, lqbert

define CLOCK 2

define pot_source 7

define pot_pin 7

void setup() { Tlc.init(); pinMode(CLOCK, OUTPUT); pinMode(pot_source, OUTPUT); Serial.begin(9600); }

void loop() {

int n = 0; digitalWrite(pot_source, HIGH); n = analogRead(pot_pin); digitalWrite(pot_source, LOW);

Tlc.set(2, 4095); Tlc.set(3, 4095); Tlc.set(0, 4095); Tlc.set(1, 4095); Tlc.set(4, 4095); Tlc.set(5, 4095);

digitalWrite(CLOCK, HIGH); digitalWrite(CLOCK, LOW);

Tlc.update(); delay(n); // Serial.println(n); }

Did you have any flicker when you were driving the leds directly from the 4017?

I assume that you have connected the 4017 reset line to output 8, so that it doesn't count to 10.

For the delay rate, if you want say a 32Hz update rate (which should be flicker-free) you would need to complete a full cycle in about 31ms, or about 4ms per row for 8 rows. Depending on what values you get from the pot, maybe you should consider scaling it down to a 1-6 range or thereabouts if you are going to use it for controlling the delay.

You could also try tying the 4017 clock to the TLC xlat, then they should be synchronized without having to pulse a separate line.

btw why do you toggle pot_source?


Thanks for the reply… I had the reset line tied to output 8, but now I’ve got it tied to a pin on the Arduino that I pulse at the end of a loop in my code… I did so I could manually reset the 4017 with code at the beginning of the row scanning.

How do you determine what refresh rate you’re getting? I think I tried to figure it out by outputting millis() to the console each time I went through the loop, but I’m sure these added functions are adding wasted time, right?

I toggle pot_source because I’m using pin 7 as the source voltage of the pot. I initially just had the pot being sourced by +5V. It was pointed out that I could use the “toggle the source pin” method to not waste power unnecessarily when I’m not taking a reading from the pot.

The “tying the 4017 clock to the TLC xlat” is intriguing, indeed. I’m not too familiar with the the xlat does, or when it does it? Can you give a quick run-down of when the xlat fires off a pulse?

As you can see from the code below, I’ve altered it a bit. Now it scans through the 8 rows in a for() loop. A reading is taken from the pot each time before row 1 is pulsed. This reading is used to basically fade both columns from red to blue and all points in between. if I use a value other than 1 in the delay() fuction, I get flicker… I assume using a 0 value lowers the duty cycle too much??? And a value higher must create too much delay between each row scan… I could be totally off and just not truly understand what’s going on. In any event, with delay(1), I get no noticeable flicker and the pot fades between red and blue very nicely. The final design will need to fade colors with a pot like this.

Thanks in advance for any additional clues or advice…


/* These two includes should go at the top of any file that uses the TLC5940 library */
#include "tlc_config.h"
#include "Tlc5940.h"

/* These definitions assume that LEDs are connected to the TLC5940s' inputs 
consecutively by rows (starting with row 1) in ascending order starting with OUT0 on TLC #1 */ 
#define NUM_ROWS 8
#define NUM_COLUMNS 6
#define NUM_COLORS 3

/* Define colors used here -- number them starting with "1" up to NUM_COLORS in the 
order that they're connected to the TLC5940 outputs */
#define BLUE 1
#define RED 2
#define GREEN 3

#define COUNTER_CLK 2
#define CLR 4

#define pot_source 7
#define pot_pin 7

int n;

void setup()
  /* Tlc.init() has to be called before using any of the library functions */
  pinMode(CLR, OUTPUT);
  pinMode(pot_source, OUTPUT);

void loop()

  n = potRead(pot_source, pot_pin);
  pulse(CLR);          //Sets the 4017 counter to start at 0
  for (int i = 1; i<=NUM_ROWS;i++){      // Loop that pulses each row
    Tlc.set(2, n*4);
    Tlc.set(3, n*4);
    Tlc.set(0, 4095-n*4);
    Tlc.set(1, 4095-n*4);
    delay(1);        //Anything other that 1 causes flicker


Function to return an ADC value from a potentiometer... values passed to it are a digital pin number acting as the 5VDC source and an analog pin number to take the reading from 

int potRead(int source_pin, int read_pin){
  digitalWrite(source_pin, HIGH);
  int n = analogRead(read_pin);    // read the value from the pot and store in n
  digitalWrite(source_pin, LOW);
  return n;

Function to clock a pin as described by the passed variable 

int pulse(int pin_num) {
   digitalWrite(pin_num, HIGH);
   digitalWrite(pin_num, LOW);
   return 0;

How do you determine what refresh rate you're getting?

Use an oscilloscope. Or if you can see it flickering it is below 30Hz.

Please when posting code paste it between the two square brackets you get with the hash icon (9th from the right on the top row).

Noted... and the xlat works like a charm...

...tying the 4017 clock to the TLC xlat:

I found this worked really well when I was prototyping with the TLC and a decade counter. I gave up though since the CMOS counter couldn't provide enough juice; it never occurred to me to use transistors to boost the output.

The XLAT pin is toggled once every time a full set of data has been shifted into the TLC over the SIN line.

You could perhaps otherwise use the BLANK line, you'd have to look at the TLC library code to see what order they are toggled.

Mind you, I've been using my own code during prototyping so I can't guarantee this will work with the library.

You will still have to reset the counter during initialisation, as you have already found out. I ended up putting a diode between my reset and the 8th output to ensure the periodic reset worked. It might be an idea to set the arduino pin to high impedance instead, I'm not sure - I'm actually rubbish at electronics.

xlat worked OK... but I'm having a couple issues:

1) I've tried to set up some code to use multiplexing to only have, for instance, only couple LEDs lit at a time. I have the basic idea understood (pulse through the rows very quickly and only sink the current to the appropriate column when the row you want to light up comes around). I think I need some pseudo code for when to transition to the next row and when to update the 5940 (i.e. sink current to the column).

2) I slowed down the clocking of the 4017 to troubleshoot a weird "flashing" issue I have when I pulse rows. On the UP cycle transition of the clock, every row flashes very dimly... on the DOWN cycle transition, every row flashes dimly again (though a little less bright than on the UP cycle). If I were to program only 1 LED in the column to be lit using multiplexing, this "flashing" issue makes it look like all the other LEDs in the column are dimly lit.

I'm not sure if for some reason on every clock cycle the 4017 is putting out a small amount of current on every output that my 2182 source driver is amplifying, or what?

Thanks again... I may try using a shift register... or switch my configuration to only pulsing 2 rows and quadrupling the number of columns I have (go from a 8x2 to a 2x8). This of course would increase my power requirements, but I could get rid of the 4017 and just use 2 pins from the Arduino to pulse the 2 rows.


The code I used did something like this, triggered by a software interrupt

  • shift data for row X to TLC
  • bring the BLANK line high
  • latch XLAT
  • increment counter (done by XLAT)
  • increment X
  • bring BLANK low

Because BLANK is high when the decade counter incremented, there's should be no 'leakage'.