Running two PicoBorg Reverse for different uses in one unit
Forums:
I've managed to assign different addresses as per the instructions so have address 10 and 11 with 10 as the mian standard wheel driver.
I want to use one board as wheel driver (10) and am using MJoy.py to drive a home made version of diddyborg. I now want to use the second PicoBorg Reverse to drive (11) on board motors (not driving the wheels) with a 'simple' full on or full of switch assigned to a PS3 remote using say Triangle and Square as on off switching.
My questions relate to modifying the MJoy scrip to include the second board but am a bit lost how to intergrate the two. This is what i've tried so far, it seems to work the same as MJoy.py but cant even get the LED flashing on board 11?
#!/usr/bin/env python # coding: Latin-1 # Load library functions we want import time import os import sys import pygame import PicoBorgRev # Add no crash system #import UltraBorg #distanceMin = 300 # Minimum distance in mm, corresponds to DiddyBorg reversing at 100% #distanceMax = 400 # Maximum distance in mm, corresponds to DiddyBorg driving at 100% # Start the UltraBorg #UB = UltraBorg.UltraBorg() # Create a new UltraBorg object #UB.Init() # Set the board up (checks the board is connected) # 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 PicoBorg Reverse PBR1 = PicoBorgRev.PicoBorgRev() PBR2 = PicoBorgRev.PicoBorgRev() PBR1.i2cAddress = 10 # Uncomment and change the value if you have changed the board address PBR2.i2cAddress = 11 PBR1.Init() PBR2.Init() if not PBR1.foundChip: boards = PicoBorgRev.ScanForPicoBorgReverse() if len(boards) == 0: print 'No PicoBorg Reverse found, check you are attached :)' else: print 'No PicoBorg Reverse at address %02X, but we did find boards:' % (PBR1.i2cAddress),(PBR2.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 'PBR1.i2cAddress = 0x%02X' % (boards[0]),'PBR2.i2cAddress = 0x%02X' % (boards[0]) sys.exit() # PBR.SetEpoIgnore(True) # Uncomment to disable EPO latch, needed if you do not have a switch / jumper # Ensure the communications failsafe has been enabled! failsafe = False for i in range(5): PBR1.SetCommsFailsafe(True) PBR2.SetCommsFailsafe(True) failsafe = PBR1.GetCommsFailsafe() failsafe = PBR2.GetCommsFailsafe() if failsafe: break if not failsafe: print 'Board %02X failed to report in failsafe mode!' % (PBR1.i2cAddress),(PBR2.i2cAddress) sys.exit() PBR1.ResetEpo() PBR2.ResetEpo() # Settings for the joystick axisUpDown = 1 # Joystick axis to read for up / down position axisUpDownInverted = False # Set this to True if up and down appear to be swapped axisLeftRight = 2 # Joystick axis to read for left / right position axisLeftRightInverted = False # Set this to True if left and right appear to be swapped buttonResetEpo = 3 # Joystick button number to perform an EPO reset (Start) 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 = 3.7 * 4 # Total battery voltage to the PicoBorg Reverse voltageOut = 12.4 # Maximum motor voltage # Setup the power limits if voltageOut > voltageIn: maxPower = 1.0 else: maxPower = voltageOut / float(voltageIn) # Setup pygame and wait for the joystick to become available PBR1.MotorsOff() PBR2.MotorsOff() 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, toggle the LED PBR1.SetLed(not PBR1.GetLed()) PBR2.SetLed(not PBR2.GetLed()) pygame.joystick.quit() time.sleep(0.5) else: # We have a joystick, attempt to initialise it! joystick = pygame.joystick.Joystick(0) break except pygame.error: # Failed to connect to the joystick, toggle the LED PBR1.SetLed(not PBR.GetLed()) PBR2.SetLed(not PBR.GetLed()) pygame.joystick.quit() time.sleep(0.5) except KeyboardInterrupt: # CTRL+C exit, give up print '\nUser aborted' PBR1.SetLed(True) PBR2.SetLed(True) sys.exit() print 'Joystick found' joystick.init() PBR1.SetLed(False) PBR2.SetLed(False) 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.JOYAXISMOTION: # A joystick has been moved hadEvent = True if hadEvent: # Read axis positions (-1 to +1) if axisUpDownInverted: upDown = -joystick.get_axis(axisUpDown) else: upDown = joystick.get_axis(axisUpDown) if axisLeftRightInverted: leftRight = -joystick.get_axis(axisLeftRight) else: leftRight = joystick.get_axis(axisLeftRight) # Apply steering speeds if not joystick.get_button(buttonFastTurn): leftRight *= 0.5 # Determine the drive power levels driveLeft = -upDown driveRight = -upDown if leftRight < -0.05: # Turning left driveLeft *= 1.0 + (2.0 * leftRight) elif leftRight > 0.05: # Turning right driveRight *= 1.0 - (2.0 * leftRight) # Check for button presses if joystick.get_button(buttonResetEpo): PBR1.ResetEpo() if joystick.get_button(buttonSlow): driveLeft *= slowFactor driveRight *= slowFactor # Set the motors to the new speeds PBR1.SetMotor1(driveRight * maxPower) PBR1.SetMotor2(-driveLeft * maxPower) # Change the LED to reflect the status of the EPO latch PBR1.SetLed(PBR1.GetEpo()) PBR2.SetLed(PBR2.GetEpo()) # Wait for the interval period time.sleep(interval) # Disable all drives PBR1.MotorsOff() PBR2.MotorsOff() except KeyboardInterrupt: # CTRL+C exit, disable all drives PBR1.MotorsOff() PBR2.MotorsOff() print
Any help would be much apreciated
piborg
Wed, 11/02/2016 - 19:52
Permalink
Combining two PicoBorg Reverses
The first thing you want to do is replace the
# Setup the PicoBorg Reverse
section in the script with the code you have above.Next replace all of the references to
PBR
withPBR1
.At this point the script should run and work the same way it used to.
Next we want to ensure the second Reverse has it's motors disabled when the script is done.
Find all the lines which look like this:
and add a duplicate for
PBR2
:In order to "grab" button presses we want to put some code to handle button press events.
First look for this bit of code:
What we want to do is check what the button was and change the values for the second Reverse.
You can find out what the button code is from
event.button
, the codes for a PS3 controller are listed on our PlayStation 3 controller help sheet in the button index column.As an example this will turn motor 1 on with triangle, and off with square:
You can keep adding additional
elif
lines for more buttons until you run out :)METTAUK
Thu, 11/03/2016 - 01:34
Permalink
Is this right, it works but...
Thank you for your help
On line 32 I have
With nothing for PBR2. As PBR2 to will be spinning a motor at 8000rpm I want to make sure fail safes are working? I have the jumper wired to cut switches but am a little worried if the BT to PS3 remote fails, will it stop after x time with no connection? WiFi is less of an issue at the moment (Only used to get the script going then WiFi is lost anyway!
Line 176 and 179 turn the spinner on and off
I'm a bit worried that I've just duplicated lines to add in the second PicoBorg Reverse without really knowing what i'm doing! Its not dangerous but further down the line I might make something else and it could be IF i'M MESSING UP HERE!
piborg
Thu, 11/03/2016 - 11:00
Permalink
Failsafes
Firstly I would recommend changing:
to:
so that the script will stop before doing anything if it cannot find both Reverses.
The failsafe option is a little confusing, but in short you probably want it on for both boards.
Basically with the failsafe on the Reverse will automatically shut both motors down if it has been too long since it has heard from the Raspberry Pi.
This should protect against a number of possible problems:
From memory the Reverse needs to see at least 4 messages each second to prevent the failsafe from activating.
To get the motors to turn off when the PS3 controller is out-of-range or disconnected we can either:
The easiest is option 1 and you can try it by indenting lines 186 to 188 once to the right.
This will mean the LEDs will only be changed when the PS3 controller sends a message.
The controller should send messages frequently enough to keep the failsafe happy from memory.
You can test by running the script with the robot lifted off the ground so it cannot move.
Run the script and hold/press something so the motors are running.
Now walk out of range with the motors still running, they should stop when the controller is too far away.
If you have someone else watching the robot the LEDs on both Reverses should be flashing to indicate the failsafe is engaged.
If you have trouble with option 1 or would rather try option 2 instead take a look at the code we used for running DoodleBorg:
DoodleBorg - Controlled using a PS3 controller
This has a specific set of checks to shut the motors down in the event that communication with the controller is lost.
METTAUK
Thu, 11/03/2016 - 18:48
Permalink
differnet power outputs to PBR1 and PBR2
Thanks again you have been really helpful
I now have it up and running and am impressed! But realise it moves way to fast! so want to reduce the power to the drive motors on PBR1 to around max 60% but not to PBR2 which needs to stay at 97-100%
The power setting seem to apply to both?
Or is it just a simple change like
piborg
Thu, 11/03/2016 - 19:04
Permalink
maxPower
The power setting should only apply if the motor setting line includes
* maxPower
.Your alternative suggestion should also work fine.
METTAUK
Thu, 11/03/2016 - 19:24
Permalink
More power for turning but less for straight
I tried second option, the problem is with reduced power, turning becomes difficult! Is there a way to increase power only when turning, either tank or just turn?
piborg
Fri, 11/04/2016 - 10:53
Permalink
Power boost when turing
A simple fix is to choose the reduction depending on the outputs, for example replace:
with
METTAUK
Fri, 11/04/2016 - 15:27
Permalink
Re: Power boost when turning
Thank you so much, it works like a dream for tank steering, However, for minor direction changes it sort of takes off (200rpm motors with 135mm dia tyres so can hit about 1.4m/s or 3mph+.
Is there a way to modify the steering so that if say steer left or right is less than x maintain powerLevel for straight. Perhaps something with axisLeftRight without buttonFastTurn only allows say 0.75 power where buttonFastTurn of full turn keeps power at 100%. Is there a way to know what level of steering is being input from the PS3? full lock or minor adjustment?
Currently it woks well with;
0.55 for straight, still quite fast but OK
1.0 is good for tank steering or full lock turn
would like to add 0.9 for full turns depending on terrain
with
0.55 or a bit more power, say 0.65 for minor direction changes
I know my syntax is wrong but hope it explains what I'm trying to get to work but suspect i'm on the wrong track?
something like
piborg
Fri, 11/04/2016 - 16:29
Permalink
Use the leftRight variable
You are on the right track, but the
leftRight
variable would be the best thing to test.Putting the value through the
abs
function will remove the +/- differences and make it easier to check against.For example:
METTAUK
Sat, 11/05/2016 - 10:35
Permalink
Thank you so much, it works
Thank you so much, it works really well and I think I learnt something, which brings another question...
You helped me add a 2nd PicoBorg Reverse to run a separate motor from the main wheels, now I want to change the speed of that motor in relation to PBR1 so it slows down when PBR1 is turning. Something like...
If PBR1 turning then PBR2 left slows to 50%
piborg
Sun, 11/06/2016 - 10:09
Permalink
Related speeds
This is quite easy, we simply need to change the spinner output to behave like the left and right motors.
First make a new value for the spinner drive:
Next change the button code to change this value instead of the motor itself:
Now make a new power value using the same
if
block as the left/right power value:Finally set the motor using both values in the same way as the left and right motors get set:
Now the spinner speed should update with how the robot is turning :)