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:

  1. Draw a 40 cm sized square
  2. Move to the center of the square
  3. Spin around in both directions
  4. 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:

  1. Forward for 50 cm
  2. Backward for 50 cm
  3. Spin left 360°
  4. 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 backward
  • PerformSpin 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)
Subscribe to Comments for &quot;MonsterBorg - The ultimate Pi robot&quot;