class StepperMotor(object): def __init__(self, motor_inputs, state=0, delay=0.05): ''' :param motor_inputs: Ordered list of parallel values to turn motor :type motor_inputs: list or tuple :param state: Initial starting state of motor position :type state: int :param delay: Delay between steps (speed) :type delay: float ''' self.MOTOR_INPUTS = motor_inputs self.state = state self.delay = delay # Setup parallel interface on first init self.parallel_interface = Parallel() #Q: Keep as a function or store state to self? def stepper_generator(self, state_steps): ''' Returns a generator object which yields the current state and motor input. :param state_steps: Number of steps to step the motor. :type state_steps: int :returns: Generator yielding tuples (state_index, motor_input) :rtype: (int, hex) ''' if state_steps < 0: step = -1 else: step = 1 for virtual_state in xrange(self.state + 1, self.state + state_steps + 1, step): # NOTE: virtual_state is not used other than for informing the user the # overall relative step we've applied! self.state += step if self.state >= len(self.MOTOR_INPUTS): # start at list 0 self.state = 0 elif self.state < 0: # start at the end self.state = len(self.MOTOR_INPUTS) - 1 else: # we're at an index within the current motor inputs list pass motor_command = self.MOTOR_INPUTS[self.state] print "%+ 4d : Moving to internal state index %02d, %s hex %03.2f degrees" % ( virtual_state, self.state, hex(motor_command), state_to_angle(self.state, len(self.MOTOR_INPUTS))) # present the required value yield motor_command def turn_motor(self, cycles): ''' Turns the motor the desired amount. :param cycles: Loops to turn :type cycles: float :returns: New state position :rtype: int ''' # round to the nearest step possible steps = int(round(cycles * len(self.MOTOR_INPUTS))) stepper = self.stepper_generator(steps) for motor_position in stepper: ##print "turn motor to position %s" % hex(motor_position) self.parallel_interface.setData(motor_position) time.sleep(self.delay) return self.state def turn_to_angle(self, angle): ''' Turns the motor to the desired absolute angle. Accessor which converts arguments for turn_motor method. :param angle: Angle to turn to :type angle: float :returns: New state position :rtype: int ''' cycles = self.angle_to_cycles(angle, self.state) return self.turn_motor(cycles) def rotate(self, degrees): ''' Turns the motor by the number of degrees. -720 will turn the motor two whole cycles anti-clockwise. Accessor which converts arguments for turn_motor method. :param degrees: Degrees to turn motor by :type degrees: float :returns: New state position :rtype: int ''' cycles = degrees / 360.0 return self.turn_motor(cycles)
#!/usr/bin/env python from sys import argv from parallel import Parallel p = Parallel() args = argv[1:] if args: if 'on' in args: p.setData(0) if 'off' in args: p.setData(255)
class StepperMotor(object): def __init__(self, motor_inputs, state=0, delay=0.05): ''' :param motor_inputs: Ordered list of parallel values to turn motor :type motor_inputs: list or tuple :param state: Initial starting state of motor position :type state: int :param delay: Delay between steps (speed) :type delay: float ''' self.MOTOR_INPUTS = motor_inputs self.state = state self.delay = delay # Setup parallel interface on first init self.parallel_interface = Parallel() #Q: Keep as a function or store state to self? def stepper_generator(self, state_steps): ''' Returns a generator object which yields the current state and motor input. :param state_steps: Number of steps to step the motor. :type state_steps: int :returns: Generator yielding tuples (state_index, motor_input) :rtype: (int, hex) ''' if state_steps < 0: step = -1 else: step = 1 for virtual_state in xrange(self.state+1, self.state+state_steps+1, step): # NOTE: virtual_state is not used other than for informing the user the # overall relative step we've applied! self.state += step if self.state >= len(self.MOTOR_INPUTS): # start at list 0 self.state = 0 elif self.state < 0: # start at the end self.state = len(self.MOTOR_INPUTS) -1 else: # we're at an index within the current motor inputs list pass motor_command = self.MOTOR_INPUTS[self.state] print "%+ 4d : Moving to internal state index %02d, %s hex %03.2f degrees" % ( virtual_state, self.state, hex(motor_command), state_to_angle(self.state, len(self.MOTOR_INPUTS))) # present the required value yield motor_command def turn_motor(self, cycles): ''' Turns the motor the desired amount. :param cycles: Loops to turn :type cycles: float :returns: New state position :rtype: int ''' # round to the nearest step possible steps = int(round(cycles * len(self.MOTOR_INPUTS))) stepper = self.stepper_generator(steps) for motor_position in stepper: ##print "turn motor to position %s" % hex(motor_position) self.parallel_interface.setData(motor_position) time.sleep(self.delay) return self.state def turn_to_angle(self, angle): ''' Turns the motor to the desired absolute angle. Accessor which converts arguments for turn_motor method. :param angle: Angle to turn to :type angle: float :returns: New state position :rtype: int ''' cycles = self.angle_to_cycles(angle, self.state) return self.turn_motor(cycles) def rotate(self, degrees): ''' Turns the motor by the number of degrees. -720 will turn the motor two whole cycles anti-clockwise. Accessor which converts arguments for turn_motor method. :param degrees: Degrees to turn motor by :type degrees: float :returns: New state position :rtype: int ''' cycles = degrees / 360.0 return self.turn_motor(cycles)