Schrittmotor am I2C
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
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.
[codesyntax lang="python"] #!/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()
[/codesyntax]