• First Steps
  • General
  • Projects
Facebook Twitter YouTube
Tutorials for Raspberry Pi Tutorials for Raspberry Pi
  • Hardware & GPIO
  • Sensors & Components
  • Scale
  • Cases
  • Fingerprint
  • Gas Sensor
  • Heartbeat
  • German
  • French
Tutorials for Raspberry Pi Tutorials for Raspberry Pi
Home»Hardware & GPIO»Raspberry Pi Stepper Motor Control with L293D / ULN2003A

Raspberry Pi Stepper Motor Control with L293D / ULN2003A

Facebook Twitter LinkedIn Tumblr Email Reddit
Share
Facebook Twitter LinkedIn Email Tumblr Reddit Telegram WhatsApp

Stepper motors are ideal for applications where it is necessary to know the angle of rotation, for example in robotics. Unlike a normal motor, stepper motors can control the steps individually and can therefore detect the exact position.
For easy controlling such a motor, a driver IC like the L293D or the ULN2003 are needed. The use of both drivers is shown in this tutorial.

 

The more common of those two is the ULN2003, this is also often included on driver boards with the 28BYJ–48th There is a voltage of 5V and 12V possible.

The L293D however opens the possibility to connect an external power source, whereby for example a higher amperage (which in some motors is necessary) can be connected.

 

Accessories

  • Stepper motor, e.g. the 28BYJ-48 with ULN2003 driver board (US / UK)
  • L293D Driver IC (US / UK)
  • alternatively, if no L293D is wanted: ULN2003 Darlington Array IC (US / UK)
  • Jumper wire (US / UK)
  • maybe an external power source, for example batteries

Of course, you can use any other stepper motor, but it is important to identify the possibly different wire colors when you connect them (see data sheet).

Those colors reflect in my case to the 28BYJ-48 (data sheet):

magn
If you so choose a different motor, consider the case that the colors may be different. Important are the positions and steps.

 

Wiring L293D

If you have a motor with ULN2003 driver board or the ULN2003 driver IC, you can skip this step.

The data sheet shows that an external power source is possible. The structure is thus as follows:

l293d_Steckplatine
It is important to say that if you use an external power source, the + 5V from Raspberry Pi must also be connected to the bottom left pin of the IC (pin 8), in addition to Pin 16.

If the motor amperage required more than the Raspberry can deliver, you must have an external power source (a fixed current source is better than batteries). The pre-resistor is also specified in the data sheet. Pay attention that you have enough voltage and amperage, because that is the most common cause, why the engine later is not working as it should. With the 28BYJ-48 however, this is not the case.

 

Wiring ULN2003

Unlike the L293D, here are only 5V or 12V input voltage allowed (data sheet). Since the Raspberry Pi only has 5V supplies, we can also only use stepper motors that require a maximum of 5V.

 

uln2003_Steckplatine
 

Testing

When using the 28BYJ–48, the sequence is as follows. If you are using a different motor, you have to adjust the sequence corresponding to your data sheet.
So we create a script:

sudo nano stepper.py

and add the following script:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import RPi.GPIO as GPIO
import time
 
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
coil_A_1_pin = 4 # pink
coil_A_2_pin = 17 # orange
coil_B_1_pin = 23 # blue
coil_B_2_pin = 24 # yellow
 
# adjust if different
StepCount = 8
Seq = range(0, StepCount)
Seq[0] = [0,1,0,0]
Seq[1] = [0,1,0,1]
Seq[2] = [0,0,0,1]
Seq[3] = [1,0,0,1]
Seq[4] = [1,0,0,0]
Seq[5] = [1,0,1,0]
Seq[6] = [0,0,1,0]
Seq[7] = [0,1,1,0]
 
GPIO.setup(enable_pin, GPIO.OUT)
GPIO.setup(coil_A_1_pin, GPIO.OUT)
GPIO.setup(coil_A_2_pin, GPIO.OUT)
GPIO.setup(coil_B_1_pin, GPIO.OUT)
GPIO.setup(coil_B_2_pin, GPIO.OUT)
 
GPIO.output(enable_pin, 1)
 
def setStep(w1, w2, w3, w4):
    GPIO.output(coil_A_1_pin, w1)
    GPIO.output(coil_A_2_pin, w2)
    GPIO.output(coil_B_1_pin, w3)
    GPIO.output(coil_B_2_pin, w4)
 
