ShiftPWM

ShiftPWM is a software PWM library for Arduino. It uses the SPI to drive shift registers in the most efficient way possible. This makes it possible to control 768 LED’s at 32 brightness levels for a fraction of the price of dedicated led drivers. Code for HSV to RGB conversion is included for easy color shifting.

ShiftPWM rainbow on a breadboard

The LED rainbow from the ShiftPWM example

What is ShiftPWM?

ShiftPWM is a library for Arduino to control many PWM outputs using shift registers (for example the 74HC595). I wrote it for my job at the Electronics Atelier of Industrial Design at the Technical University of Eindhoven, where I often got the request to individually control the brightness of many LED’s.

The dedicated IC’s for PWM, for example the TLC5940, are expensive. Generating the PWM in software costs a few CPU cycles, but allows you to use much cheaper hardware. ShiftPWM does this very efficiently, allowing you to control up to 768 outputs with ease.

ShiftPWM computes the outputs in a timer interrupt and uses the SPI to control the shift registers as fast as possible.

Features of the library:

  • Control the duty cycle of many PWM outputs in a single shift register chain.
  • Easily configure frequency, number of registers and number of brightness levels.
  • Outputs can be inverted for common anode RGB LED’s
  • Function to print information on timer settings and interrupt load to the serial port.
  • Switches to timer2 if timer1 is in use by the servo library
  • Checks for input to functions that is out of range and prints error messages to the serial port
  • Can be placed in the libraries directory of Arduino
  • Includes an example which can be opened in Arduino via file->examples
  • Example includes HSV to RGB function for easy color shifting with RGB LED’s.

How fast is ShiftPWM?

ShiftPWM computes and transfers the bits for one shift register in just 43 clock cycles. The load on your program can be calculated by the following formula:

  • Load = Interrupt frequency * interrupt duration / clock frequency
  • Interrupt frequency = PWM frequency * number of brightness levels
  • Interrupt duration = 112 + number of shift registers * 43 clock cycles.
  • In one formula: L = F*(Bmax+1)*(112+43*N)/F_CPU

Here is an example of the load on a 16 MHz Arduino Uno:

Shift registers Maximum Brightness PWM Frequency Load
3 255 75 Hz 0.29
6 255 75 Hz 0.45
24 100 75 Hz 0.54
48 64 75 Hz 0.66
96 32 75 Hz 0.66

 

Where can I get ShiftPWM?

ShiftPWM is hosted on Google code here, Download link on Google code

New version moved to GitHub, extract to Arduino-1.0/libraries/ShiftPWM:

Download an archive of the latest release

11-05-2012: New version on GitHub has easier to use RGB and HSV functions, support for gaps of unused pins (offset), pin grouping (RRRGGGBBBRRR… instead of RGBRGBRGB), an option to not use the SPI (2.5x slower) and new examples. Documentation will be updated soon.

How do I use ShiftPWM?

The easiest way to get started with ShiftPWM is to start from the example that comes with ShiftPWM:

  1. Download ShiftPWM from Google code
  2. Extract the archive in the library directory of Arduino.
  3. Restart Arduino
  4. In Arduino, go to File -> Examples ->ShiftPWM

Which hardware is used with ShiftPWM?

Basically just an Arduino and a chain of Shift registers. The circuit is almost the same as in the ShiftOut tutorial on arduino.cc, but it uses pin 13 as clock and pin 11 as data. You can choose the latch pin yourself, but the data and clock pins should be connected to the SPI pins MOSI(11) and SCK(13). Leave out the latch pin capacitor!

High power led driver

I have designed a ShiftPWM compatible LED driver to drive 3W RGB LED’s. It has 6 STP04CM05 LED drivers, so it can drive 24 channels at 350 mA. That’s a total of 8A per board, but of course they can be chained. I use 3 of them in my Ambilight project go get 24 independent 3W RGB LED’s. The maximum LED current can be set with a potentiometer from 60-350 mA. I designed them for my own project, but I am considering getting a small batch (100) made to sell. Let me know if you are interested.

My 24x 350 mA LED driver with an Arduino Uno for size comparisson.

What’s in the example?

The example that comes with ShiftPWM demonstrates the use of all ShiftPWM functions. It also includes a function to convert HSV to RGB to make it easier to work with RGB LED’s.

