Using ShiftPWM to control RGB LED’s with Arduino

If you want to use normal 20mA LED’s, this article will show you how to wire them for use with ShiftPWM. If you are not using 20mA LED’s, please take a look at my other pages for high power LED’s (350mA) or LED strips.

16 RGB LED’s driven by 6 shift registers and ShiftPWM on a breadboard

So which shift registers are compatible with ShiftPWM?

My library is compatible with almost any shift register. What is important is that you use a serial in – parallel out shift register with an internal storage register (so with a latch pin). The most commonly used shift register is the 74HC595. Please note however, that while the 74HC595 can handle 30 mA per output, it’s total current is officially rated at 70mA max. I have not encountered any problems with the 595 driving 8 LED’s, but I just want to be clear you are exceeding the maximum current rating of the device.

A great alternative to the 74HC595 is the TLC5916. It is a shift register with a constant current sink output. The are a bit more expensive, but still cost less than $1.50. You can choose the output current with an external resistor, so you do not need a resistors each LED. That will save you a lot resistors and a lot of soldering, which makes up for the price difference.

You can chain as many shift registers as you like, but if you are using many registers or long wires in between, the Arduino will have trouble driving the signal lines at high speeds. A small push-pull line driver between the Arduino and the signal wires will increase the output drive capability and solve the problem, see the schematics below.

The schematics below are for common anode RGB LED’s, but 74HC595′s will work with common cathode RGB’s as well. If you want to use the TLC5916 drivers, watch out when buying LED’s because they can only sink current. Common cathode RGB LED’s will not work with the TCL5916!

 

Which Arduino pins should I use?

There are two versions of ShiftPWM: a version that uses the hardware SPI port and a version that doesn’t.With the non-SPI version, you can choose all the pins freely. It is 2.5x slower than the SPI version, but you can use the SPI port for something else.

With the SPI version, you will have to use the MOSI (Master Out-Slave In, PB2) and SCK (SPI clock, PB1) pin.

It makes sense use the SS pin (Slave Select, PB0) as latch pin, but you can choose that pin freely. I use pin 8 by default, because SS is tied to the RX LED on the Arduino Leonardo so it is not available for ShiftPWM. Using pin 8 keeps it the library consistent between boards.

Do not use the MISO pin for anything, because this interferes with SPI operation!

The following table shows you where those pins are located on various Arduino boards:

 

Regular Arduino / LilyPad (atmega328) Arduino Leonardo Arduino Mega Teensy 2.0 Teensy++ 2.0
Data pin (MOSI) 11 ICSP 4 51 2 (B2) 22 (B2)
Clock pin(SCK) 13 ICSP 3 52 1 (B1) 21 (B1)
Default Latch pin 8 8 8 8 8
Slave select (SS) 10 - (RX LED) 53 0 (B0) 20 (B0)
MISO pin(do NOT use!) 12 ICSP 1 50 3 (B3) 23 (B3)

 

Schematic for regular 74HC595 shift registers

The shift registers are used as a current sink here, so make sure that ShiftPWM_inverOutputs is set to true.

ShiftPWM schematic for 3 74hc595 shift registers and 8 RGB LED’s

Schematic for TLC5916 constant current LED drivers

The constant current LED drivers are on when the output is written to 1, so make sure that ShiftPWM_inverOutputs is set to false.

ShiftPWM schematic for 3 TLC5916 constant current LED drivers and 8 RGB LED's

ShiftPWM schematic for 3 TLC5916 constant current LED drivers and 8 RGB LED’s

 

