Författare:
Per Stenebo
Skapad:
2019-10-27 17:43:25
Ändrad:
2020-06-04 18:06:02
en

Unipolar stepper motor with driver

Description on how to connect and code for a 28BYJ-48 and ULN2003 with a Raspberry Pi.

28BYJ-48 is a 5 VDC unipolar stepper motor. ULN2003 is the main component on the driver board. This circuit is fed from a 5 VDC power supply but the signal connections can handle both 3.3 volt (like from a Raspberry Pi) and 5 volt (like from an Arduino).

There are plenty of tutorials about this motor, some even with this driver board, but none (as fas as I know) with this exact combination of motor, driver and controller. As I was new to this kind of motor I have spent many hours searching and testing, an effort I hope to save someone else with this page.

28BYJ-48 motor and ULN2003 driver

External resources

I have bought these as a Luxorparts kit from Kjell & Co.

Most info, images and code compiled from the following sources:
| instructables.com | Raspberry Pi Tutorialsseeedstudio.com42bots.com |

 

Wiring

GPIO pin Driver pin Motor wire
GPIO #4 IN1 Blue
GPIO #17 IN2 Pink
GPIO #23 IN3 Yellow
GPIO #24 IN4 Orange

 

Connection chart with separate power sources (recommended):

Connection chart 2 -alternative location

Connection chart with common power source:

Connection chart 1 -alternative location

You can of course choose any available GPIO pin but you need to adjust the code accordingly. Remember that driving stepper motors is all about signal order, keep track of your changes.

You can (and should) have a separate power supply for the controller and the driver/motor. If so, remember to connect a ground wire between the controller and the driver so they have a common reference.

The LEDs and the resistors (330 Ω) on the breadboard are just for fun (and for troubleshooting). You can skip these.

The capacitor (100uF 50V) are also optional, it mitigates power surges from the motor, causing voltage drops to the controller. Use separate power supplies instead.

 

Troubleshooting

Resistance between motor wires, motor disconnected from the driver board:

Orange    Red        21,9 Ω
Yellow    Red        21,8 Ω
Pink    Red        21,7 Ω
Blue    Red        21,7 Ω

Blue    Pink    43,4 Ω
Blue    Yellow    43,4 Ω
Blue    Orange    43,5 Ω

Pink    Yellow    43,3 Ω
Pink    Orange    43,5 Ω

Orange    Yellow    43,5 Ω

The motor includes a gearbox with high ratio, about 63:1. When using the default delay of 5 ms between each step, the visible gear still turns quite slow. The high ratio also makes the gear somewhat self-locking. The gears will break if you try to turn the motor from the visible shaft.

 

Code for python 3 (preferred)

#!/usr/bin/python3
# coding: utf-8
'''
sudo apt install python3-dev python3-rpi.gpio
Run with: python3 stepper.py
'''
import sys, signal, time
import RPi.GPIO as GPIO


#-----------------------------------------------------------------------
# Functions (inline)
#-----------------------------------------------------------------------
# Manage ctrl+c
def signal_handler(signal, frame):
	GPIO.cleanup()
	print ('Script terminated by Ctrl+C')
	# Terminate script
	sys.exit(0)

signal.signal(signal.SIGINT, signal_handler)

 
#-----------------------------------------------------------------------
# GPIO setup
#-----------------------------------------------------------------------
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

# Adjust if different
coil_A_1_pin = 4 # blue
coil_A_2_pin = 17 # pink
coil_B_1_pin = 23 # yellow
coil_B_2_pin = 24 # orange

StepCount = 8
Seq = [0,1,2,3,4,5,6,7]

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]


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)
			#input("Fwd seq #%d : %s %s %s %s" % (j, 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])
			time.sleep(delay)
			#input("Rev seq #%d : %s %s %s %s" % (j, Seq[j][0], Seq[j][1], Seq[j][2], Seq[j][3]))

#-----------------------------------------------------------------------
# Main
#-----------------------------------------------------------------------
if __name__ == '__main__':
	setStep(0, 0, 0, 0)
	
	delay = input("Time Delay (ms) [5]? ")
	if not delay:
		delay = 5
	else:
		delay = int(delay)
		
	steps_fwd = input("How many steps forward? [100] ")
	if not steps_fwd:
		steps_fwd = 100
	else:
		steps_fwd = int(steps_fwd)
		
	steps_rev = input("How many steps backward? [100] ")
	if not steps_rev:
		steps_rev = 100
	else:
		steps_rev = int(steps_rev)
		
	
	while True:
		forward(delay / 1000.0, steps_fwd)
		setStep(0, 0, 0, 0)
		time.sleep(0.5)
		backwards(delay / 1000.0, steps_rev)
		setStep(0, 0, 0, 0)
		time.sleep(0.5)

Code for python 2

#!/usr/bin/python2.7
# coding: utf-8
'''
sudo apt install python-dev python-rpi.gpio
Run with: python2 stepper.py
'''
import sys, signal, time
import RPi.GPIO as GPIO


#-----------------------------------------------------------------------
# Functions (inline)
#-----------------------------------------------------------------------
# Manage ctrl+c
def signal_handler(signal, frame):
	GPIO.cleanup()
	print ('Script terminated by Ctrl+C')
	# Terminate script
	sys.exit(0)

signal.signal(signal.SIGINT, signal_handler)

 
#-----------------------------------------------------------------------
# GPIO setup
#-----------------------------------------------------------------------
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

# Adjust if different
coil_A_1_pin = 4 # blue
coil_A_2_pin = 17 # pink
coil_B_1_pin = 23 # yellow
coil_B_2_pin = 24 # orange
 
StepCount = 8
Seq = range(0, StepCount)

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]


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)
			#raw_input("Fwd seq #%d : %s %s %s %s" % (j, 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])
			time.sleep(delay)
			#raw_input("Rev seq #%d : %s %s %s %s" % (j, Seq[j][0], Seq[j][1], Seq[j][2], Seq[j][3]))

#-----------------------------------------------------------------------
# Main
#-----------------------------------------------------------------------
if __name__ == '__main__':
	setStep(0, 0, 0, 0)
	
	delay = raw_input("Time Delay (ms) [5]? ")
	if not delay:
		delay = 5
	else:
		delay = int(delay)
		
	steps_fwd = raw_input("How many steps forward? [100] ")
	if not steps_fwd:
		steps_fwd = 100
	else:
		steps_fwd = int(steps_fwd)
		
	steps_rev = raw_input("How many steps backward? [100] ")
	if not steps_rev:
		steps_rev = 100
	else:
		steps_rev = int(steps_rev)
		
	
	while True:
		forward(delay / 1000.0, steps_fwd)
		setStep(0, 0, 0, 0)
		time.sleep(0.5)
		backwards(delay / 1000.0, steps_rev)
		setStep(0, 0, 0, 0)
		time.sleep(0.5)

 

More images

Tip: Right-click on the image and select "Show image in new tab" to view it in full size.

28BYJ-48 gearbox

Motor internal circuit

Driver board

Backside of motor

Front side of motor

 

 

Kommentarer till sidan Stepper 1