253 lines
7.9 KiB
Python
Executable File
253 lines
7.9 KiB
Python
Executable File
#!/usr/bin/python
|
|
|
|
from Adafruit_PWM_Servo_Driver import PWM
|
|
import time
|
|
|
|
class Adafruit_StepperMotor:
|
|
MICROSTEPS = 8
|
|
MICROSTEP_CURVE = [0, 50, 98, 142, 180, 212, 236, 250, 255]
|
|
|
|
#MICROSTEPS = 16
|
|
# a sinusoidal curve NOT LINEAR!
|
|
#MICROSTEP_CURVE = [0, 25, 50, 74, 98, 120, 141, 162, 180, 197, 212, 225, 236, 244, 250, 253, 255]
|
|
|
|
def __init__(self, controller, num, steps=200):
|
|
self.MC = controller
|
|
self.revsteps = steps
|
|
self.motornum = num
|
|
self.sec_per_step = 0.1
|
|
self.steppingcounter = 0
|
|
self.currentstep = 0
|
|
|
|
num -= 1
|
|
|
|
if (num == 0):
|
|
self.PWMA = 8
|
|
self.AIN2 = 9
|
|
self.AIN1 = 10
|
|
self.PWMB = 13
|
|
self.BIN2 = 12
|
|
self.BIN1 = 11
|
|
elif (num == 1):
|
|
self.PWMA = 2
|
|
self.AIN2 = 3
|
|
self.AIN1 = 4
|
|
self.PWMB = 7
|
|
self.BIN2 = 6
|
|
self.BIN1 = 5
|
|
else:
|
|
raise NameError('MotorHAT Stepper must be between 1 and 2 inclusive')
|
|
|
|
def setSpeed(self, rpm):
|
|
self.sec_per_step = 60.0 / (self.revsteps * rpm)
|
|
self.steppingcounter = 0
|
|
|
|
def oneStep(self, dir, style):
|
|
pwm_a = pwm_b = 255
|
|
|
|
# first determine what sort of stepping procedure we're up to
|
|
if (style == Adafruit_MotorHAT.SINGLE):
|
|
if ((self.currentstep/(self.MICROSTEPS/2)) % 2):
|
|
# we're at an odd step, weird
|
|
if (dir == Adafruit_MotorHAT.FORWARD):
|
|
self.currentstep += self.MICROSTEPS/2
|
|
else:
|
|
self.currentstep -= self.MICROSTEPS/2
|
|
else:
|
|
# go to next even step
|
|
if (dir == Adafruit_MotorHAT.FORWARD):
|
|
self.currentstep += self.MICROSTEPS
|
|
else:
|
|
self.currentstep -= self.MICROSTEPS
|
|
if (style == Adafruit_MotorHAT.DOUBLE):
|
|
if not (self.currentstep/(self.MICROSTEPS/2) % 2):
|
|
# we're at an even step, weird
|
|
if (dir == Adafruit_MotorHAT.FORWARD):
|
|
self.currentstep += self.MICROSTEPS/2
|
|
else:
|
|
self.currentstep -= self.MICROSTEPS/2
|
|
else:
|
|
# go to next odd step
|
|
if (dir == Adafruit_MotorHAT.FORWARD):
|
|
self.currentstep += self.MICROSTEPS
|
|
else:
|
|
self.currentstep -= self.MICROSTEPS
|
|
if (style == Adafruit_MotorHAT.INTERLEAVE):
|
|
if (dir == Adafruit_MotorHAT.FORWARD):
|
|
self.currentstep += self.MICROSTEPS/2
|
|
else:
|
|
self.currentstep -= self.MICROSTEPS/2
|
|
|
|
if (style == Adafruit_MotorHAT.MICROSTEP):
|
|
if (dir == Adafruit_MotorHAT.FORWARD):
|
|
self.currentstep += 1
|
|
else:
|
|
self.currentstep -= 1
|
|
|
|
# go to next 'step' and wrap around
|
|
self.currentstep += self.MICROSTEPS * 4
|
|
self.currentstep %= self.MICROSTEPS * 4
|
|
|
|
pwm_a = pwm_b = 0
|
|
if (self.currentstep >= 0) and (self.currentstep < self.MICROSTEPS):
|
|
pwm_a = self.MICROSTEP_CURVE[self.MICROSTEPS - self.currentstep]
|
|
pwm_b = self.MICROSTEP_CURVE[self.currentstep]
|
|
elif (self.currentstep >= self.MICROSTEPS) and (self.currentstep < self.MICROSTEPS*2):
|
|
pwm_a = self.MICROSTEP_CURVE[self.currentstep - self.MICROSTEPS]
|
|
pwm_b = self.MICROSTEP_CURVE[self.MICROSTEPS*2 - self.currentstep]
|
|
elif (self.currentstep >= self.MICROSTEPS*2) and (self.currentstep < self.MICROSTEPS*3):
|
|
pwm_a = self.MICROSTEP_CURVE[self.MICROSTEPS*3 - self.currentstep]
|
|
pwm_b = self.MICROSTEP_CURVE[self.currentstep - self.MICROSTEPS*2]
|
|
elif (self.currentstep >= self.MICROSTEPS*3) and (self.currentstep < self.MICROSTEPS*4):
|
|
pwm_a = self.MICROSTEP_CURVE[self.currentstep - self.MICROSTEPS*3]
|
|
pwm_b = self.MICROSTEP_CURVE[self.MICROSTEPS*4 - self.currentstep]
|
|
|
|
|
|
# go to next 'step' and wrap around
|
|
self.currentstep += self.MICROSTEPS * 4
|
|
self.currentstep %= self.MICROSTEPS * 4
|
|
|
|
# only really used for microstepping, otherwise always on!
|
|
self.MC._pwm.setPWM(self.PWMA, 0, pwm_a*16)
|
|
self.MC._pwm.setPWM(self.PWMB, 0, pwm_b*16)
|
|
|
|
# set up coil energizing!
|
|
coils = [0, 0, 0, 0]
|
|
|
|
if (style == Adafruit_MotorHAT.MICROSTEP):
|
|
if (self.currentstep >= 0) and (self.currentstep < self.MICROSTEPS):
|
|
coils = [1, 1, 0, 0]
|
|
elif (self.currentstep >= self.MICROSTEPS) and (self.currentstep < self.MICROSTEPS*2):
|
|
coils = [0, 1, 1, 0]
|
|
elif (self.currentstep >= self.MICROSTEPS*2) and (self.currentstep < self.MICROSTEPS*3):
|
|
coils = [0, 0, 1, 1]
|
|
elif (self.currentstep >= self.MICROSTEPS*3) and (self.currentstep < self.MICROSTEPS*4):
|
|
coils = [1, 0, 0, 1]
|
|
else:
|
|
step2coils = [ [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],
|
|
[1, 0, 0, 1] ]
|
|
coils = step2coils[self.currentstep/(self.MICROSTEPS/2)]
|
|
|
|
#print "coils state = " + str(coils)
|
|
self.MC.setPin(self.AIN2, coils[0])
|
|
self.MC.setPin(self.BIN1, coils[1])
|
|
self.MC.setPin(self.AIN1, coils[2])
|
|
self.MC.setPin(self.BIN2, coils[3])
|
|
|
|
return self.currentstep
|
|
|
|
def step(self, steps, direction, stepstyle):
|
|
s_per_s = self.sec_per_step
|
|
lateststep = 0
|
|
|
|
if (stepstyle == Adafruit_MotorHAT.INTERLEAVE):
|
|
s_per_s = s_per_s / 2.0
|
|
if (stepstyle == Adafruit_MotorHAT.MICROSTEP):
|
|
s_per_s /= self.MICROSTEPS
|
|
steps *= self.MICROSTEPS
|
|
|
|
print s_per_s, " sec per step"
|
|
|
|
for s in range(steps):
|
|
lateststep = self.oneStep(direction, stepstyle)
|
|
time.sleep(s_per_s)
|
|
|
|
if (stepstyle == Adafruit_MotorHAT.MICROSTEP):
|
|
# this is an edge case, if we are in between full steps, lets just keep going
|
|
# so we end on a full step
|
|
while (lateststep != 0) and (lateststep != self.MICROSTEPS):
|
|
lateststep = self.oneStep(dir, stepstyle)
|
|
time.sleep(s_per_s)
|
|
|
|
class Adafruit_DCMotor:
|
|
def __init__(self, controller, num):
|
|
self.MC = controller
|
|
self.motornum = num
|
|
pwm = in1 = in2 = 0
|
|
|
|
if (num == 0):
|
|
pwm = 8
|
|
in2 = 9
|
|
in1 = 10
|
|
elif (num == 1):
|
|
pwm = 13
|
|
in2 = 12
|
|
in1 = 11
|
|
elif (num == 2):
|
|
pwm = 2
|
|
in2 = 3
|
|
in1 = 4
|
|
elif (num == 3):
|
|
pwm = 7
|
|
in2 = 6
|
|
in1 = 5
|
|
else:
|
|
raise NameError('MotorHAT Motor must be between 1 and 4 inclusive')
|
|
self.PWMpin = pwm
|
|
self.IN1pin = in1
|
|
self.IN2pin = in2
|
|
|
|
def run(self, command):
|
|
if not self.MC:
|
|
return
|
|
if (command == Adafruit_MotorHAT.FORWARD):
|
|
self.MC.setPin(self.IN2pin, 0)
|
|
self.MC.setPin(self.IN1pin, 1)
|
|
if (command == Adafruit_MotorHAT.BACKWARD):
|
|
self.MC.setPin(self.IN1pin, 0)
|
|
self.MC.setPin(self.IN2pin, 1)
|
|
if (command == Adafruit_MotorHAT.RELEASE):
|
|
self.MC.setPin(self.IN1pin, 0)
|
|
self.MC.setPin(self.IN2pin, 0)
|
|
def setSpeed(self, speed):
|
|
if (speed < 0):
|
|
speed = 0
|
|
if (speed > 255):
|
|
speed = 255
|
|
self.MC._pwm.setPWM(self.PWMpin, 0, speed*16)
|
|
|
|
class Adafruit_MotorHAT:
|
|
FORWARD = 1
|
|
BACKWARD = 2
|
|
BRAKE = 3
|
|
RELEASE = 4
|
|
|
|
SINGLE = 1
|
|
DOUBLE = 2
|
|
INTERLEAVE = 3
|
|
MICROSTEP = 4
|
|
|
|
def __init__(self, addr = 0x60, freq = 1600):
|
|
self._i2caddr = addr # default addr on HAT
|
|
self._frequency = freq # default @1600Hz PWM freq
|
|
self.motors = [ Adafruit_DCMotor(self, m) for m in range(4) ]
|
|
self.steppers = [ Adafruit_StepperMotor(self, 1), Adafruit_StepperMotor(self, 2) ]
|
|
self._pwm = PWM(addr, debug=False)
|
|
self._pwm.setPWMFreq(self._frequency)
|
|
|
|
def setPin(self, pin, value):
|
|
if (pin < 0) or (pin > 15):
|
|
raise NameError('PWM pin must be between 0 and 15 inclusive')
|
|
if (value != 0) and (value != 1):
|
|
raise NameError('Pin value must be 0 or 1!')
|
|
if (value == 0):
|
|
self._pwm.setPWM(pin, 0, 4096)
|
|
if (value == 1):
|
|
self._pwm.setPWM(pin, 4096, 0)
|
|
|
|
def getStepper(self, steps, num):
|
|
if (num < 1) or (num > 2):
|
|
raise NameError('MotorHAT Stepper must be between 1 and 2 inclusive')
|
|
return self.steppers[num-1]
|
|
|
|
def getMotor(self, num):
|
|
if (num < 1) or (num > 4):
|
|
raise NameError('MotorHAT Motor must be between 1 and 4 inclusive')
|
|
return self.motors[num-1]
|