Per Stenebo
2019-11-07 21:33:02
2020-06-25 22:15:37
Bipolar stepper motor with driver board
SM15DD Bipolar stepper motor, ripped from a PC DVD-ROM laser spindle. Link to full image (1.7 MB).


Adafruit TB6612 1.2A DC/Stepper Motor Driver Breakout Board.

Raspberry Pi, version 3 B+ in this case but any version should do.

Link to full image (4.4 MB).
External resources
A russian (?) site where I found valuable info about the motor: avr-cpp.blogspot.com | translated | According to this site, we have a 5 volt motor with 10 ohm per winding and 18 degrees per step. The datasheet above is also from that site.
Adafruit product page: TB6612
Step sequence
Controlling stepper motors is all about energizing the windings in timed order. I found a map, possibly orginating from stepperworld.com, of the possible sequences, wich I have implemented in the python code below.

Breadboard circuit
The circuit as Fritzing file.
The fritzing circuit features a similar driver from Sparkfun: Dual TB6612FNG , the connection seems almost identical, only VM and VCC are moved to the other side.
It seems possible to control the speed with the PWM inputs (other than the time between the steps), but I have not tested PWM yet, just pulled them to logical high (= max speed?).
Python 3 code
#!/usr/bin/python3
# coding: utf-8
'''
Hardware:
Adafruit TB6612 1.2A DC/Stepper Motor Driver Breakout Board
SM15DD CD-ROM laser spindle motor
Bipolar stepper motor
5 V
10 ohm per winding
18 degrees per step
sudo apt install python3-dev python3-rpi.gpio
Run with: python3 stepper.py
python3 /opt/diverse/stepper.py
'''
import sys, signal, time
import RPi.GPIO as GPIO
#-----------------------------------------------------------------------
# GPIO setup
#-----------------------------------------------------------------------
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(True)
# Signals from GPIO
# Adjust if different
coil_A_1_pin = 4 # yellow A+
coil_A_2_pin = 17 # green A-
coil_B_1_pin = 23 # blue B+
coil_B_2_pin = 24 # white B-
# Step sequence map
# Wave drive, one-phase
SeqA = [0,1,2,3]
SeqA[0] = [0,1,0,0] # 1 +- --
SeqA[1] = [0,0,0,1] # 2 -- +-
SeqA[2] = [1,0,0,0] # 3 -+ --
SeqA[3] = [0,0,1,0] # 4 -- -+
# High torque, two-phase
SeqB = [0,1,2,3]
SeqB[0] = [0,1,0,1] # 1.5
SeqB[1] = [1,0,0,1] # 2.5
SeqB[2] = [1,0,1,0] # 3.5
SeqB[3] = [0,1,1,0] # 4.5
# Half step
SeqC = [0,1,2,3,4,5,6,7]
SeqC[0] = [0,1,0,0] # 1
SeqC[1] = [0,1,0,1] # 1.5
SeqC[2] = [0,0,0,1] # 2
SeqC[3] = [1,0,0,1] # 2.5
SeqC[4] = [1,0,0,0] # 3
SeqC[5] = [1,0,1,0] # 3.5
SeqC[6] = [0,0,1,0] # 4
SeqC[7] = [0,1,1,0] # 4.5
mode_default = 'A'
delay_default = 10
steps_fwd_default = 10
steps_rev_default = 10
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)
#-----------------------------------------------------------------------
# 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)
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)
print ('A: Wave drive, one-phase')
print ('B: High torque, two-phase')
print ('C: Half step')
mode = input('Select squence mode [%s]? ' % mode_default)
if not mode:
mode = mode_default
if mode.upper() == 'A':
Seq = SeqA
elif mode.upper() == 'B':
Seq = SeqB
elif mode.upper() == 'C':
Seq = SeqC
else:
print ('Failed to parse input')
GPIO.cleanup()
sys.exit(0)
StepCount = len(Seq)
delay = input("Time Delay (ms) [%d]? " % delay_default)
if not delay:
delay = delay_default
else:
delay = int(delay)
steps_fwd = input("How many steps forward? [%d] " % steps_fwd_default)
if not steps_fwd:
steps_fwd = steps_fwd_default
else:
steps_fwd = int(steps_fwd)
steps_rev = input("How many steps backward? [%d] " % steps_rev_default)
if not steps_rev:
steps_rev = steps_rev_default
else:
steps_rev = int(steps_rev)
while True:
forward(delay / 1000.0, steps_fwd)
setStep(0, 0, 0, 0)
time.sleep(1.0)
backwards(delay / 1000.0, steps_rev)
setStep(0, 0, 0, 0)
time.sleep(1.0)