ShiftPWM: the easiest software PWM library for Arduino

Control many PWM outputs with only 3 Arduino pins

ShiftPWM is a software PWM library for Arduino that uses shift registers to expand the number of PWM outputs. With only 3 data pins, you can control an almost unlimited amount of PWM outputs. Because ShiftPWM is a software PWM library, it is not limited by the number of hardware PWM outputs on the Arduino. Shift registers are also a lot cheaper than dedicated hardware PWM IC’s, like the TLC5940.

Easy to use

The library is written to be as easy to use as possible: It provides intuitive functions like SetRGB and SetHSV to directly set an LED to a certain color. The complexity of calculating PWM values and driving the shift registers is hidden in an interrupt.
The library comes with two examples. The easiest way to get start is to just open an example from the Arduino menu and edit it to suit your application.

To SPI or not to SPI

You can use ShiftPWM with the hardware SPI or without. Using it without the hardware SPI is about 2.5x slower, but allows you to use the SPI port for something else.


For a quick demonstration of ShiftPWM, see the video below. The video is from an older version example that comes ShiftPWM. I will upload a better and more up-to-date video soon when I get my hands on a better camera. My iPhone cannot get the exposure right when filming LED’s.

To give you an idea of how easy it is to use ShiftPWM, the movie below shows the result of this example code.


Getting Started

The easiest way to get started with ShiftPWM is to open one of the examples that come with the library. But first you have to install ShiftPWM.

Downloading and installing ShiftPWM

  1. Go to the GitHub repository the download the latest version of ShiftPWM.
  2. Extract ShiftPWM directory from the archive to your Arduino libraries directory (for example: \???\arduino-1.0\libraries).
    Extract it with the ShiftPWM directory intact, so the result will be \???\arduino-1.0\libraries\ShiftPWM).
  3. Restart Arduino
  4. Open one of the examples from the Arduino menu (File –> Examples –> ShiftPWM –> pick one)

Configuring ShiftPWM

ShiftPWM comes with a number of options to adapt it to various LED setups. These are all set before the   ShiftPWM.Start(pwmFrequency,maxBrightness) is called. Using ShiftPWM with the hardware SPI port is 2.5x faster than not using the SPI port. But if you need the hardware SPI for something else, you do have the option to use any 3 digital pins. See Using ShiftPWM to control 20mA RGB LED’s for schematic and which pins to use.

unsigned char maxBrightness = 255;

This sets the number of brightness steps. More brightness steps will give a higher load on you program. The maximum you can use is 255, because the brightness for each LED is stored as a byte. The value you choose here means fully on. Choosing a lower value only decreases the number of steps, not the actual brightness.

unsigned char pwmFrequency = 75;

This sets the PWM frequency. A frequency above 75Hz makes flickering unnoticeable in most cases.

int numRegisters = 3;

Here you set the number of 8 bit shift registers that you are using. If your setting here is lower than the actual number, your pattern will be repeated. If you are using 4 bit shift registers, still enter the number of outputs divided by 8 and rounded up.

const bool ShiftPWM_invertOutputs = false;

By setting this to true, all outputs will be inverted. If you are using common anode LED’s, you’ll set this to true. When inverting is enabled, a value of 255 will mean that the shift register output is low.


The default setting is that your RGB LED’s are connected like this: RGBRGBRGBRGB. Sometimes however it makes more sense for your hardware to connect them like this: RRRRGGGGBBBBRRRR… In that case you can set the pin grouping to 4. All RGB and HSV functions will take the grouping into account.

How much CPU-time will ShiftPWM take?

ShiftPWM works with software PWM: it calculates the value (high/low) for each shift register pin and updates all shift registers 19200 times per second (at 75Hz and 256 levels). This takes about 5 clock cycles per output pin and a bit of overhead per interrupt. Your own program will be interrupt each time to update the shift registers, so this puts a load on your program. If this load gets too high, your program will become unresponsive. You will have to choose the number of brightness levels and the frequency to keep the load at an acceptable value. With the calculator below you can estimate the load. A value of 0.5 means that 50% of the CPU time will be used by ShiftPWM.

The real value of the interrupt load can be determined at run time with the function ShiftPWM.PrintInterruptLoad(), which prints the data to the serial port.

