MonsterBorg - The ultimate Pi robot
Set your MonsterBorg to move in a preset sequence
Robots such as BigTrak and Turtles work by having a sequence of moves programmed into them. Most of them use a set of commands based on the Logo programming language.
In this example we will turn our MonsterBorg into a turtle robot, just without the pen :)
Parts
All we need for this example is the MonsterBorg itself, no other bits are necessary :)
Get the example
The example is part of the standard set of MonsterBorg examples installed during the getting started instructions: bash <(curl https://www.piborg.org/install-monsterborg.txt)
Run once
Before running make sure your MonsterBorg has plenty of room to move, we do not want it to fall of a table! When it is running keep and eye on where he is in case you need to rescue him from disaster.
Go to the MonsterBorg code directory:cd ~/monsterborg
and run the script:./monsterSequence.py
The standard example should move roughly like this:
- Draw a 40 cm sized square
- Move to the center of the square
- Spin around in both directions
- Return to where we started
Tuning your MonsterBorg
As you may have noticed, the moves are not 100% perfect because the MonsterBorg is driving without looking where he is going! If the moves are very wrong you probably need to tune the amount of time he spends moving.
Start by opening the script in an editor, such as nano:nano monsterSequence.py
then move down until you find the movement settings:
# Movement settings (worked out from our MonsterBorg on carpet tiles) timeForward1m = 0.85 # Number of seconds needed to move about 1 meter timeSpin360 = 1.10 # Number of seconds needed to make a full left... testMode = False # True to run the motion tests, False to run...
Change testMode
to True
, then save and exit. After that re-run the script to run in test mode. While in test mode the MonsterBorg will perform some simple moves one at a time:
- Forward for 50 cm
- Backward for 50 cm
- Spin left 360°
- Spin right 360°
If the movement is too long or too short you can correct it by changing the values in the script:
- Forward / backward too long → Make
timeForward1m
smaller - Forward / backward too short → Make
timeForward1m
larger - Left / right spinning too long → Make
timeSpin360
smaller - Left / right spinning too short → Make
timeSpin360
larger
When all the movements are roughly correct change testMode
back to False
to get MonsterBorg to run the sequence again.
Programming a new sequence
The sequence of moves are all towards the bottom of the script:
### Our sequence of motion goes here ### # Draw a 40cm square for i in range(4): PerformDrive(+0.4) PerformSpin(+90) # Move to the middle of the square PerformSpin(+45) distanceToOtherCorner = math.sqrt(0.4**2 + 0.4**2) # Pythagorean theorem PerformDrive(distanceToOtherCorner / 2.0) PerformSpin(-45) # Spin each way inside the square PerformSpin(+360) PerformSpin(-360) # Return to the starting point PerformDrive(-0.2) PerformSpin(+90) PerformDrive(-0.2) PerformSpin(-90)
There are two commands provided for moving the MonsterBorg:
PerformDrive
takes a distance in meters to move. Positive values move forward, negative values move backwardPerformSpin
takes an angle in degrees to spin. Positive values spin right, negative values spin left
You can use any normal python code with these functions, such as loops or maths to decide how many times to do something or how far to travel. You can make awesome patterns using these moves so have fun and experiment away :)
Run at startup
Once your sequence is ready you can make MonsterBorg perform the sequence when he is powered on all by himself.
Open /etc/rc.local to make an addition using:sudo nano /etc/rc.local
Then add this line just above the exit 0
line:/home/pi/monsterborg/monsterSequence.py &
Finally press CTRL+O, ENTER to save the file followed by CTRL+X to exit nano.
Next time you power up the Raspberry Pi it should start the script for you :)
Full code listing - monsterSequence.py
#!/usr/bin/env python # coding: Latin-1 # Simple example of a motor sequence script # Import library functions we need import ThunderBorg import time import math import sys # Setup the ThunderBorg TB = ThunderBorg.ThunderBorg() #TB.i2cAddress = 0x15 # 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() TB.SetCommsFailsafe(False) # Disable the communications failsafe # Movement settings (worked out from our MonsterBorg on carpet tiles) timeForward1m = 0.85 # Number of seconds needed to move about 1 meter timeSpin360 = 1.10 # Number of seconds needed to make a full left / right spin testMode = False # True to run the motion tests, False to run the normal sequence # Power settings voltageIn = 12.0 # 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) # Function to perform a general movement def PerformMove(driveLeft, driveRight, numSeconds): # Set the motors running TB.SetMotor1(driveRight * maxPower) TB.SetMotor2(driveLeft * maxPower) # Wait for the time time.sleep(numSeconds) # Turn the motors off TB.MotorsOff() # Function to spin an angle in degrees def PerformSpin(angle): if angle < 0.0: # Left turn driveLeft = -1.0 driveRight = +1.0 angle *= -1 else: # Right turn driveLeft = +1.0 driveRight = -1.0 # Calculate the required time delay numSeconds = (angle / 360.0) * timeSpin360 # Perform the motion PerformMove(driveLeft, driveRight, numSeconds) # Function to drive a distance in meters def PerformDrive(meters): if meters < 0.0: # Reverse drive driveLeft = -1.0 driveRight = -1.0 meters *= -1 else: # Forward drive driveLeft = +1.0 driveRight = +1.0 # Calculate the required time delay numSeconds = meters * timeForward1m # Perform the motion PerformMove(driveLeft, driveRight, numSeconds) # Run test mode if required if testMode: # Show settings print 'Current settings are:' print ' timeForward1m = %f' % (timeForward1m) print ' timeSpin360 = %f' % (timeSpin360) # Check distance raw_input('Check distance, Press ENTER to start') print 'Drive forward 50cm' PerformDrive(+0.5) raw_input('Press ENTER to continue') print 'Drive reverse 50cm' PerformDrive(-0.5) # Check spinning raw_input('Check spinning, Press ENTER to continue') print 'Spinning left' PerformSpin(-360) raw_input('Press ENTER to continue') print 'Spinning Right' PerformSpin(+360) print 'Update the settings as needed, then test again or disable test mode' sys.exit(0) ### Our sequence of motion goes here ### # Draw a 40cm square for i in range(4): PerformDrive(+0.4) PerformSpin(+90) # Move to the middle of the square PerformSpin(+45) distanceToOtherCorner = math.sqrt(0.4**2 + 0.4**2) # Pythagorean theorem PerformDrive(distanceToOtherCorner / 2.0) PerformSpin(-45) # Spin each way inside the square PerformSpin(+360) PerformSpin(-360) # Return to the starting point PerformDrive(-0.2) PerformSpin(+90) PerformDrive(-0.2) PerformSpin(-90)