This repository has been archived by the owner on Oct 3, 2020. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Your Name
committed
Jan 23, 2015
1 parent
626fa70
commit 7d1a7a6
Showing
8 changed files
with
928 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,252 @@ | ||
#!/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] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
#!/usr/bin/python | ||
|
||
import time | ||
import math | ||
from Adafruit_I2C import Adafruit_I2C | ||
|
||
# ============================================================================ | ||
# Adafruit PCA9685 16-Channel PWM Servo Driver | ||
# ============================================================================ | ||
|
||
class PWM : | ||
# Registers/etc. | ||
__MODE1 = 0x00 | ||
__MODE2 = 0x01 | ||
__SUBADR1 = 0x02 | ||
__SUBADR2 = 0x03 | ||
__SUBADR3 = 0x04 | ||
__PRESCALE = 0xFE | ||
__LED0_ON_L = 0x06 | ||
__LED0_ON_H = 0x07 | ||
__LED0_OFF_L = 0x08 | ||
__LED0_OFF_H = 0x09 | ||
__ALL_LED_ON_L = 0xFA | ||
__ALL_LED_ON_H = 0xFB | ||
__ALL_LED_OFF_L = 0xFC | ||
__ALL_LED_OFF_H = 0xFD | ||
|
||
# Bits | ||
__RESTART = 0x80 | ||
__SLEEP = 0x10 | ||
__ALLCALL = 0x01 | ||
__INVRT = 0x10 | ||
__OUTDRV = 0x04 | ||
|
||
general_call_i2c = Adafruit_I2C(0x00) | ||
|
||
@classmethod | ||
def softwareReset(cls): | ||
"Sends a software reset (SWRST) command to all the servo drivers on the bus" | ||
cls.general_call_i2c.writeRaw8(0x06) # SWRST | ||
|
||
def __init__(self, address=0x40, debug=False): | ||
self.i2c = Adafruit_I2C(address) | ||
self.i2c.debug = debug | ||
self.address = address | ||
self.debug = debug | ||
if (self.debug): | ||
print "Reseting PCA9685 MODE1 (without SLEEP) and MODE2" | ||
self.setAllPWM(0, 0) | ||
self.i2c.write8(self.__MODE2, self.__OUTDRV) | ||
self.i2c.write8(self.__MODE1, self.__ALLCALL) | ||
time.sleep(0.005) # wait for oscillator | ||
|
||
mode1 = self.i2c.readU8(self.__MODE1) | ||
mode1 = mode1 & ~self.__SLEEP # wake up (reset sleep) | ||
self.i2c.write8(self.__MODE1, mode1) | ||
time.sleep(0.005) # wait for oscillator | ||
|
||
def setPWMFreq(self, freq): | ||
"Sets the PWM frequency" | ||
prescaleval = 25000000.0 # 25MHz | ||
prescaleval /= 4096.0 # 12-bit | ||
prescaleval /= float(freq) | ||
prescaleval -= 1.0 | ||
if (self.debug): | ||
print "Setting PWM frequency to %d Hz" % freq | ||
print "Estimated pre-scale: %d" % prescaleval | ||
prescale = math.floor(prescaleval + 0.5) | ||
if (self.debug): | ||
print "Final pre-scale: %d" % prescale | ||
|
||
oldmode = self.i2c.readU8(self.__MODE1); | ||
newmode = (oldmode & 0x7F) | 0x10 # sleep | ||
self.i2c.write8(self.__MODE1, newmode) # go to sleep | ||
self.i2c.write8(self.__PRESCALE, int(math.floor(prescale))) | ||
self.i2c.write8(self.__MODE1, oldmode) | ||
time.sleep(0.005) | ||
self.i2c.write8(self.__MODE1, oldmode | 0x80) | ||
|
||
def setPWM(self, channel, on, off): | ||
"Sets a single PWM channel" | ||
self.i2c.write8(self.__LED0_ON_L+4*channel, on & 0xFF) | ||
self.i2c.write8(self.__LED0_ON_H+4*channel, on >> 8) | ||
self.i2c.write8(self.__LED0_OFF_L+4*channel, off & 0xFF) | ||
self.i2c.write8(self.__LED0_OFF_H+4*channel, off >> 8) | ||
|
||
def setAllPWM(self, on, off): | ||
"Sets a all PWM channels" | ||
self.i2c.write8(self.__ALL_LED_ON_L, on & 0xFF) | ||
self.i2c.write8(self.__ALL_LED_ON_H, on >> 8) | ||
self.i2c.write8(self.__ALL_LED_OFF_L, off & 0xFF) | ||
self.i2c.write8(self.__ALL_LED_OFF_H, off >> 8) |
Oops, something went wrong.