Version: Number of registers: Max brightness (=#levels-1): PWM Frequency (Hz): Clock Frequency (MHz):
Interrupt load: Interrupt frequency (Hz): Interrupt duration (clocks):


Debugging ShiftPWM

ShiftPWM has a few built-in checks to prevent errors. Whey you try to apply settings that will cause the load to be over 0.9, it will print an error to the serial port. When you try to write to an output beyond the number of shift registers you defined, it will also print an error. So keep an eye on the serial output when working with ShiftPWM.

Available functions

ShiftPWM comes with a number of useful functions to control LED’s and to debug your setup. You can find all of them in the ShiftPWM function reference.


I have written 3 articles to help you build your LED circuits. Take a look at the article for normal LED’s first, because it covers some of the basics of using ShiftPWM.

I have written separate articles for high power LED’s and LED strips. You can also buy ShiftPWM compatible boards for power LED’s and LED strips in my shop.

Using ShiftPWM to control normal RGB LED’s

Using ShiftPWM to control 350mA high power LED’s

Using ShiftPWM to control RGB LED strips


If you have a problem getting ShiftPWM to work, please first check this support topic on the Arduino forum.

The old ShiftPWM page

This ShiftPWM documentation was updated on August 9, 2012. You can still find the old ShiftPWM page here.


  1. Heya,

    i just wanted to thank you for this great library and your efforts in updating this page – i really appreciate your work! As a arduino-beginner it really helped me with getting my shift-registers to work, and I intend to use your ShiftMatrixPWM functions for my first “real” project – looking forward for the update on those :).


  2. Greatttttttttttttttt…………..

  3. Elco! Love the update

    Just hooked up a board with 5 shift registers, using the non-SPI version of the code, and i’m seeing substantially less brightness from the LEDs attached to the last two registers. Any insight?

    • Hi Joe, sorry for the late response. The release of BrewPi has taken up all my time.
      Are you still having this issue? Have you checked the supply voltage?
      A valueable test is to take skip one of the earlier shift registers and see if the problem moves as well. Then you know whether it’s a hardware or software problem.

      • Man, you do not have to apologize at all. you just hit SLASHDOT!
        Unfortunately, i am a goodfornothing hobbyist, and my multimeter is broken. i will update when i get some results.

        next problem: its a persistence of vision toy, and i’m seeing a pretty bad update lagtime, resulting in gaps shown here, using

        for(int j=0;j<maxBrightness;j++){
        for(int i=0;i<40;i=i+3){


        is it because i’m running nonSPI? updating using SetOne?
        i know youre busy, don’t feel bad taking your time. you are SUPER AWESOME keep doing what youre doing.

        delete that other response, i goof’d.

        • Scratch that. Frequency, got it.

          • What you are seeing is the PWM cycle. PWM is very fast on/off. The on/off ratio determines the brightness. The on off switching is invisible because your eye is slow. Now when you are swinging it around like that, the flickering is not invisible anymore. You will need to go to a frequency that is much higher. You can use the calculator on my website to see which setting would be best and you can compare SPI and Non-SPI.

  4. Thank you very much! :D
    That’s what I’ve been searching for half a year…
    Unfortunately it will take me a few weeks to understand everything.
    I’m not so far in Arduino but I’ll get it.
    Thank you!

  5. Im working on a POV Globe like this one

    Was wondering if its possible to run your ShiftPWM on something like that. I plan on running the ring at 900 rpm, so it has to refresh the columns a lot. I plan to run about 128-192 columns and 64 rgb leds. I put in the number of shift registers (24) but am unsure of the refresh rate needed, I will have it built within a month but am trying to plan the code out somewhat.

    • That looks really sweet!
      With a spinning LED, you will be smearing out the PWM period, so your duty cycle becomes a line segment length. You want to keep the period really short, so the update frequency high to make these line segments short and have a high number of segments. 900 rpm is pretty fast, that’s 15Hz. So if you want 100 line segments, you want your PWM frequency to be 1500 Hz.

      It is a trade off between vertical resolution (#registers), horizontal resolution (frequency) and color resolution (brightness levels). You probably want to switch to a new column at each zero crossing in the PWM cycle, so you will have to add that to the interrupt.

      • Its definitely a challenge, I was looking at your calculation tool, for brightness, is that the number of brightness levels?

        If so 24 registers with 1500hz pwm and 7 brightness levels is possible. Its far better then the 8 colors the globe I posted above had.

        I was also looking at the new Arm boards, Teensy 3 and the DUE.
        The extra MH’z could be useful if it can run on them.

        For me the biggest problem is coding, im still very new to C programming.

        • That is indeed the number of brightness levels, I have changed the page to make that more clear. ShiftPWM has not been ported to ARM yet, so your best shot will be the teensy++ 2.0. It has more code space than a normal Arduino. I do plan to port ShiftPWM to ARM, but for now I am far to busy with BrewPi.

  6. Hi! this is great!
    You talk about using SPI, do you have a SPI device? In case of which is the one you use? Or its just driving SPI directly to 74HC595? . I am new using SPI.

    • It is using the SPI to drive the shift registers. Shift registers use a protocol that is almost the same as SPI.

  7. Great lib! this is fast enough to control 16 RGB LED strips over DMX. Would be nice as offline PWM generator controlled via I2C bus. then, one Arduino may act as interface, an other connected as i2c slave, will output PWM.

    • There is a load calculator on the main page. That will tell you exactly how many brightness levels you can get for a certain number of LED’s, without overloading the CPU too much. The load is spread out pretty well, so one Arduino might be able to do both tasks at once.

  8. Wonderful library!

    I would like to know if it is possible to run shiftPWM with SPI if you add a flash memory card to the Arduino project? So I can have music and output running from memory card.

    • Most SPI devices have a slave select input. With that input you can get your memory card to not listen to the SPI unless you tell it too. The shift registers don’t really have such an input, but the Shift registers won’t put new data on the output unless you pulse the latch pin. So just disable the timer interrupt while you talk to the memory card.

      You could also use the non-SPI version of ShiftPWM (uses any 3 pins), but it is about 2.5x slower.

  9. Whats the maximum frequency this lib supports?

    • There is a calculator on the main ShiftPWM page. If you use less brightness levels you can go pretty high in frequency. Just upload one of the examples to your arduino without LEDs to try it out.

  10. Hello,

    I see a couple references to servo.h, but no examples on wiring or coding. Are there any working demos for running multiple servos?
    I’m trying and failing to get the tlc5940 to run my servos so I thought I might try this library.

    I’m using 595 already so this library might fit right in if it will run my servos too? I just want to control up to 16 micro servos.

    Thanks for any feedback and help.

    • I haven’t used ShiftPWM with servos. I think it would be pretty hard to get a decent resolution out of it, because you need to squash your full resolution in about a millisecond. The references to servo.h are because ShiftPWM will use timer2 when timer1 is in use by the servo library. Sorry.

    • fyi, check for a tlc5940 servo demo

  11. Hi –

    I’m using your ShiftPWM library for a project that uses white LEDs (not RGB LEDs). I was wondering what settings I need to tweak in order to trick the code into the correct pin group setting for my particular setup.


    • You can just use the SetOne or SetGroupOfx functions

  12. Do you have the library for the raspberry pi planned to provide?
    The Raspberry Pi has a larger CPU that a larger quantity of 74HC595.

    • Not in the near future. I am too busy with my other project, BrewPi.

  13. Hello,

    i dont understand i checked your code it does everything but sending commands to the shift registers
    i cannot also find the interrup usualy used
    anoother question is that i try to do the same but for a 6×24 led panel

    is this feasible?
    i can achive the code to be working, but it is so slow that instead of pwn, i get leds blinking for low pwm freq values

    • The interrupt is in ShiftPWM.h

      Do you have the LED’s configured as a matrix or are all registers in one chain?

  14. Hi nice work! I love the video.

  15. Hi Elco,

    Can you tell me what to change in order to get ShiftPWM working with the Arduino MICRO?

    I want to use it on my motorbike for controlling rear / brake light

    • The Arduino micro uses the same chip as the leonardo, so it should work without any changes.

      • Hi Elco,
        I’m afraid not. Using the Arduino environment and choosing the MICRO board, the compiler gives errors. When I choose as a board the UNO, it compiles fine. Leonardo also gives errors

        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp: In member function ‘void CShiftPWM::InitTimer2()’:
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:356: error: ‘TCCR2B’ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:356: error: ‘WGM22′ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:357: error: ‘TCCR2A’ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:357: error: ‘WGM21′ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:358: error: ‘WGM20′ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:366: error: ‘CS22′ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:366: error: ‘CS21′ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:366: error: ‘CS20′ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:370: error: ‘CS22′ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:370: error: ‘CS21′ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:370: error: ‘CS20′ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:375: error: ‘CS22′ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:375: error: ‘CS21′ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:375: error: ‘CS20′ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:379: error: ‘CS22′ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:379: error: ‘CS21′ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:379: error: ‘CS20′ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:383: error: ‘CS22′ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:383: error: ‘CS21′ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:383: error: ‘CS20′ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:387: error: ‘CS22′ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:387: error: ‘CS21′ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:387: error: ‘CS20′ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:394: error: ‘OCR2A’ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp: In member function ‘void CShiftPWM::PrintInterruptLoad()’:
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:462: error: ‘OCR2A’ was not declared in this scope
        C:\Users\BvdP\Arduino\libraries\ShiftPWM\CShiftPWM.cpp:483: error: ‘OCR2A’ was not declared in this scope

        • I have no problems with the latest version from GitHub and Arduino 1.04.
          I just cloned the repository into the Arduino library directory and opened one of the ShiftPWM examples.

  16. Hi Elco

    I’m using the Arduino IDE 1.04 on a Windows 7 machine. The errors listed persist. When I choose the UNO board it compiles fine.
    I have just received a UNO board, so I will use that board, but I would still like to be able to use the MICRO board. If you say it should work, please help me find out why the examples do not compile with the Micro board selected.


      On that line I check whether timer2 exists for the chosen processor. It should not be defined when using the atmega32u4 and the lines that generate the error for you should not be included. I am not sure why the compile time #if fails on your system.

      • I don’t know either why it fails, but it fails. Can you please look into the code and solve this problem for me?
        Are there any users out there experiencing the same problem OR are there any users of the MICRO that do not have this problem?

        Please respond, users!

        • It is hard for me to fix the problem when I cannot recreate it.
          For some reason, your Arduino environment doesn’t include the right headers files I think, or it doesn’t work well with #if defined( )

          Your errors indicate that the compiler cannot find registers for timer2, but on line 355 I just checked that it is defined.

          Are you just compiling the example? Are you not defining that register somewhere else?

          I can compile for the micro just fine. Also running 1.04 on win7. Try reinstalling everything.

          • Hi Elco, sorry for the late reply. I was experimenting with my Uno board, so I did not try the Micro board further. I will reinstall everything and see if the problem is still there. Yes, I tried to compile the samples without any change.
            For now I have not much time to investigate further, so I’ll contact you in about a month from now to give you the results.

          • Hi.
            I’ve encountered the same problem on Leonardo and Micro.
            Link in the main article ( now leads to old version of library (dated as 2012-aug-15) with the issue. I’m not familiar with GitHub but on page the library is compatible with Micro/Leonardo.
            It seems you just need to renew the download page on GitHub and it will fix the problem.

          • Thank you for solving that mystery! I just deleted the download. GitHub has a nice ‘download as zip’ button that should work just fine.

  17. Hi Elco,

    The library is working well for me within the Arduino IDE.

    However, I’d like to be able to #include “ShiftPWM.h” within another h file I am using in my project. When I try to do this, I see errors that ‘__vector_11′ and ‘ShiftPWM’ have multiple definitions.

    Error can be reproduced by simply making a library file ‘Test.h’ or something, containing only the line “#include ‘ShiftPWM.h”, and importing that test library file into an arduino sketch.

    Running on Mac OS 10.8. I have the latest version of the code from the github repo.

    Any suggestions would be appreciated. Thanks, and keep up the good work.


    • Normally, this line prevents including a file twice:

      But Arduino compiles libraries separately in a strange way, which causes errors when one library is included in another. Maybe you could try this:

      • Thanks for the quick reply.

        I’ve got the #ifndef/#define/#endif paradigm implemented on multiple other libraries and am able to #include them within each other with no issues.

        To isolate the issue, I’ve done the following:

        Without editing your source code at all, I made ‘Test.h’ and ‘Test.cpp’ and put them in the folder: /libraries/ShiftPWM/.

        Test.h defines values for clockPin, dataPin, latchPin, invertOutputs, and balanceLoad, vis-a-vis the example provided.

        Test.cpp only contains ‘#include “Test.h”‘

        My arduino sketch I am using to test only has the lines:

        #include “Test.h”
        void setup(){}
        void loop(){}

        My compiler complains:

        ShiftPWM/test.cpp.o: In function ‘__vector_11′
        [path]/ShiftPWM/ShiftPWM.h:195: multiple definition of ‘__vector_11′
        testSketch.cpp.o: [path]/ShiftPWM/ShiftPWM.h:195: first defined here
        ShiftPWM/test.cpp.o: In function ‘__vector_11′
        [path]/ShiftPWM/ShiftPWM.h:195: multiple definition of ‘ShiftPWM’
        testSketch.cpp.o: [path]/ShiftPWM/ShiftPWM.h:195: first defined here

        The line they are referring to is:

        ISR(TIMER1_COMPA_vect) {ShiftPWM_handleInterrupt();}

        I’ve seen posts about other arduino users getting this error when they try to use two libraries (such as Servo and Tone) that both want to use timer1. I am just confused because I don’t believe it’s an error on my part, I believe the #ifndef line would prevent arduino from defining these variables multiple times, and I’ve tried to eliminate all other sources of error possible.

        Any further thoughts? Thanks again.

        • I think the root of the issue is that I define the ISR in a header file.

          Defining a function in a header file is not the way one should program C++ normally. Header files should only include prototypes, function bodies should go into cpp files.

          The reason I do it though is the following:
          - The user sets the pin numbers in the main sketch (which is added to main.cpp).
          - With ShiftPWM.h in the same file, the compiler is able to resolve the pin numbers at compile time. This results in much faster bitset and bitclear instructions.

          If you can figure out a solution that is just as fast, but more flexible, please let me know. Or even better: send me a pull request on GitHub!

  18. Hi! This lib it amazing! But I have a question: can I use this library with this schematic?


    • That is a schematic for a matrix setup.
      ShiftPWM works for one long chain of shift registers, not a matrix setup.
      I started on a matrix version a while ago, but didn’t have time to fully complete it. I could put the result so far on GitHub for others to finish though.

  19. Hi,

    I want to implement Shift PWM in my project. Im using an Arduino Due (ARM Sam Processor). What do I need to change to make it work? Or do you have some kind of “beta” available? As far as I saw, you just need to change the Port-mapping, don’t you?


    • The Arduino DUE is ARM, a completely different processor. ShiftPWM is highly optimized for the instruction set of AVR and will not work with ARM. I have not had time to create an ARM version yet.

  20. Hello! Is this possible to switch another SPI device for a time? e. g. enable SD card, read data from it, then disable it, and then enable registers and send data to them? Or I should use non-SPI connection, or two different Atmega328 (where one reads from SD, and other is BAM synthesizer with ShiftPWM, with communication between them via I2C/Serial)? I need to control 9 registers (24 RGB LEDs), non-SPI eats lots CPU time.

  21. hi! when trying to download, i get “There aren’t any uploads for this repository.”

    • They were outdated, so I removed them. Use the ‘download as zip’ button instead.

  22. Can the ShiftPWM Library be used by the ATtiny 84 or 85?
    Tried to compile the example sketch(edited out the serial stuff),
    but cant seem to get it working:-(
    I am not really very good at this, so I was wondering if
    there might be a quick fix(long shot);-)

    Any tips?

  23. Hello,
    I have your library working well with my basic register setup and line of leds. What I also need/want to do is control some other devices, namely small hobby DC motors off the same set of output registers. I have the DC motor hooked up via a SN754410 H-bridge and I’m actually able to control it by just wiring one of the register outputs to the h-bridge enable pin. So when I use SetOne on the register pin to the h-bridge it activates the motor in a PWM manner; I can even fade it on/off. However the issue is that when I want 100% full on using maxBrightness value, the motor is not getting to full speed. I assume this is due to frequency set in ShiftPWM library at Start time.
    How might I control a pin on the register bypassing the control of the ShiftPWM library on that pin, so I could set it myself (100% on, no PWN)? I know how to write my own values to the register, however ShiftPWM is probably going to overwrite any values I write there?
    Thanks for the ShiftPWM library, its very useful.

  24. Hi Elco,

    Great library.

    I’m using ShiftPWM to control LEDs. I’ve got a lot of them, and turning them on and off rapidly produces large voltage swings on my power lines. I have other sensors on my board that are affected by these voltage swings. So, the more I can smooth the swings, the better.

    Is there a way to tweak your library so I can “alternate” the PWM signal? For example, If I have 16 LEDs on at half brightness, instead of them all turning on at the same time and off at the same time, could the duty cycles of half of these LEDs be inverted? That way, 8 LEDs would be on and 8 would be off at any given time, reducing the swings on my power line.

    If the library already does this, then well done, and I suppose I’ll keep adding big fat decoupling caps and hoping for the best.

    Otherwise, any help would be appreciated. Thanks!

    • bump

      • bump again!

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>