Driving a 28BYJ-48 Stepper Motor & ULN2003 driver with a Raspberry Pi

Quick points about this motor & driver

They are wonderfully cheap and extremely accurate due to 1/64 gearing. They move by 0.087890625° per step! However, the gearing is made of plastic and will wear out overtime, especially if moving heavy objects. Lastly the motors can become a little toasty if you work them hard.

Circuit

Fritzing

Code

#!/usr/bin/python3
import RPi.GPIO as GPIO
import time

in1 = 17
in2 = 18
in3 = 27
in4 = 22

# careful lowering this, at some point you run into the mechanical limitation of how quick your motor can move
step_sleep = 0.002

step_count = 4096 # 5.625*(1/64) per step, 4096 steps is 360°

direction = False # True for clockwise, False for counter-clockwise

# defining stepper motor sequence (found in documentation http://www.4tronix.co.uk/arduino/Stepper-Motors.php)
step_sequence = [[1,0,0,1],
                 [1,0,0,0],
                 [1,1,0,0],
                 [0,1,0,0],
                 [0,1,1,0],
                 [0,0,1,0],
                 [0,0,1,1],
                 [0,0,0,1]]

# setting up
GPIO.setmode( GPIO.BCM )
GPIO.setup( in1, GPIO.OUT )
GPIO.setup( in2, GPIO.OUT )
GPIO.setup( in3, GPIO.OUT )
GPIO.setup( in4, GPIO.OUT )

# initializing
GPIO.output( in1, GPIO.LOW )
GPIO.output( in2, GPIO.LOW )
GPIO.output( in3, GPIO.LOW )
GPIO.output( in4, GPIO.LOW )

motor_pins = [in1,in2,in3,in4]
motor_step_counter = 0 ;

def cleanup():
    GPIO.output( in1, GPIO.LOW )
    GPIO.output( in2, GPIO.LOW )
    GPIO.output( in3, GPIO.LOW )
    GPIO.output( in4, GPIO.LOW )
    GPIO.cleanup()

# the meat
try:
    i = 0
    for i in range(step_count):
        for pin in range(0, len(motor_pins)):
            GPIO.output( motor_pins[pin], step_sequence[motor_step_counter][pin] )
        if direction==True:
            motor_step_counter = (motor_step_counter - 1) % 8
        elif direction==False:
            motor_step_counter = (motor_step_counter + 1) % 8
        else: # defensive programming
            print( "uh oh... direction should *always* be either True or False" )
            cleanup()
            exit( 1 )
        time.sleep( step_sleep )

except KeyboardInterrupt:
    cleanup()
    exit( 1 )

cleanup()
exit( 0 )

Stuff you might need for this to run:

sudo apt-get update --fix-missing && sudo apt-get install python3-rpi.gpio

Results

This motor takes 5.625*(1/64)° per step, this means 2048 steps for 180°:

and 4096 steps for 360°:

One thing that is super cool about the driver board are the LEDs. Projects are always cooler with blinky LEDs, but these guys also help show what is actually going on inside the stepper, and can help you find issues. They are supposed to light up in sequence.

