Code Update!
After a while of working on writing code, I have finally done it! This script below is adapted from the MonsterJoy code by PiBorg, yet it has a number of important changes. I will probably also tweak the code slightly (ie turn magnitude).
#!/usr/bin/env python | |
# coding: Latin-1 | |
# Load library functions we want | |
import time | |
import os | |
import sys | |
import pygame | |
import ThunderBorg | |
import UltraBorg | |
# Re-direct our output to standard error, we need to ignore standard out to hide some nasty print statements from pygame | |
sys.stdout = sys.stderr | |
# Setup the ThunderBorg | |
TB = ThunderBorg.ThunderBorg() | |
TB.i2cAddress = 0xA # Uncomment and change the value if you have changed the board address | |
TB.Init() | |
if not TB.foundChip: | |
boards = ThunderBorg.ScanForThunderBorg() | |
if len(boards) == 0: | |
print 'No ThunderBorg found, check you are attached :)' | |
else: | |
print 'No ThunderBorg at address %02X, but we did find boards:' % (TB.i2cAddress) | |
for board in boards: | |
print ' %02X (%d)' % (board, board) | |
print 'If you need to change the I²C address change the setup line so it is correct, e.g.' | |
print 'TB.i2cAddress = 0x%02X' % (boards[0]) | |
sys.exit() | |
# Ensure the communications failsafe has been enabled! | |
failsafe = False | |
for i in range(5): | |
TB.SetCommsFailsafe(True) | |
failsafe = TB.GetCommsFailsafe() | |
if failsafe: | |
break | |
if not failsafe: | |
print 'Board %02X failed to report in failsafe mode!' % (TB.i2cAddress) | |
sys.exit() | |
# Settings for the joystick | |
axisUp = 2 | |
axisDown = 5 # Joystick axis to read for up / down position | |
axisUpDownInverted = True # Set this to True if up and down appear to be swapped | |
axisLeftRight = 0 # Joystick axis to read for left / right position | |
axisLeftRightInverted = True # Set this to True if left and right appear to be swapped | |
buttonSlow = 8 # Joystick button number for driving slowly whilst held (L2) | |
slowFactor = 0.5 # Speed to slow to when the drive slowly button is held, e.g. 0.5 would be half speed | |
buttonFastTurn = 9 # Joystick button number for turning fast (R2) | |
interval = 0.00 # Time between updates in seconds, smaller responds faster but uses more processor time | |
# Power settings | |
voltageIn = 1.2 * 10 # Total battery voltage to the ThunderBorg | |
voltageOut = 12.0 * 0.95 # Maximum motor voltage, we limit it to 95% to allow the RPi to get uninterrupted power | |
# Setup the power limits | |
if voltageOut > voltageIn: | |
maxPower = 1.0 | |
else: | |
maxPower = voltageOut / float(voltageIn) | |
powerReductionFactor = 0.6 | |
maxPower *= powerReductionFactor | |
# Show battery monitoring settings | |
battMin, battMax = TB.GetBatteryMonitoringLimits() | |
battCurrent = TB.GetBatteryReading() | |
print 'Battery monitoring settings:' | |
print ' Minimum (red) %02.2f V' % (battMin) | |
print ' Half-way (yellow) %02.2f V' % ((battMin + battMax) / 2) | |
print ' Maximum (green) %02.2f V' % (battMax) | |
print ' Current voltage %02.2f V' % (battCurrent) | |
print("Initializing ultraborg") | |
UB = UltraBorg.UltraBorg() | |
UB.i2cAddress = 0xB | |
UB.Init() | |
servo1Min = -1 | |
servo1Max = 1 | |
servo2Min = -1 | |
servo2Max = 1 | |
servo3Min = -1 | |
servo3Max = 1 | |
servoRate = -0.05 | |
servoRatePincer = 0.05 | |
servoUD = 4 | |
servoLR = 3 | |
pincerClose = 5 | |
pincerOpen = 4 | |
print("returning to start position...") | |
servo1 = UB.GetServoStartup1() | |
servo2 = UB.GetServoStartup2() | |
servo3 = 0 | |
UB.SetServoPosition1(servo1) | |
UB.SetServoPosition2(servo2) | |
UB.SetServoPosition3(servo3) | |
# Setup pygame and wait for the joystick to become available | |
TB.MotorsOff() | |
TB.SetLedShowBattery(False) | |
TB.SetLeds(0,0,1) | |
os.environ["SDL_VIDEODRIVER"] = "dummy" # Removes the need to have a GUI window | |
pygame.init() | |
#pygame.display.set_mode((1,1)) | |
print 'Waiting for joystick... (press CTRL+C to abort)' | |
while True: | |
try: | |
try: | |
pygame.joystick.init() | |
# Attempt to setup the joystick | |
if pygame.joystick.get_count() < 1: | |
# No joystick attached, set LEDs blue | |
TB.SetLeds(0,0,1) | |
pygame.joystick.quit() | |
time.sleep(0.1) | |
else: | |
# We have a joystick, attempt to initialise it! | |
joystick = pygame.joystick.Joystick(0) | |
break | |
except pygame.error: | |
# Failed to connect to the joystick, set LEDs blue | |
TB.SetLeds(0,0,1) | |
pygame.joystick.quit() | |
time.sleep(0.1) | |
except KeyboardInterrupt: | |
# CTRL+C exit, give up | |
print '\nUser aborted' | |
TB.SetCommsFailsafe(False) | |
TB.SetLeds(0,0,0) | |
sys.exit() | |
print 'Joystick found' | |
joystick.init() | |
TB.SetLedShowBattery(True) | |
ledBatteryMode = True | |
try: | |
print 'Press CTRL+C to quit' | |
driveLeft = 0.0 | |
driveRight = 0.0 | |
running = True | |
hadEvent = False | |
upDown = 0.0 | |
leftRight = 0.0 | |
# Loop indefinitely | |
while running: | |
# Get the latest events from the system | |
hadEvent = False | |
events = pygame.event.get() | |
# Handle each event individually | |
for event in events: | |
if event.type == pygame.QUIT: | |
# User exit | |
running = False | |
elif event.type == pygame.JOYBUTTONDOWN: | |
# A button on the joystick just got pushed down | |
hadEvent = True | |
elif event.type == pygame.JOYBUTTONUP: | |
hadEvent = True | |
elif event.type == pygame.JOYAXISMOTION: | |
# A joystick has been moved | |
hadEvent = True | |
if hadEvent: | |
#Pincer | |
close = joystick.get_button(pincerClose) | |
open = joystick.get_button(pincerOpen) | |
if close: | |
servo3 -= 0.2 | |
if servo3 < servo3Min: | |
servo3 = servo3Min | |
UB.SetServoPosition3(servo3) | |
if open: | |
servo3 += 0.2 | |
if servo3 > servo3Max: | |
servo3 = servo3Max | |
UB.SetServoPosition3(servo3) | |
close = False | |
open = False | |
#Camera Servo | |
servo1 += servoRate * joystick.get_axis(servoLR) | |
servo2 -= servoRate * joystick.get_axis(servoUD) | |
if servo1 > servo1Max: | |
servo1 = servo1Max | |
if servo1 < servo1Min: | |
servo1 = servo1Min | |
if servo2 > servo2Max: | |
servo2 = servo1Max | |
if servo2 < servo2Min: | |
servo2 = servo1Min | |
UB.SetServoPosition1(servo1) | |
UB.SetServoPosition2(servo2) | |
# Read axis positions (-1 to +1) | |
up = (1 + joystick.get_axis(axisUp))/2 | |
down = (1 + joystick.get_axis(axisDown))/2 | |
upDown = up - down | |
leftRight = joystick.get_axis(axisLeftRight) | |
# Apply steering speeds | |
if not joystick.get_button(buttonFastTurn): | |
pass | |
#leftRight *= 0.5 | |
# Determine the drive power levels | |
driveLeft = upDown | |
driveRight = upDown | |
if leftRight > 0.05: | |
# Turning left | |
driveLeft *= 1.0 + (2.0 * leftRight) | |
driveRight *= 1.0 - (1.0 * leftRight) | |
elif leftRight < -0.05: | |
# Turning right | |
driveRight *= 1.0 - (2.0 * leftRight) | |
driveLeft *= 1.0 + (1.0 * leftRight) | |
# Check for button presses | |
if joystick.get_button(buttonSlow): | |
driveLeft *= slowFactor | |
driveRight *= slowFactor | |
# Set the motors to the new speeds | |
TB.SetMotor1(driveRight * maxPower) | |
TB.SetMotor2(driveLeft * maxPower) | |
# Change LEDs to purple to show motor faults | |
if TB.GetDriveFault1() or TB.GetDriveFault2(): | |
if ledBatteryMode: | |
TB.SetLedShowBattery(False) | |
TB.SetLeds(1,0,1) | |
ledBatteryMode = False | |
else: | |
if not ledBatteryMode: | |
TB.SetLedShowBattery(True) | |
ledBatteryMode = True | |
# Wait for the interval period | |
time.sleep(interval) | |
# Disable all drives | |
TB.MotorsOff() | |
except KeyboardInterrupt: | |
# CTRL+C exit, disable all drives | |
TB.MotorsOff() | |
TB.SetCommsFailsafe(False) | |
TB.SetLedShowBattery(False) | |
TB.SetLeds(0,0,0) | |
Comments
Post a Comment