I need to light up 19 RGB LED strips, which it seems would require 19*3=57 PWM outs and 57 transistors. The transistors aren't an issue, but of course the 57 PWM's is. Even if I hacked the digital IO ports to work as PWM, I still wouldn't have enough.

How can I do this more simply? Is there some kind of device I can get that would let me just pass data to it, perhaps over I2C, and it would control many PWMs? Is there another solution I haven't considered? Maybe whatever is used to control those 8x8 RGB LED dot matrixes?

Any help would be greatly appreciated. Thank you!

  • There is "set and forget" hardware available to do this, but a simple processor intensive method is to use either a 57+ long serial shift register or 9 x 8 bit parallel latches and write them with on/off patterns fast enough to PWM them. Depending on what PWM frame rate is acceptable this is "easy enough" or hard. At say 1 kHz rate you need to each of write 9 parallel latches every 100 uS or so. That's scrambling but doable. Commented Feb 9, 2015 at 1:23

2 Answers 2


You can use addressable LEDs that allow chaining from one LED to another using a serial protocol.

Like this : Fritzing, wiring

This would alow you to set the first row blue, the second purple, each one can be controled independently.

Take a look at Ada Fruit's neopixels to start. These are basically skillfully branded WS2811 & WS2812 LEDs, but they are very well documented and well built. They feature 8 bit per channel RGB color (24 bit color) and take care of PWM internally. You could even chain the end of one strip to another, allowing all control to come from two pins of an arduino.

Assuming you go this route, consider the following:

  1. You will need enough RAM to store the full array of pixels in memory, which is 3 bytes per pixel. Alternatively, you can create a custom library with reduced bit depth, or one that stores pixels in clusters, because at the end of the day you are just operating a giant shift register.

  2. You will need to supply enough current (60mA per led), and supply it at several points along longer strips. You will likely need to use external power sources. You can drive a decent amount of LEDs from Vin (before the power regulator), but not anything near 19 strips.

Now if you already have the strips, and they are analog strips, I think you can find similar drivers that output more power to drive strips, but still use a serial protocol.

You can use my example code here:

// NeoPixel Demo minimum 
// By leo etchaas
// released under the GPLv3 license to match the rest of the AdaFruit NeoPixel library

#include <Adafruit_NeoPixel.h>
#include <avr/power.h>

// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1
#define PIN            6 

// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS      55

// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
// Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest
// example for more information on possible values.
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

int delayval = 500; // delay for half a second

void setup() {
  // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
#if defined (__AVR_ATtiny85__)
if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
// End of trinket special code

pixels.begin(); // This initializes the NeoPixel library.

void loop() {

// For a set of NeoPixels the first NeoPixel is 0, second is 1, all the way up to the count of pixels minus one.

for(int i=0;i<NUMPIXELS;i++){

// pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
pixels.setPixelColor(i, pixels.Color(25,255,255)); // Moderately bright green color.

pixels.show(); // This sends the updated pixel color to the hardware.

delay(delayval); // Delay for a period of time (in milliseconds).

}for(int i;i>0;i-=1){

// pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
pixels.setPixelColor(i, pixels.Color(255,5,255)); // Moderately bright green color.

pixels.show(); // This sends the updated pixel color to the hardware.

delay(delayval); // Delay for a period of time (in milliseconds).


There are several ways you can do this:

Option 1 - the easy way: You can use a serial-in-parallel out. Google "Arduino SIPO", and you will find examples. You basically send out 8 bits at a time, to a SIPO chip, then "enable" the chip; this changes the 8 "output" pins of the sipo to combinations of high/low as per the 8 bits that went in. You can pwm the "enable" pin. The best part is that each SIPO chip has an overflow - if you put a ninth bit in, you will get the first bit out of the overflow pin, which you can hook up to the input pin of a second SIPO, and so forth.

This option uses about arduino 4 pins, for an unlimited number of output pins.

This also has the advantage that SIPO chips can normally carry much more power than an arduino. Check the spec sheet on the SIPO to see how many milliamps it can carry at once (maximum). An example of a SIP is 74HC595.

Option 2 - Control the common pin for each strip. Basically, you will be using e.g. 3 pins to select the colour, 19 to select which strip - I think some arduinos have that many pins? To light up red on strip 3, you would put the red pin high (and green & blue low); then you would put the pin for strip 3 low, and all the others high. You would step through each pin you want to light, or you could light them in groups - first red goes high (green/blue low), and all the strips you DONT want red on have their cathode high, and those you DO want red on would have their cathode low. drop red down; then do the same for green and blue. This does mean that you can't light up leds more than 1/3 of the time. This can be combined with the SIPO chip above - it may be easier. This does mean that you need to break out the "common" (cathode, normally to ground).

None of these allow very fine-grained control like pwm - you can't just say "led 3, green, 40%"; you will have to do a lot more work. You may burn all your Arduino time just doing the LEDs; this may or may not be a problem. You have the option of offloading your work onto another AtMega chip, or even an AtTiny; I think I would use an AtTiny and three SIPOs - 4 pins of the AtTiny to control the SIPOs, and 4 for SPI to receive the new settings (e.g. send the AtTiny 57 half-bytes, would give you 12-bit colour depth). You would need to do your own "fake pwm", but you could devote the entire AtTiny to running the light show. The AtTiny is programmed the same way as an Arduino; you would use a USBISP to send the program. Just hook up the power and away you go! An AtTiny will set you back around $2, depending on how many you get and where you get them from.


What about using something like a TLC5940? I haven't looked at the specs, but I found a reference to Arduino code. 16 Channel, 12 bit duty cycle per channel; you would need 4 of them. Apparently they can be daisy-chained as well. http://playground.arduino.cc/Learning/TLC5940

  • The DM13A is similar to the TLC5940, so that's an alternative.
    – Gerben
    Commented Feb 9, 2015 at 15:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.