Here is a video of the example with 16 RGB LED’s:

Function overview

The library provides the following functions:

ShiftPWM.Start(int ledFrequency, int max_Brightness)

Enable ShiftPWM with desired frequency and brightness levels.

ShiftPWM.SetAmountOfRegisters(int newAmount)

Set or change the amount of output registers. Can be changed at runtime.

ShiftPWM.PrintInterruptLoad()

Print information on timer usage, frequencies and interrupt load.

ShiftPWM.SetOne(int pin, unsigned char value)

Set the duty cycle of one output

ShiftPWM.SetAll(unsigned char value)

Set all outputs to the same duty cycle

ShiftPWM.OneByOneFast()

Fade in and fade out all outputs fast

ShiftPWM.OneByOneSlow()

Fade in and fade out all outputs slowly

ShiftPWM.SetGroupOf2(int group, unsigned char v0, unsigned char v1);

ShiftPWM.SetGroupOf3(int group, unsigned char v0, unsigned char v1, unsigned char v2);

ShiftPWM.SetGroupOf4(int group, unsigned char v0, unsigned char v1, unsigned char v2, unsigned char v3);

ShiftPWM.SetGroupOf5(int group, unsigned char v0, unsigned char v1, unsigned char v2, unsigned char v3, unsigned char v4);

Set a group of outputs to the given values. SetGroupOf3 is useful for RGB LED’s: each LED will be a group then.

Assumes that all groups are size x for the function SetGroupx.

Gallery

If you used ShiftPWM to create something cool, please send me a link to a video. I will create a gallery page to show off all the cool projects.

Support

Please ask support questions in the Arduino forum here