def forward(delay, steps):
    for i in range(steps):
        for j in range(StepCount):
            setStep(Seq[j][0], Seq[j][1], Seq[j][2], Seq[j][3])
            time.sleep(delay)
 
def backwards(delay, steps):
    for i in range(steps):
        for j in reversed(range(StepCount)):
            setStep(Seq[j][0], Seq[j][1], Seq[j][2], Seq[j][3])
            time.sleep(delay)
 
if __name__ == '__main__':
    while True:
        delay = raw_input("Time Delay (ms)?")
        steps = raw_input("How many steps forward? ")
        forward(int(delay) / 1000.0, int(steps))
        steps = raw_input("How many steps backwards? ")
        backwards(int(delay) / 1000.0, int(steps))
 

Then just save with CTRL+O and CTRL+X and quit. You can start it with:

sudo python stepper.py

With setStep(0,0,0,0) you can set the stepper to idle, because otherwise power is consumed all the time (by the electromagnets in the motor).

Regard that if you choose a high delay value (per step), the motor is moving very slowly (e.g. with a 100ms delay one full turn would already take 51.2 seconds, because the engine has a total of 512 steps. Too small delay values may, however, have the opposite effect, so that the signals are transmitted too quickly and causing the motor to just “stuttering”. If you want a faster engine, choose a model with a larger step angle).

python stepper motor uln2003 uln2003a
Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
Previous ArticleUsing a Raspberry Pi distance sensor (ultrasonic sensor HC-SR04)
Next Article Bodenfeuchtigkeit mit dem Raspberry Pi messen

Related Posts

Control all GPIOs with the Raspberry Pi REST API via Python

How to build a ESP8266 Scale (with Weight Sensor HX711)

Using TensorFlow Lite with Google Coral TPU on Raspberry Pi 4

How-To: Bluetooth Connection between ESP32’s and Raspberry Pi’s

32 Comments

  1. Gregory on 27. October 2017 6:22

    My stepper motor only rotates about a quarter of a turn, any siggestions?

    Reply
    • Felix on 27. October 2017 14:25

      Maybe you have another step size/more steps or other intervals. Check the datasheet.

      Reply
  2. Leo P on 16. December 2017 21:19

    The stepping sequence above is wrong for the 28BYJ-48 motor. The correct one is:
    Seq[0] = [1,0,0,0]
    Seq[1] = [1,1,0,0]
    Seq[2] = [0,1,0,0]
    Seq[3] = [0,1,1,0]
    Seq[4] = [0,0,1,0]
    Seq[5] = [0,0,1,1]
    Seq[6] = [0,0,0,1]
    Seq[7] = [1,0,0,1]

    Reply
    • Bogdan on 31. December 2019 1:32

      Works like a charm 🙂
      Thanks

      Reply
    • bill on 17. July 2020 7:23

      Thank you!! this is the correct sequence. You are a gentleman and a scholar!

      Reply
    • Jack VB on 3. June 2021 0:49

      The sequence above works but on the 28BYJ-48 motor it is reversed. According to the data sheet (https://tutorials-raspberrypi.de/wp-content/uploads/2014/08/Stepper-Motor-28BJY-48-Datasheet.pdf) forward direction is clockwise and the correct sequence is
      Seq = [0,1,2,3,4,5,6,7]
      Seq[0] = [0,0,0,1]
      Seq[1] = [0,0,1,1]
      Seq[2] = [0,0,1,0]
      Seq[3] = [0,1,1,0]
      Seq[4] = [0,1,0,0]
      Seq[5] = [1,1,0,0]
      Seq[6] = [1,0,0,0]
      Seq[7] = [1,0,0,1]

      just the reverse of yours.

      Reply
  3. Silvio on 17. March 2018 13:44

    The backward function dont work for me!???

    Reply
    • Felix on 17. March 2018 18:22

      Maybe your motor needs another sequence.

      Reply
  4. Simon on 5. April 2018 22:34

    File “stepper.py”, line 23, in
    GPIO.setup(enable_pin, GPIO.OUT)
    NameError: name ‘enable_pin’ is not defined

    i have this error what can i do?

    Reply
    • Satinder Sidhu on 28. July 2021 3:06

      You need to add following line before
      enable_pin = 18

      Reply
  5. Rich1812 on 23. April 2018 14:50

    What is the point of this article? It is a direct copy of https://learn.adafruit.com/adafruits-raspberry-pi-lesson-10-stepper-motors/overview
    And it does not even copied the diagram correctly.
    Plagiarism, waste of readers’ time!

    Reply
  6. mallamma on 10. September 2018 10:08

    Traceback (most recent call last):
    File “/home/pi/Desktop/stepper.py”, line 14, in
    Seq[0] = [0,1,0,0]
    TypeError: ‘range’ object does not support item assignment ===>i am getting error like this

    Reply
    • Dorian on 11. December 2022 1:47

      Range objects do not support item assignment but lists do, so converting the range into a list should solve this problem.
      try
      Seq = list(range(0, StepCount))
      instead of
      Seq = range(0, StepCount)

      Reply
  7. DANIEL on 13. February 2019 17:13

    DONT WASTE YOUR TIME WITH THIS TUT!
    #CTRLC #CTRLV

    Reply
    • Alcor on 2. April 2019 13:44

      I agree

      Reply
  8. Ed Goss on 7. June 2020 18:31

    I bodged this code like this and it works (although you may well need to adjust the pin sequence / use the change above if you use the 28BJY)

    import RPi.GPIO as GPIO
    import time
    
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)
    coil_A_1_pin = 18 # pink
    coil_A_2_pin = 23 # orange
    coil_B_1_pin = 24 # blue
    coil_B_2_pin = 25 # yellow
    
    # adjust if different
    StepCount=8
    Seq = [
        [0,1,0,0],
        [0,1,0,1],
        [0,0,0,1],
        [1,0,0,1],
        [1,0,0,0],
        [1,0,1,0],
        [0,0,1,0],
        [0,1,1,0]
        ]
    
    
    GPIO.setup(coil_A_1_pin, GPIO.OUT)
    GPIO.setup(coil_A_2_pin, GPIO.OUT)
    GPIO.setup(coil_B_1_pin, GPIO.OUT)
    GPIO.setup(coil_B_2_pin, GPIO.OUT)
    
    
    def setStep(w1, w2, w3, w4):
        GPIO.output(coil_A_1_pin, w1)
        GPIO.output(coil_A_2_pin, w2)
        GPIO.output(coil_B_1_pin, w3)
        GPIO.output(coil_B_2_pin, w4)
    
    def forward(delay, steps):
        for i in range(steps):
            for j in range(StepCount):
                setStep(Seq[j][0], Seq[j][1], Seq[j][2], Seq[j][3])
                time.sleep(delay)
    
    def backwards(delay, steps):
        for i in range(steps):
            for j in reversed(range(StepCount)):
                setStep(Seq[j][0], Seq[j][1], Seq[j][2], Seq[j][3])
                time.sleep(delay)
    
    if __name__ == '__main__':
        while True:
            delay = input("Time Delay (ms)?")
            steps = input("How many steps forward? ")
            forward(int(delay) / 1000.0, int(steps))
            steps = input("How many steps backwards? ")
            backwards(int(delay) / 1000.0, int(steps))
    Reply
    • Lornioiz on 2. October 2020 15:16

      @Ed Goss

      Thank you, your code is working!
      I just don’t get why is woring in reverse and not forward… I don’t get why it works in a direction and not in the other, given that the command are just sent backwards…

      Reply
      • Ctz on 10. February 2021 1:52

        Did you figure it out?

      • Sean Trautman on 12. April 2021 20:22

        Try this seq to fix forward/backward
        Seq = [
        [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]
        ]

      • Duc on 23. December 2022 23:16

        Thank you. It works perfect with your code. I just had to flip A1 and B1 pin numbers.
        This was exactly what i was looking for!

Leave A Reply Cancel Reply

Raspberry Pi GSM Module – Mobile Internet (LTE, 3G, UMTS)

How to build a Raspberry Pi Radio Transmitter

Raspberry Pi Heartbeat / Pulse measuring

Remote Control of Raspberry Pi Robots with an Xbox 360 Controller (Part 6)

Use C# and .NET to develop your own GUI apps for the Raspberry Pi

Run a Raspberry Pi on rechargeable Batteries

Subscribe to Blog
Subscribe to Raspberry Pi Tutorials and don't miss any new Tutorial!
Subscribe

Thank you!

We will contact you soon.

Tutorials for Raspberry Pi
Facebook Twitter YouTube
  • Contact & Disclaimer

Type above and press Enter to search. Press Esc to cancel.