26 Replies to “Driving a 28BYJ-48 Stepper Motor & ULN2003 driver with a Raspberry Pi”

  1. Hi – absolutely brilliant – simple and effective and got me rolling straight away so firstly thanks for putting this up. Not sure if I’ve missed this but I’m trying to import and call 2 versions one after the other ( ie creating a new file / module which calls your 360 version and then a 180 version straight after). However, I’m guessing there’s something in the coding that’s stopping my 180 (or any further) version from executing once the 1st one has stopped. I’ve even added a sleep(5) in between import mod1 and import mod2. Any clues please?

    Much appreciated

    Rik

    1. I’d have to see your code, but importing the snippet I gave as a mean to run it seems like a terrible way to call it :). It’s not a library, it’s a fully fledged (albeit distilled to the essential) program that’s sets up the pins when it starts, and cleans them up when it stops. It’s not surprising it wouldn’t work when you’re calling it twice in the same context.

      The thing to do here, is copy paste my code within your code, and arrange it so the “meat” section is a function you can call at will, ideally with a step count as a parameter.

      I hope this helps.

      1. Hi Ben

        Sorry for my late reply (been mothered with non playing wav files – all sorted now).

        Many thanks for your swift reply and advice. I agree it’s a terrible way to incorporate your script. I’ll look into something else.

        Thanks again – glad I came across your site.

        Rik

  2. Hi,

    I have the motor board powered directly from the raspberry, i execute the script and there is no error message, any idea why it executes but there is no movement from the motors or even the leds? Thank you so much.

    Biel Paloamr

    1. Yes, the Pi can’t supply enough power. It can indeed supply 5V, but definitely not with enough amps. That’s why there’s an external power supply in the circuit. In general physical motion (motors) takes lots of power and doesn’t want to be powered by the logic. Another good reason is that motors often create massive interference on circuits and you don’t want them messing with the logic side, so it’s better to keep them decoupled from it.

      1. To answer your question more specifically about why the code doesn’t error out: it is doing what it is supposed to and activating the GPIO pins properly. From Python’s perspective, everything went well. There is no mechanism for it to be aware that this had no effect on the stepper motor or its driver.

  3. Is the Linux on Raspberry Pi conducive to a stepper motor? Since you need exactly timed pulses to move it a certain amount, would the Raspberry Pi be able to move it an exact number of degrees consistently?

    1. The short answer is yes. I’ve been running various projects for thousands of hours without missing a single step.

      The long answer, and what you are alluding to correctly, is that Pi processors are shared between multiple processes and sleeping a certain amount of time between steps is not guaranteed. Here’s what I found though illustrated as an example. If I sleep for 0.0002 seconds between steps, it’s not guaranteed I’ll sleep exactly 0.0002 seconds, but it’s guaranteed I’ll sleep AT LEAST 0.0002 seconds. In the real world, when I hear my motors step, they have a very consistent sound, but if I SSH into the Pi and start running a bunch of commands competing for the CPU, I’ll hear the motors slow down at bit. Maybe that’s an issue for some projects with CPU volatility and where consistent motor speed being required. But it’s never been an issue for what I’m working on.

  4. Great tutorial it worked for me… How could I connect 2 of the same motors to raspberry pi(to do different things)? is it possible?.. what pins could I use additionally for the other motor?

  5. Thanks Ben for your post.
    It was very easy and useful.
    As I do not have external power supply, I have powered the motor and ULN2008 with Raspberry Pi 4. As said, it perfectly worked.

    What it’s more amusing is that I have descovered your web page. Congratulations. It’s fantastic. This lifestyle and projects are inspiring. They even make me a little jealous. Healthy envy. And they bring back a little hope in the human being. Good luck and good health from Catalonia.

    1. David,

      bon dia, I was very lucky to spend several Summer vacations in Catalonia and I found it to be an incredible place. The culture is strong and the people are super nice. My sister is a Casteller in France, this tradition is exceptional and I show videos of it to my kids. Because they show amazing kids, but also because the exercise is the antithesis of American individualism :). It’s good for them to see both.

      In any case, I won’t bore you with my vacations, but your place is a truly special one in the world, and from it there isn’t much to envy.

      I’m glad I was able to help you drive your motor, and I’m suprised you were able to power the motor with the Pi :). Motors usually wreck havoc on circuits and you want to decouple them from the logic and other sensitive things. But hey, if it works it works :).

      Take care and good health to you too.

      1. Thanks Ben,

        I’m very glad to read your answer. In one of your videos I heard some French, so it makes sense with what you say regarding your sister. For sure she sould be Casteller in Paris or Toulouse.

        USA is a great country, with more diversity than is transmitted through the news and stereotypes. Just a sample: I am writing this after attending a concert in Barcelona by the great Bruce Springsteen. I’m a big fan. He has always been a rebel and a committed man.

        Concerning Catalonia, well,… just trying to preserve language ​​and culture, which is difficult in this globalized world if you don’t have a state behind. But always, keeping the doors open to everyone who needs it, with solidarity, There are millions of people who, just because of their place of birth, have less opportunities than us.

        Best wishes to you and your family.

  6. Hey, Used your code, and it works well BUT, step_count = 4096 makes stepper revolve 4 times.. (360 x 4)…. I reduced step_count to 1024 for 1 360 degree rotation…. So what’s happening here..
    any comment would be appreciated… thanks

    1. That’s really bizarre. Off the top of my head:
      – are you sure you’ve got the same stepper motor?
      – did you change the code in any way? (sorry I gotta cover the basics :))
      – when it moves, is it going at the same speed as the GIFs on this post? Or is is faster/slower?

    2. Ok, so apparently the SAME Stepper (28byj-48) comes in two
      flavors a 1/16, and a 1/64 gear ratio… see adafruit’s 28byj-48…??
      So of cores, with your code they both work but with different amount of steps per 360 degree.. On amazon search both 1/16 and 1/64 to get the right one for your particular need… These steppers draw NO current when all inputs are set to 0,0,0,0.. this is a very good feature as other type steppers always draw current…
      Thanks for your quick response…

      1. Oh wow, I’m glad there’s an explanation. I never came upon the 1/16 ones, thanks for finding out.

        I think that most stepper drivers have a “brake” mode that does draw current to stay in position, and a “free” mode that draws no current but lets the motor move is force is applied externally.

  7. Thanks for the quick-start with the stepper motor! I was playing around with your code and optimized the main for loop. You have to make range() iterate backwards to have the motor reverse, but it only changes the GPIO ports as they need to be changed.

    # the meat
    try:
        for i in range(step_count):
            GPIO.output(motor_pins[(i%8//2 + 2*(i%2))%4], i%2)
            time.sleep(step_sleep)
    
  8. Recommend you update the wiring diagram to connect the Pi and ULN2003 grounds together. Bad things might happen if someone uses a separate AC supply.

    Fun that it works at all. They’re likely grounding through suppression diodes.

    1. You’re entirely right, I think in my test I was using the 2 ports of the same USB power bank so I most likely had shared ground.

      Thanks for pointing it out, it’s updated!

  9. dear friends,
    I tried to rebuild the circuit diagramm as shown above.
    I miss the ground connection between circuit (ULN2008) and Raspi. As a result of this my engine doesn’t work. Secondly I connected the external power supply-ground with Raspi-ground and external (+) with (+) of the ULN2008 circuit, but the result was the same. Zhen I used the +5V and Ground from Raspi for connecting with ULN2008 circuit. This configuration works.
    I want to supply the ULN2008 with an external power supply. How does it works? Can you help me please

    1. Rolf,

      I’m having a hard time understanding what wire was where when things were working or not. Are you saying that you actually powered the motor from the Pi? Even if it works it’s pretty “dangerous” to do so because motors generator a lot of noise on circuits and do you don’t want them hooked up directly to your GPIO pins (expect for the control pins of course). But hey, if it works it works :).

      In any case, are you saying that you have a 5V external power supply, and that you’d like to power both the Pi and the motor with it?

  10. It’s one of the first time I read a tutorial, really “ready to use”.
    I just followed your diagram, copy/past your script, and it works !

    Congrats and thank you 🙂

    1. C’est tellement la lutte pour trouver des informations succinctes et précises sur ce genre de sujet, j’essaye vraiment de poster des infos qui sont les deux. Merci de laisser un commentaire pour me faire savoir que c’est réussi :).

  11. Thank you. This article was clear and concise. It explained very well how the motor works with Raspberry pi. It is exactly what I was looking for.

Leave a Reply

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