Stepper Motor Control in raspberry pi
Steppers
Steppers, or stepping motors, are brushless DC motors. In the PyHack workshop we first started with brushed DC motors (2 wires), then using H bridges to make them rotate both ways, and used pulse width modulation (PWM) to vary their speed. We followed with servos and then we went into steppers.
Unfortunately, I've not posted on some of these aspects yet (I thought I had), but I'll definitely post the explanations (servo, PWM), diagrams and python code for these too.
Now, let's get back to our steppers. They do come in all kinds of shape and size:
Wired
For our discussion right now however, we'll focus on just one thing, the number of wires. Typically, you will have a stepper with 4, 5 or 6 wires:
5 wire unipolar, 4 wire bipolar |
6 wire unipolar |
As can be seen, 5 or 6 wires are fundamentally the same. They are what is called a Unipolar stepper. 4 wire steppers are Bipolar steppers. A different type of driver is needed depending if you have to drive one or the other.
5 wire unipolar stepper with a 6 position connector |
Unipolar
We are focusing today on the unipolar kind. Last summer, I got a hold of a good quantity of some very small steppers (28BYJ-48). Their spec was 5V, 5 wire unipolars, originally designed to control louvers on air conditioning units.
The neat thing with them is they have a built-in gearhead with a 64:1 ratio, allowing for some torque and precision, and allowing for instant on full speed sequencing (no need to ramp up):
I had this as spec:
What is interesting to note is that we basically have 4 square waves driving the motor, with 2/3 offset.
If you don't have the specs like above (even with your google-fu being strong), you will need a multimeter to measure the resistance between the different wires to figure out which wire is the center tap and which wires are part of the same coil.
Let's say you measure 72 ohm between 2 wires, and 144 between 2 others, then you know that one of the wires that had 72 ohm is a center tap. The two giving 144 ohm (whatever the value, we are looking for ratios of 2:1) are the extremities of a coil.
Driver
With the above motor, we will need 4 GPIOs. The 28BYJ-48 is often sold with a small board that includes a ULN2003 darlington array (I got those with some subsequent buys of the steppers):
It is convenient because it even includes the headers. All you need are 6 jumper wires. 4 for the GPIOs, one for ground and one for 5V, and you are in business. That is sufficient to start playing with Python code, and you might be able to skip the next section.
If however you are like me, your odyssey is just beginning.
The ULN2003 were bread and butter circuits in the days of 7 segment led displays (remember those calculators with red led segment displays or even vacuum displays)? They had 7 Darlington pairs in the array. However, 7 is an inconvenient number. Our steppers need 4 channels (4 Darlington pairs). So we need 2 ULN2003 if we are going to drive 2 motors.
A better choice is the ULN 2803. The specs can be found here (Texas Instrument). Similar design to the ULN2003, it has 8 channels (8 Darlington pairs), hence a perfect match for 2 motors!
Prototyping
The ULN2803 has several built in features that will make our life oh so simple:
- inputs all on one side
- outputs all on the other
- each output is protected by a free wheeling diode
- each channel is an inverting amplifier
Interfacing With The Pi
The motor connects to the controller board with a pre-supplied connector. The controller board has 4+2 pins that need to be connected to the Pi header (P1).
- 5V (P1-02)
- GND (P1-06)
- Inp1 (P1-18)
- Inp2 (P1-22)
- Inp3 (P1-24)
- Inp4 (P1-26)
To rotate the stepper motor you provide a sequence of “high” and “low” levels to each of the 4 inputs in sequence. By setting the correct sequence of high and low levels the motor spindle will rotate. The direction can be reversed by reversing the sequence
Program :-
#!/usr/bin/python
# Import required libraries
import time
import RPi.GPIO as GPIO
# Use BCM GPIO references
# instead of physical pin numbers
GPIO.setmode(GPIO.BCM)
# Define GPIO signals to use
# Physical pins 11,15,16,18
# GPIO17,GPIO22,GPIO23,GPIO24
StepPins = [17,22,23,24]
# Set all pins as output
for pin in StepPins:
print "Setup pins"
GPIO.setup(pin,GPIO.OUT)
GPIO.output(pin, False)
# Define advanced sequence
# as shown in manufacturers datasheet
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]]
StepCount = len(Seq)
StepDir = 1 # Set to 1 or 2 for clockwise
# Set to -1 or -2 for anti-clockwise
# Read wait time from command line
if len(sys.argv)>1:
WaitTime = int(sys.argv[1])/float(1000)
else:
WaitTime = 10/float(1000)
# Initialise variables
StepCounter = 0
# Start main loop
while True:
print StepCounter,
print Seq[StepCounter]
for pin in range(0,4):
xpin=StepPins[pin]# Get GPIO
if Seq[StepCounter][pin]!=0:
print " Enable GPIO %i" %(xpin)
GPIO.output(xpin, True)
else:
GPIO.output(xpin, False)
StepCounter += StepDir
# If we reach the end of the sequence
# start again
if (StepCounter>=StepCount):
StepCounter = 0
if (StepCounter<0):
StepCounter = StepCount+StepDir
# Wait before moving on
time.sleep(WaitTime)
Comments
Post a Comment