Created
January 28, 2016 20:10
-
-
Save maartenpaauw/2c09e282fe7c9e33ff2e to your computer and use it in GitHub Desktop.
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
# Group: YouMedtBro (#25) | |
# Students: Don, Maarten, Youri, Murtaza, Idriss | |
# Referenced: | |
# https://learn.adafruit.com/adafruits-raspberry-pi-lesson-10-stepper-motors/software | |
import RPi.GPIO as GPIO # Raspberry GPIO | |
import os # Required for shutdown and reboot functions | |
import time | |
from multiprocessing import Process # Required in order to run the animation function async | |
class Hwctrl: | |
# Init | |
def __init__(self): | |
# Set GPIO mode to BCM (Broadcom pin numbers) | |
GPIO.setmode(GPIO.BCM) | |
# Stepper pins | |
self.coil_A_1_pin = 17 | |
self.coil_A_2_pin = 18 | |
self.coil_B_1_pin = 27 | |
self.coil_B_2_pin = 22 | |
self.switch_pin = 23 # Limit switch | |
self.sensor_pin = 13 # Light sensor | |
self.light_pin = 21 # LED Light | |
# Delay between steps (10ms, 4x 2.5ms 0.0025) | |
self.delay = 0.0025 | |
# Different settings for R.Pi version A (armv6l) | |
if "armv6" in os.popen('uname -m').read(): | |
self.coil_B_1_pin = 23 # Different stepper pin | |
self.switch_pin = 25 # Limit switch | |
self.sensor_pin = 27 # Light sensor | |
self.light_pin = 24 # Led light | |
self.delay = 0.00235 # Sync delay | |
# GPIO setup | |
GPIO.setup(self.switch_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) | |
GPIO.setup(self.sensor_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) | |
GPIO.setup(self.light_pin, GPIO.OUT) | |
GPIO.setup(self.coil_A_1_pin, GPIO.OUT) | |
GPIO.setup(self.coil_A_2_pin, GPIO.OUT) | |
GPIO.setup(self.coil_B_1_pin, GPIO.OUT) | |
GPIO.setup(self.coil_B_2_pin, GPIO.OUT) | |
# Stepper sequence | |
self.stepSeq = [[0,0,0,1],[0,0,1,0],[0,1,0,0],[1,0,0,0]] | |
# Group animation pattern | |
# 0 = Wait (seconds) | |
# 1 = Move (direction, steps) | |
# 2 = Flash LED | |
# 3 = Pause, Wait for light trigger (the R.Pi at position X:0/Y:0 does not wait for this trigger) | |
# 4 = Trigged halt: same as pause, but happens only once during animation runtime | |
# 5 = (true/false) Set LED | |
# Timeline: | |
self.animation = [ [3], | |
[1,False,125], | |
[2], | |
[1,False,275], | |
[1,True,400] | |
] | |
# Threaded animation | |
self.animThr = Process(target=self.animatePlay, args=()) | |
self.animationActive = False | |
# Threaded LEDflash (so the motion doesn't stop when a signal is given) | |
self.flashThr = Process(target=self.flashLed, args=()) | |
# Load X and Y position from disk | |
fh = open('/boot/x.txt', 'r') | |
self.xpos = int(fh.read()) | |
fh.close() | |
fh = open('/boot/y.txt', 'r') | |
self.ypos = int(fh.read()) | |
fh.close() | |
# Move the stepper motor | |
def move(self,direction,steps,override): | |
if not self.animationActive or override: # Check if the animation is currently running, if yes: abort (moves made by the animation itself may override this check) | |
for i in range(steps): | |
# Check if limit switch has been activated | |
if not self.checkSwitch() or not direction: | |
self.step(direction) # One turn | |
# Upper limit reached: stop motion | |
else: | |
self.setStep(0, 0, 0, 0) # Power down | |
break | |
self.setStep(0, 0, 0, 0) # Power down | |
return True | |
else: | |
return False | |
# One turn | |
def step(self,direction): | |
# One turn up | |
if direction: | |
for i in range(4): | |
self.setStep(self.stepSeq[i][0], self.stepSeq[i][1], self.stepSeq[i][2], self.stepSeq[i][3]) | |
time.sleep(self.delay) | |
# One turn down | |
else: | |
for i in range(3,-1,-1): | |
self.setStep(self.stepSeq[i][0], self.stepSeq[i][1], self.stepSeq[i][2], self.stepSeq[i][3]) | |
time.sleep(self.delay) | |
# Return home | |
def moveHome(self): | |
return self.move(True, 10000, False) | |
# Control stepper motor coils | |
def setStep(self,w1,w2,w3,w4): | |
GPIO.output(self.coil_A_1_pin, w1) | |
GPIO.output(self.coil_A_2_pin, w2) | |
GPIO.output(self.coil_B_1_pin, w3) | |
GPIO.output(self.coil_B_2_pin, w4) | |
# Start animation | |
def animateStart(self): | |
if not self.animationActive: | |
self.moveHome() | |
self.move(False,100,False) # Drop ball by 100 steps before the animation runs | |
self.animationActive = True | |
self.animThr = Process(target=self.animatePlay, args=()) | |
self.animThr.start() | |
return True | |
else: | |
return False | |
# Stop animation | |
def animateStop(self): | |
if self.animationActive: | |
if self.animThr.is_alive(): | |
self.animThr.terminate() | |
self.animationActive = False | |
self.toggleLight(False) | |
self.moveHome() | |
return True | |
else: | |
return False | |
# Play animation | |
def animatePlay(self): | |
trigged = False | |
while self.animationActive: | |
for a in self.animation: | |
# Wait | |
if a[0] == 0: | |
time.sleep(a[1]) | |
# Move | |
elif a[0] == 1: | |
self.move(a[1],a[2],True) | |
# Flash LED | |
elif a[0] == 2: | |
self.flashThr = Process(target=self.flashLed, args=()) | |
if not self.flashThr.is_alive(): | |
self.flashThr.start() | |
# Pause, Wait for light trigger | |
elif a[0] == 3: | |
while (self.checkSensor() == False): | |
time.sleep(.02) | |
# Trigged pause, Wait a single light trigger, ignore for the rest of the animation | |
elif a[0] == 4: | |
if not trigged: | |
while (self.checkSensor() == False): | |
time.sleep(.02) | |
trigged = True | |
# Pause, Wait for light trigger | |
elif a[0] == 5: | |
self.toggleLight(a[1]) | |
# Flash the LED | |
def flashLed(self): | |
self.toggleLight(True) | |
time.sleep(.5) | |
self.toggleLight(False) | |
return | |
# Shutdown R.Pi | |
def shutdown(self): | |
if self.animationActive: # Animation is running, cancel action | |
return False | |
else: | |
if os.system("/sbin/shutdown -h now") is not None: | |
return True # Command successful | |
else: | |
return False # Command failed | |
# Reboot R.Pi | |
def reboot(self): | |
if self.animationActive: # Animation is running, cancel action | |
return False | |
else: | |
if os.system("/sbin/shutdown -r now") is not None: | |
return True # Command successful | |
else: | |
return False # Command failed | |
# Return X-postion | |
def getXpos(self): | |
return self.xpos | |
# Return Y-postion | |
def getYpos(self): | |
return self.ypos | |
# Check the switch status | |
def checkSwitch(self): | |
if GPIO.input(self.switch_pin) == 0: | |
return True | |
else: | |
return False | |
# Check the light sensor status (always true for the first Pi in the row) | |
def checkSensor(self): | |
if self.firstPi(): | |
return True | |
elif GPIO.input(self.sensor_pin) == 0: | |
return True | |
else: | |
return False | |
# First Raspberry on the block (position 0,0) | |
def firstPi(self): | |
if self.xpos == 0 and self.ypos == 0: | |
return True | |
else: | |
return False | |
# Return if the animation is active or not | |
def getAnimationActive(self): | |
return self.animationActive | |
# Control the LED light | |
def toggleLight(self,onoff): | |
GPIO.output(self.light_pin,onoff) | |
# Cleanup GPIO | |
def cleanShutdown(self): | |
print "## Shutting down..." | |
GPIO.cleanup() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment