Raspberry Pi Stepper Motor Control with L293D / ULN2003A

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 28BYJ48th 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.



  • 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):

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:

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.




When using the 28BYJ48, 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:

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).

30 Responses

  1. 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]

  2. 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?

  3. 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

  4. 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
    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
    Seq = [
    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])
    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])
    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))
    • @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…

      • Try this seq to fix forward/backward
        Seq = [

Leave a Comment

Your email address will not be published.

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