47 Comments

  1. Hi. I tried to run the shiftpwm_RGB_ example but it appear that shiftPWM was not declared in this scope.this is my first try with PWM THANKS FOR YOUR EXPLANATION IN YOUR WEB. Jaime

    • It sounds like you did not add did not add the ShiftPWM library to your Arduino libraries directory.
      Did you add the ShiftPWM library and then opened the example through File->examples->ShiftPWM?

  2. Thank you for creating and documenting the ShiftPWM library. I am planning to use it in creating a string of addressable Christmas lights. All the commercially-available fully-addressable strings cost $2 or more per pixel, and I am trying to find a way to do it closer to $1 per light. Using 24 TLC5916 or 12 TLC5927 chips to drive the RGB LEDs in clusters, I think I can get close to that cost for 48 lights.

    I have been concerned about sending these signals down long runs over a 12 ft or even 24 ft run (all the electronics projects I have made so far could sit on the palm of my hand). The inset in your schematic shows a Push-Pull Line Driver circuit for “long wires”. How long is “long”? The CLOCK and LATCH lines will probably need this, but how far can I send the DATA line between chips without some sort of line driver or repeater?

    Thanks!

    • I think the data line between chips will not become a problem. The load on the line is only 1 shift registers, where it is all shift registers for the clock and latch line. Each shift register reconditions the data line.

      But I have not tried using a very long data line, so you will have to experiment with that a bit. It will pick up some more noise and it will have some inductance and capacity, so you just have to try it out. A faulty clock line is worse than a faulty data line, because it causes all LED’s to be shifted. A bit flip in the data line might be less noticeable, because it gets refreshed really quickly.

  3. Do you know if this library works with the ATtiny 45/85/44/84 MCU`s??

    Thanks for writing an awesome Library!!

    Kim K.

  4. can i use tihs library into codevision ?

    • I have never tried it. It works fine in AVR Studio, for which I have an example project available.

  5. hi & good day to you,

    i have just stumbled upon your library and this AWESOME set of instructions and schematics, im only a newbie with Arduino and learning but i have made a few homebrew PCBs and have two questions if you would be so kind to help me out on these:

    Please could you show me how i would connect up common cathode LEDs to this setup and also do you have the eagle file for the schematic for the 595 shift registers available to be emailed to me please please please – i really want to create an RGB array for my fiancĂ©, a lightbox that a glass ornament would sit on!

    Please please help !

    Many thanks in advance,

    Anil Sethi Jnr

    • Hi Anil,

      You will have to use the schematic for normal shift registers, but you just turn the LED’s around and connect the common cathode to ground.
      The TLC5916 is not compatible with common cathode LED’s. It is the better choice, so if you have not bought your LED’s already, get common anode.

      I will send you the eagle file of the schematic by mail.
      Show me the result when its finished please!

      Elco

      • Hey Thanks So Very Very Much Elco !!!

        Your A Genius !!!

        The Library, Schematic & Extra Help are the foundations of my project now, unfortunately i had already acquired common cathode RGB LED’s, a whole bunch of them, if only i had seen your website 1st !

        I am aiming to make two homebrew PCB’s, one for housing the RGB LED’s and one for the Arduino Components and plan to use all SMD Parts, i have shift registers (595), resistors, crystal, just saving up for a few of Atmega168P-AU as they are cheaper to buy in batches of 10 and will most-definitely let you know how it goes with some photo’s !

        Once again, thanks so much Elco, your work is truly Legendary !

        ;-)

        • Get the Atmega328P instead, it’s the same chip with double the memory.

          • Once again i am in your debt Elco !!!

            Thanks so very very much !!!

  6. Hi,
    I have a question.
    YOu said that with the TLC5916 we dont need the resistors, because you can set the voltage & current with a resistor.

    BUT, most of the RGB LEDs need a different voltage for each colour.

    For example:
    RED 2.0 volts
    GREEN 3.2 volts
    BLUE 3.2 volts

    Can you explain to me your solution with this problem?

    Another question:
    I don’t have a 5v source.
    I have only a 3.7v battery, can i use your TLC5916 circuit? If yes, i must change only the resistor to get the proper voltage? Do you how much Ohms?

    Thank you very much to sharing with us your library, very useful!

    Damiano

    • You only set the current with the external resistor, the chip makes sure the current is 20mA, so there is no problem. You should check the TLC5916 library to see if it supports the lower supply voltage. It will also depend on your LED forward voltage how low you can go.
      I think 3.7V might be a little low. The formula for the resistor is also in the datasheet.

      Elco

  7. @ Damiano:

    Just a suggestion, but if you only want to use a 3.7v battery (im guessing Li-Po/Li-ion) then hows about you use a Boost PCB to boost its voltage upto the 5v that you need to run Elco’s awesome tutorial, like below:
    http://cgi.ebay.co.uk/ws/eBayISAPI.dll?ViewItem&item=221176542142&ssPageName=STRK:MESE:IT

    Also i completely forgot about the RGB LED’s having to need different resistors for the red portion of them, thanks for reminding me !

    @ Elco

    Yaa im gonna check the datasheet too for the resistor calculation formula, completely forgot to do that too !

    Keep up the GREAT-Work !!!
    (Yup ima still collecting parts for my PCB lol !!)

  8. Is this code compatible with the TLC5940?
    If so do you have any wiring examples?

    • Hi John, this library is not compatible with the TLC5940, which has hardware PWM. In my library, the Arduino calculates the PWM. So it is software PWM.

  9. Hi Elco,

    Does your library work with the 16-channel version? (TLC59025)

  10. Hello,

    I think I know the answer to this, but would rather hear it from you…it looks like this library will work with the 16-channel version (TLC59025), is this correct?

    Thanks.

    • Hi Mike,
      As far as I know, the 16 channel version behaves exactly the same as a chain for two 8-channel versions.
      So just treat them like that.
      Elco

  11. from looking at the diagrams you have to run leds in multiples of 8? 8, 16, 24,32…etc?

    • The shift registers have 8 outputs, so multiples of 8 for single color LEDs.

  12. oh… i already bought a common chatode RGB led. i forgot to check it.
    how i supposed to do with the schematic..??

    could u send me the schematic for common chatode..??

    thank you before

    • For common cathode LEDs, use the 74hc595 schematic. The direction of your LED’s is reversed, so they will connect to a common ground instead of a common 5V line.

      • @Elco
        I am in the same situation as well I am building a 5x5x5 cube and I am stuck with common cathode RBG leds. I understand you said to use the 595 schematic where the common line is just ground. Now in order to control each leg with pwm do i set the 595s to source the voltage? Also I have the 595s controlling the base of transistors allowing for an external power source to power the leds once the base is biased. Will the pwm voltage on the base give the same effect as directly powering the leds with pwm?? I am using transistors to limit the load. After all 125×3 leds are being driven. I really appreciate this library, seems like its the only solution in enabling PWM in my project. Most drivers are current sinking this looks amazing. If you could answer my question it would be greatly appeciated. Again thank you!!

        • You could:
          - Source current directly from 595′s. They can officially only provide 70mA total. It is not really recommended, but it works.
          - Use P-Fet transistors on the high side.

          I have plans to make a board with a shift register and 8 high side switches for led matrices, but I just have not found the time yet.

  13. halo @elco;

    can i use 3 datapin with this code? i want to control 3 of my set led, not at the same time. just one of them at time.

    how can i do it?

  14. Hi Elco

    I am a big newbie with arduino and I am going to attempt this project. Thanks first off for putting it online in such a descriptive way (also the youtube video was great too). I was just wondering is it possible to extend this to run more than 8 RGB leds from one arduino? And running them so you can control each one individually.

    Thanks again
    Pete

    • Hi Pete,

      You can chain multiple shift registers together for more outputs, all controlled individually.
      There is a calculator on the ShiftPWM page to show you how many brightness levels you can get for you desired number of LED’s. If you go down in the number of levels, you can use lots of LED’s.

      Elco

  15. Hey man, thanks for this library! What’s the maximum PWM frequency you can get out of this? (Using hardware SPI.)

    I’m working on a propeller clock and want to use RGB LEDs, but I’m going to need a very high PWM frequency (mid-kHz range) to prevent smearing and blank spots. I’m not opposed to having multiple uP’s control multiple sets of shift registers if it would get me a higher frequency.

    The goal is for full high speed PWM control of 32 RGB LEDs.

    Thanks!

    • There is a calculator on the main ShiftPWM page, where you can try out different frequencies and number of brightness levels.
      You can also try uploading one of the examples to your Arduino. You don’t have to have LED’s connected to get the info on the CPU load of your settings.

  16. Hi Elco,

    Can i control rgb leds individually here? I mean if i want to switch ON first one and switch off second one, can i do that?

    Regards,
    Prabhakar

    • You can set the intensity for all LED’s/colors individually.

  17. hi elco,

    first of all, thanks so much for this library!

    i’ve been playing around with the examples, trying to get them to work with piezo buzzers instead of LEDs. i’ve searched on the arduino boards and have seen one project with a matrix of computer fans, which gives me hope, but i haven’t found any examples of how to tweak the code to produce tones.

    i’ve tried different values in the ShiftPWM.SetOne() function, but the tone doesn’t change… if you have any ideas (or can point me to a similar project) i’d be really grateful!

    cheers,
    meg

    • To change the tone, you will have to change the frequency. ShiftPWM changes the duty cycle for a fixed frequency. You can change that frequency, but you will change it for all outputs at once, which is probably not what you are after. There is a tone library for Arduino that is probably more suitable.

      • thanks, elco, i’m going to play around with the tone library and see how i get along. :)

  18. does this code compile on a newer teensy 3.0?

    • I have not had time yet to port this to ARM, so unfortunately: no.

  19. Hi. Thanks for this great, practical advice and instruction, it’s inspired an idea. I have a bunch of common cathode LEDs bought on sale at a price too good. Would it work to use the decoded outputs from the 595s and use them to drive an ULN2003 current sink, using what I have rather than getting new shifter/current sinks/sources ?

    • You are saying you have common cathode LEDs, which means common GROUND. That wouldn’t work well with a current sink, right?
      If they are just 20mA RGB LEDs, 595′s can drive them directly. It is out of spec according to the datasheet, but it works well in practice. A friend of me recently did a 30mA burn in test on all 8 pins and the 595s were fine.

  20. Thanks Elco, I was and still am a bit confused, even though it’s basic and I should just get it. I think I do now. Yes, I have just bargain bin common cathode LEDs, I’ll try them with the 595s and all those resistors – in truth, what I was trying to avoid. For a longer term stable solution (variable low watt lighting), what would you recommend? Common anode LEDs seem to be more widely supported so that’d be a start I guess.

    • If you really want to light up things, pieces of LED strip or high power LED’s might be a better option. I have a driver for both in my web shop and an article on both, if you want to use ShiftPWM. Regular 20mA LED’s are nice to look at, but do not really shine much light onto their surroundings.

      Common anode LED’s are much more popular, because it is easier to make a sink driver. Having ground as a reference is easier.

  21. I just stumbled across your blog – and it reminds me of some work I did last year on a PIC driving (up to 24x RGB LEDs in a similar manner with constant current shift-registers and bit-bashed PWM.

    http://www.youtube.com/watch?v=eewAOwAOzpw

    One other element I added was a high-side P-FET on a hardware PWM pin – to provide ‘all channel’ brightness capability (no gamma correction!).
    I never used the code – but it could happily sustain 72 channels (24x RGB) with 24-bit color mixing and animation functions as shown.

  22. Thanks!!! This saved me so much work. I am building a rain lamp for my wife and am putting LED’s on top to light up the water. I had already planned on using everything in your instructions but having the blueprint and code already written save me tons or work. I used the Mega but since this saved me so much work I’ll probably just use the UNO, burn a chip and go barebones to save me an Arduino.

    If I can remember I’ll send or post pictures of the rain lamp when I am done. I have all of the parts but it may take me a little while.

    Thanks again!!!

  23. Hi Elco,

    i have a little problem. I want to use 2 rgbw leds. your libary only support rgbw. how can i modify pingrouping to use 2 rgbw leds.

    Q0 – Q3 : RGBW1
    Q4 – Q7 : RGBW2

  24. Hi Elco …

    This thread hasn’t died yet! Just a comment (and thanks, library is great).

    I’ve been playing with TLC5916′s, and I think you have a typo regarding the invertoutput; I think you mean to say it should be TRUE (not false), since the TLC5916 sinks the current. I could only get it to work with my common anode RGB’s and invert=true;

    Cheers,
    Eric

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>