Schrittmotor am I2C

16. März 2013 at 21:52
Print Friendly, PDF & Email

Es gibt eine große Anzahl von Motoren, aber ich habe mich für folgendes Modell entschieden: 28BJY-48 mit ULN2003 control board.

Die Gründe für diesen Schrittmotor

  • Er is billig – ca. 2,50 inkl. Versand
  • Es bei vielen Anbietern erhätlich
  • hat einen Controller board
  • klein aber relativ stark
  • funktioniert mit 5V
  • einfaches Interface

Ich habe ihn bei eBay im  Chip_Partner_Store gekauft (1pcs Stepper Motor+ Driver Board ULN2003 5V 4-phase 5 line)
Hier gibt es weitere Details: Stepper Motor 28BJY-48 Datasheet

wpid519-28BJY-48-Stepper-Motor.jpg

 

Raspberry mit Schrittmotor via Slice I/O

Raspberry mit Schrittmotor via Slice I/O

 

 

 

 

 

Der Motor und das Contoller Board werden mit dem Stecker vebunden.
Die Verbindung zum PI erfolgt über 2 Pins für die Stromversorgung und 4 Pins für die Steuerleitungen.

Ich habe hier den Schrittmotor via MCP23017 verbunden, welches auf dem extension board “Slice of PI/O” sitzt.
Daher muss ich in dieser Lösung den Motor über I2C / smbus ansprechen.
Das Board soll die GPIO PINs schützen.

 

Python Script  – step.py

Das folgende Script habe ich für die Steuerung erstellt.
Es gibt zwei Sequenzen mit  4- und 8 Schritten.
Die Sequenz mit 4 Schritten ist schneller hat aber weniger Kraft.

#!/usr/bin/python
 
# A simple Python command line tool to control a stepper motor
# attached to an MCP23017 I2C IO Expander
# By Thomas Hoeser http://thomas.hoeser-medien.de
# GNU GPL V3
 
import smbus
import sys
import time     # for sleep timer
import argparse # analyze command line arguments
 
bus = smbus.SMBus(1) # smbus.SMBus(1) for revision 2
 
I2C_address = 0x20 # I2C address of MCP23017
BankA   =0x00
BankB   =0x01
 
RegisterB = 0x13 # BankB
RegisterA = 0x12 # BankA
 
degree_rate = 510.0 / 360.0 # convert degree into steps; 510 steps = 360 degree
# ------------------------------------------------------------------
def usage():
   print 'Usage: step.py -h | -d <degrees> [-r -v [level] -n -s -t [time]]'
   print "Examples"
   print "step.py -d 360          # turn 360 degrees"
   print "step.py -d 360 -r       # turn 360 degrees into reverse direction"
   print "step.py -d 360 -s       # turn 360 degrees using 8 step sequence"
   print "step.py -d 360 -t 0.01  # turn 360 degrees wit delay of 0.01 seconds"
   print "step.py -d 360 -n  -v2  # simulate and print debug messages"
 
# define default settings
verbose_level = 0
simulate_flag = 0
direction_flag = 0
sleep_time = 0.006
 
# 4 step sequence is faster but the torque is lower
StepCount4 = 4
Seq4 = []
Seq4 = range(0, StepCount4)
Seq4[0] = int('00010001',2)
Seq4[1] = int('00100010',2)
Seq4[2] = int('01000100',2)
Seq4[3] = int('10001000',2)
 
# 8 step sequence is slower but the torque is higher
StepCount8 = 8
Seq8 = []
Seq8 = range(0, StepCount8)
Seq8[0] = int('00000001',2)
Seq8[1] = int('00000011',2)
Seq8[2] = int('00000010',2)
Seq8[3] = int('00000110',2)
Seq8[4] = int('00000100',2)
Seq8[5] = int('00001100',2)
Seq8[6] = int('00001000',2)
Seq8[7] = int('00001001',2)
 
