My Account

Wish List (0)

The PiBorg store is closed and we are unable to ship orders.
You will not be able to checkout any orders at this time.

YetiBorg v2 - Examples - Joystick Control

Written by in Build, YetiBorg - Build on .

Use a game controller or joystick to drive YetiBorg v2

Most of us want to be able to control our robots manually one way or another. Bluetooth wireless controllers such as a PS3 controller or Wiimote are great way to do this with Raspberry Pi based robots as the Pi 3 has Bluetooth built in to the board :) In this example we will show how these game controllers can be used to drive your YetiBorg v2. Any controller that the Raspberry Pi can recognise as a joystick should work.


In order to run this script you will only need:

Connecting the controller

Each controller is slightly different here, but the basic idea is to pair the controller using Bluetooth and it should show up as a joystick. The PS3 is a little tricky as you need to tell the controller to talk with the Raspberry Pi first. See either:

You can use the same instructions for a PS4 remote with the following changes:

  1. Skip using sixpair, it is not needed
  2. When trying to pair the controller press the PS and Share buttons at the same time to put the controller into pairing mode

There are plenty of guides on the web for setting up other controllers.


We have kept the controls nice and simple so there is not much to remember: Speed (left stick) controls the speed of the motors and Turn (right stick) changes the steering angle. In other words pushing the left stick fully up will drive at full speed, then pushing the right stick left or right at the same time will steer the YetiBorg v2. The Move slowly (L2) button limits the motors to 50% speed when held, useful for tricky maneuvering in tight spaces. The Enable tank steering (R2) button puts the left / right steering into tank mode when held, allowing the YetiBorg v2 to turn on the spot. For other controllers you will probably need to change the values in "Settings for the joystick" to work properly. You can also change the values to swap buttons around to your preferred layout :)

Speed boost

The script also has a speed boost button, giving your YetiBorg v2 the power of turbo speed! This works as a bypass of the 6V output limit to the motors, enabling you to use the full power of the battery. Be warned though, it should be used sparingly. Over-using the speed boost will shorten the life of the motors and it will also reduce the length of time YetiBorg v2 drives before needing a battery change. We recommend you save this for those times when the extra bit of speed can get you past an obstacle or overtake your opponents :)

Get the example

The example is part of the standard set of YetiBorg v2 examples installed during the getting started instructions: bash <(curl

Run once

Go to the YetiBorg v2 code directory: cd ~/yetiborgv2 and run the script using the simple launcher: ./

Run at startup

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/yetiborgv2/ & 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 -

#!/usr/bin/env python
# coding: Latin-1

# Load library functions we want
import time
import os
import sys
import pygame
import ZeroBorg

# 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 ZeroBorg
ZB = ZeroBorg.ZeroBorg()
#ZB.i2cAddress = 0x44                  # Uncomment and change the value if you have changed the board address
if not ZB.foundChip:
    boards = ZeroBorg.ScanForZeroBorg()
    if len(boards) == 0:
        print 'No ZeroBorg found, check you are attached :)'
        print 'No ZeroBorg at address %02X, but we did find boards:' % (ZB.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 'ZB.i2cAddress = 0x%02X' % (boards[0])
#ZB.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):
    failsafe = ZB.GetCommsFailsafe()
    if failsafe:
if not failsafe:
    print 'Board %02X failed to report in failsafe mode!' % (ZB.i2cAddress)

# 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)
buttonBoost = 10                        # Joystick button number for speed boost whilst held (L1)
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 = 8.4                         # Total battery voltage to the ZeroBorg (change to 9V if using a non-rechargeable battery)
voltageOut = 6.0                        # Maximum motor voltage

# Setup the power limits
if voltageOut > voltageIn:
    maxPower = 1.0
    maxPower = voltageOut / float(voltageIn)
boostPower = 1.0 / maxPower             # Boost will take speed up to battery limit :)

# Setup pygame and wait for the joystick to become available
os.environ["SDL_VIDEODRIVER"] = "dummy" # Removes the need to have a GUI window
print 'Waiting for joystick... (press CTRL+C to abort)'
while True:
            # Attempt to setup the joystick
            if pygame.joystick.get_count() < 1:
                # No joystick attached, toggle the LED
                ZB.SetLed(not ZB.GetLed())
                # We have a joystick, attempt to initialise it!
                joystick = pygame.joystick.Joystick(0)
        except pygame.error:
            # Failed to connect to the joystick, toggle the LED
            ZB.SetLed(not ZB.GetLed())
    except KeyboardInterrupt:
        # CTRL+C exit, give up
        print '
User aborted'
print 'Joystick found'

    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)
                    upDown = joystick.get_axis(axisUpDown)
                if axisLeftRightInverted:
                    leftRight = -joystick.get_axis(axisLeftRight)
                    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):
                if joystick.get_button(buttonSlow):
                    driveLeft *= slowFactor
                    driveRight *= slowFactor
                if joystick.get_button(buttonBoost):
                    driveLeft *= boostPower
                    driveRight *= boostPower
                # Set the motors to the new speeds
                ZB.SetMotor1(-driveRight * maxPower) # Rear right
                ZB.SetMotor2(-driveRight * maxPower) # Front right
                ZB.SetMotor3(-driveLeft  * maxPower) # Front left
                ZB.SetMotor4(-driveLeft  * maxPower) # Rear left
        # Change the LED to reflect the status of the EPO latch
        # Wait for the interval period
    # Disable all drives
except KeyboardInterrupt:
    # CTRL+C exit, disable all drives
Last update: Nov 05, 2017

Related Article

Related Products


Leave a Comment

Leave a Reply

The product is currently Out-of-Stock. Enter your email address below and we will notify you as soon as the product is available.