Saturday, March 1, 2014

Arduino Shift Register Stepper Motor Controller

This is my first "reader requested" post. A reader sent me an email asking me to do a post about controlling a stepper motor using a shift register, and here it is. In this post I will specifically discuss controlling a 28BYJ-48 stepper motor with a 74HC595 shift register, ULN2003, and Arduino.

First of all, I need to explain what a shift register is. Rather than doing that however, I will differ you to THIS page. It does an excellent job of introducing shift registers and provides some really easy to use sample Arduino code. My code is based off of the functions on that page. I will be using a 74HC595 shift register. I chose it because it is pretty common. I got mine off of eBay, but you can buy them at various vendors.

Second, I should point you to some information on the stepper motor I will be using. It is a 28BYJ-48 stepper motor. It is the same one I used in the two posts(Arduino Control and ATtiny Control). If you need it, those two pages have links to some good reference material.

Third, like in the other cases, I will be using a ULN2003 to drive the stepper. This is pretty common with this board. However, this time I just wired it up on my breadboard rather than using the control board that came with my stepper. I did this because I intended to solder together a whole control board. In the end, I decided I didn't have a need for it at the moment and just left it breadboarded. I can always solder it later.

Now, wiring this project has a few more wires than some of my others, so I threw out all the stops and made a Fritzing schematic. When you look at it, wiring is not terribly complicated; the wires just get crossed easily.

So here is what is going on. The Arduino is controlling the shift register like described in the link I provided above. The shift register outputs are fed into the ULN2003. The ULN2003 acts as a switch and allows the stepper to draw the current that it needs to operate.

One thing you may wish to change, in this diagram I have the stepper being driven by the 5V from the Arduino. It may be wise to drive it from an external 5V source if you are doing more than one. Also, the colors on the stepper (or even the order of the wires) can vary from vendor to vendor. Basically, if the stepper just sits there and grinds against itself, switch the wires.

Another thing that confused me for a little while, the ULN2003 sinks current (as opposed to sourcing current). That is, it allows the output to be a path to ground if the input is HIGH. If you wire the stepper like shown above it should work. The trouble comes when people like me want to test it with an LED before connecting the stepper. I connected the positive end to the ULN2003 and the negative to ground. Eventually, I realized my mistake and switched it. Long story short, to test with an LED, put the "negative" end on the ULN2003 output and the "positive" on 5V.

Here is my setup for this project. The sketch I used is an adaption of one of the sketches from my previous posts. Basically, where there was a digitalWrite I put a setRegisterPin. A potentiometer controls the speed. Get my code HERE

The motor did not turn very quickly (around 10 seconds a revolution), I suppose I shouldn't have expected much more considering all the delays the shift register puts into the system, but if you ever needed to control a large number of stepper motors on only a few pins maybe this would be an option. If you do plan on that, you might note that the ULN2003 only has 7 inputs/outputs, so be sure to get the right number of parts.

Also, it  appears that this sketch could very easily be wrapped into a library. Perhaps the stepper library could be edited to utilize a shift register. Regardless, that is beyond the scope of this post. I leave that to the reader (though feel free to tell us about it in comments).

Hopefully this is useful to someone. If anyone else has suggestions for posts, let me know. The reader requested label is looking pretty lonely.



  1. If I may inquire: What is the point and benefit to throw a shift register (74HC595) between a microcontroller (Arduino) and Darlington driver IC (ULN2003) in this case? I understand this is a "reader's request" experiment but for all practical purposes: Why?

  2. I think he was planning on using it to expand the number or steppers he could control. While using the shift register does slow the process down quite a bit, it does reduce the pins needed. I have thought about trying it with an ATtiny. That would certainly be one situation where output pins are at a premium.

  3. ATtiny also has slower clock, so wouldn't that delay the control even further? It looks like 3d printers (heavy on steppers usage) use ATmega chips.

  4. Yes. I have typically used the ATtiny at 8MHz. You can run it at 20 if you add an external crystal though. I doubt this would be terribly useful in a 3d printing environment. As you say, they typically run on an Arduino Mega with a RAMPS shield.

  5. Fried my uno attempting this circuit and I would sure like to figure out what I did wrong.
    1) Set up the circuit exactly as you have in fritzing diagram.
    2) ran the stepper common (red in your diagram) to 12v p/s sharing a common the common ground.
    3) set up the pot between +5 and gnd with the wiper going to A2 (per your code).
    Everything seemed to work correctly. I started disconnecting, first removing the usb from the uno and saw that it was still powered for several seconds.. Couldn't figure out how since there shouldn't be any 12v going to the uno. Plugged the USB back into the uno and it was dead. With the 12v plugged in (only connection would be backwards threw the stepper and then the 2003a), I made the following checks....

    2003a pin 9 to ground = 12v
    595 pin 16 to ground = 5v
    595 pin 12 and 11 to ground 4.5v

    I have to think that when the uno was connected, it was getting more power than it could handle trough the uno 10, 9 and/or 8 pins.

    Uno is definitely dead. Does anything jump out at you?


  6. First, I'm sorry to hear that you had trouble. When you say you wired everything exactly like i did, the ULN2003 pin 9 and stepper common are not connected to the 5V pin on the Arduino are they? That would obviously do bad things.

    At first I thought maybe your commons were at different voltages, but it sounds like you had that set up right. Basically, I'm not sure. I guess I would double check that your 5V and 12V systems are separated.

    Sorry I couldn't be of more help.

  7. thanks Matthew. No, I didn't have the 5v connected from the arduino. I put this aside for now and will go back to it when I can. Pretty sure there is something I am missing, but time will tell.

    Thanks again.