# ------------------------------------------------------------------
def gpio_setup():
  if verbose_level >0: print "prepare smbus: ",  I2C_address , BankA, BankB
  bus.write_byte_data(I2C_address,BankA,0x00) # Set all of bank A to outputs
  # bus.write_byte_data(I2C_address,BankB,0x00) # Set all of bank B to outputs
  return
 
# ------------------------------------------------------------------
def gpio_read(register):
 
  if simulate_flag ==0:
    value = bus.read_byte_data(I2C_address,register)
  if verbose_level >3:
     print "Read : Address 0x%02x  Register 0x%02x / Value 0x%02X = %s" % (I2C_address, register, value,bin(value))
  return
 
# ------------------------------------------------------------------
def gpio_write(register,value):
 
  if verbose_level >2:
     print "Set  : Address 0x%02x  Register 0x%02x / Value 0x%02X = %s" % (I2C_address,   register, value,bin(value)) 
 
  if simulate_flag ==0:
    bus.write_byte_data(I2C_address,register,value)
 
  if verbose_level >3: gpio_read(register)
  return  
 
# ------------------------------------------------------------------
 
def step_main(Register,Seg,Stepcount,Cycles,sleep_time): 
 
  print "----- %d steps using %s sequence, delay %.3f ----- " % (Cycles,Stepcount,sleep_time)
 
  if direction_flag >0:
    if verbose_level >1: print "turn ->"
    for cyc in range (0,Cycles):
      for value in range (0,Stepcount):
       gpio_write(Register,Seg[value])
       time.sleep(sleep_time)
  else:
    if verbose_level >1: print "turn <-"
    for cyc in range (0,Cycles):
      for value in range (Stepcount-1,-1,-1):
       gpio_write(Register,Seg[value])
       time.sleep(sleep_time)
 
  return
 
# ------------------------------------------------------------------
 
def main():
 
  global verbose_level
  global sleep_time
  global simulate_flag
  global direction_flag
 
  parser = argparse.ArgumentParser(description="write to I2C interface to control stepper motor")
  parser.add_argument("-d", "--degree", help="turn [degree]", type=int)
  parser.add_argument("-s", "--strong", action='store_const', dest='strong', const='value-to-store',help="use 8 step sequence with strong torque",)
  parser.add_argument("-t", "--time", help="sleep [TIME] seconds; default 0.006", type=float)
  parser.add_argument("-n", "--nowrite", action='store_const', dest='nowrite', const='value-to-store',help="no write, just simulate",)
  parser.add_argument("-r", "--reverse", action='store_const', dest='reverse', const='value-to-store',help="reverse direction",)
  parser.add_argument("-v", "--verbose", default=False, 
                    dest='verbose', help="increase output verbosity", type=int)
  parser.add_argument('--version', action='version', version='%(prog)s 0.1')
 
  args = parser.parse_args()
  if args.verbose:  verbose_level = args.verbose
 
  if args.degree: 
    loops = int(args.degree * degree_rate)
    print "turn %d degrees %d steps " % (args.degree,loops)
 
    if args.time:
      sleep_time = args.time
      if verbose_level >0: print "sleep time ", sleep_time
 
    if args.nowrite:
      simulate_flag = 1
      if verbose_level >0: print "simulating, no output to device"
 
    if args.reverse:
      direction_flag = 1
      if verbose_level >0: print "reverse direction"
 
    gpio_setup()  # prepare smbus
    if args.strong:
      if verbose_level >0: print "using Sequence 1"
      step_main(RegisterA, Seq8,StepCount8,loops,sleep_time)
    else:
      if verbose_level >0: print "using Sequence 2"
      step_main(RegisterA, Seq4,StepCount4,loops,sleep_time)
 
    gpio_write(RegisterA,0) # set all outputs to 0
    sys.exit(0)
 
  else:
    print "Error! need to provide cycles, e.g. 360 degrees: -c 510"
    usage()
    sys.exit(1)
 
if __name__ == "__main__":
   main()