31 Comments

  1. I was constructing a board to run 24 3w rgb leds using constant current drivers, but your board design seems to be much more compact and cheaper to manufacture. Could you post your schematic file on google so i could see the general layout of your ic’s since i am unfamiliar with those chip drivers. Also, are the capable of running all 4 channels at 350 mA steady?

    • The board has 24 PWM channels, so it can drive 8 3-pin RGB LED’s at 50 to 350 mA, settable with a potmeter.
      The biggest issue is heat, therefore i power the board from a 5V PC power supply -> huge diode -> board. The board has to dissipate 0.7V less that way.

  2. Do you have the wiring schematics for the circuits used in your example videos??

    • It’s on my to do list, but I have been terribly busy lately. All LED’s go with a resistor to the shift register outputs and share a common anode (V+). You will have to calculate the resistors per color, being (5V-Vfw)/20E-3A. For a Vfw=2V, this would be 150 Ohm.

      The shift registers are in one long chain. From pin 0 of registers 0 to the last pin of the last registers the outputs are RGBRGBRGBRGB…

  3. Do you have a rough idea how hard it would be to rearrange the data format in such a way that the LEDs can be addressed as RRRRRRRR – GGGGGGGG- BBBBBBBB etc. This would allow to use constant current drivers and hardware color balancing.

    • I redesigned my high power led driver to have adjustable current per color, so I will update the library soon to have this option.
      Somewhere next week I’ll upload a new version.

      • I figured it out. Didn’t work at first, as I was doing the math wrong. I’ve attached a youtube link for the ‘gallery’.

        • Hi Robert,
          Your video looks great! I’m wondering if you wouldn’t mind sharing the code with me? I am up against the same dilemma in a project that I am working on.

          Best,
          Sarah

          sarah.bearse@gmail.com

          • Hi Sarah, I’ve just seen your question.

            You can find all of my code/layout related stuff on Github.

            http://www.github.com/madworm/

  4. Hallo Elco,
    Ik heb je gevonden via Serge Offermans, een collega van de TU. Hij vertelde me dat je pwm library sneller is dan de library voor de tlc5940. Klopt dat?
    Ik wil een pov project doen en de tlc5940 is een beetje langzaam daarvoor.
    Groeten,
    Rob

    • De library is in ieder geval een stuk vrijer te configureren. Je kunt zelf de PWM frequentie kiezen en het aantal brightness levels. Hierdoor kun je ook hele hoge frequenties nemen met een beperkt aantal brightness levels in plaats van de default 4096 van de 5940.

  5. Just wanted to post my project that makes extensive use of the ShiftPWM library. It’s an RGB scoreboard specifically for Ultimate Frisbee games. The entire display is being controlled by 11 daisy chained 8-bit shift registers. Thanks for the great library!

    [youtube http://www.youtube.com/watch?v=Q-YWABsCgqs&version=3&hl=en_US&rel=0

    • Very impressive build Tom! Rigid case and very user friendly interface. Do you match the LED’s to the players’ shirt color?

      • Yes… that’s the plan. Before the game starts you can match the colours to what’s on the field. The only thing I haven’t quite figured out is what to do when one of the teams is wearing black. :P

        Tom

  6. ELCO!

    Firstly, thanks so much for the use of this library, it’s made my deadline far less intimidating.

    I’m a long way from achieving what I set out to do, but finished building the hardware today and implemented a basic code. More will come by Wednesday when I install in a window in Mayfair. I hope to achieve the effect of raindrops falling into a puddle.

    http://vimeo.com/m/35844283

    Thanks again, I’ll keep you posted with developments.

  7. The finished article. Thanks again for sharing.

    http://vimeo.com/36027461

  8. Hi,

    I was wanting to know how, if possible, to switch from using timer2 to timer1?

    Thanks,
    Nick

    • Hi Nick,

      Timer1 is the default. Only if servo.h is included, it switches to timer1.

      Elco

      • So you use pins 9 and 10 on an uno? because you say to use 11 and 13.

        Thanks again,
        Nick

        • Why would they be different? I say its 11 and 13, because it is 11 and 13. The MOSI and SCK pins. The timer outputs are not used, the timer is only used to generate an interrupt.

  9. Hi thanks, Do you know if there is a way to not to use 11 and 13? I am trying to make an led controller with dmx inputs and this also uses the same pins for the timer.

    • I am also interested in using other pins. How would I go about changing pins 11 and 13 to pins 5 and 7. Since you are using MOSI, I assume we would have to include SPI.h.

      • I have e-mailed you the version without SPI, because I don’t have time to update the website at the moment.
        Because it doesn’t use hardware SPI, you don’t have to include SPI.h and it is 2.5x slower.

  10. Hi, thank you for the excellent information! I am working on a 100 RGB LED display and have been searching every where for help and then I found your article. Awesome. If I understand the math correctly (I may not) I’ll need 39 595′s to run these 100 LEDs. Is this correct?

  11. Elco, thank you for the confirmation of my math (that darn 9 is right next to the 8…) I checked out your friends clock, he did a great job on it. I really the the concept behind it.

    When I finish my project I’ll try to post it. Don’t really know how to do that yet, first need to concentrate on my project.

    Again, thank you for all the great info on this site. I know it takes a lot of time.

  12. Hi,

    GREAT STUFF!!!
    I am working on animating wire framed LED displays. I want to use ShiftPWM as well as control 16 separate relays(on/off) with Vixen. Could any one point me in the right directions

    • You could use ShiftPWM for both if that’s easier. You can switch the relays by writing zero of maximum brightness. A PWM value in between would not work, because the relays are too slow for that. Switch the relays with a transistor and use a diode in reverse parallel to the relay coil to protect the transistor from induction currents. I use relays in my UberFridge project, so look there for schematics.

      For your LED displays, you will probably want to place transistors behind the shift registers.

  13. Hi Elco
    thanks for the code, just getting my head around it. I’m unfamilar with some of the terminalogy and in pariticular load. I’m interested in understanding if running this code will allow me to do other stuff in the main loop and how much your code will effect this, it seems to me that a load of 0.66 means that for the rest of the time I can do stuff and that you code will not effect this, is that correct? Not sure what 0.66 refers to but assume that its a percentage for time taken in the cpu. (i was thinking of putting in capSense hence my question)

    • You are correct. By a load of .66 I mean that the CPU will be busy with the ShiftPWM interrupt 66% of the time. The capsense function would be interrupted by ShiftPWM, but I don’t expect this to be a problem if the interrupt frequency is fast enough. It will just make the charge time measured by CapSense faster.

      • Thanks for that Elco
        that makes it a lot clearer :) Look forward to using the code.

Trackbacks/Pingbacks

  1. TIMO TOOTS | Elektron - [...] custom scripts, ShiftPWM library, EasyTransfer [...]

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> <pre lang="" line="" escaped="" highlight="">