UltraBorg PBR BattBorg and pygame robot. Help request for Python code.

Forums:

Hello PiBorg community,

Firstly I'd like to thank everyone at PiBorg for creating such brilliant boards.

The PBR gives plenty of power to control motors and the BattBorg does an excellent job of powering the Pi from batteries. The UltraBorg is a great bit of kit, offering control over servos and distance sensors. I love them all and have brought them together to create a robot with an onboard pan/tilt camera.

However, I am having some trouble with some Python code that I have cobbled together. I am sure this is a classic case of "operator error" and hopefully, can be easily resolved by someone with more knowledge than myself.

The code is designed to take inputs from a keyboard (wireless) and either move motors controlled by the PBR forwards, backwards, left and right; or move two servos controlled by the UltraBorg up, down, left and right.

The motors work perfectly with the code, but whenever I press a key to operate the servos I receive the following error:-

Traceback (most recent call last):
  File "/home/pi/picoborgrev/1.2-servo_motorcontrol_PBR_pygame .py", line 118, in 
    servo_up()
  File "/home/pi/picoborgrev/1.2-servo_motorcontrol_PBR_pygame .py", line 47, in servo_up
    servo2 += rateServo2
UnboundLocalError: local variable 'servo2' referenced before assignment

I have moved bits of code around trying to resolve the issue, but to no avail.

I have tried to comment the code methodically to show what I am trying to achieve with each section of the program. Hopefully this will help diagnose the source of the problem.

Thank you in advance for your time and any assistance you are able to offer.

Kind regards,
TankMan

PS The code is as follows:-

#!/usr/bin/env python

import time
import PicoBorgRev
import pygame
import os
import UltraBorg
 
# Settings
servoMin = -1.0                 # Smallest servo position to use
servoMax = +1.0                 # Largest servo position to use
startupDelay = 0.5              # Delay before making the initial move
stepDelay = 0.1                 # Delay between steps
rateStart = 0.05                # Step distance for all servos during initial move
rateServo1 = 0.01               # Step distance for servo #1
rateServo2 = 0.01               # Step distance for servo #2
 
# Start the UltraBorg
UB = UltraBorg.UltraBorg()      # Create a new UltraBorg object
UB.Init()                       # Set the board up (checks the board is connected)

# Start the PicoBorg Reverse
PBR = PicoBorgRev.PicoBorgRev()
PBR.Init()
PBR.ResetEpo()

# Start pygame & define pygame screen size
pygame.init()
screen = pygame.display.set_mode ((480,480))

print 'Move to central'
# Initial settings
servo1 = 0.0
servo2 = 0.0
# Set our initial servo positions
UB.SetServoPosition1(servo1)
UB.SetServoPosition2(servo2)
# Wait a while to be sure the servos have caught up
time.sleep(startupDelay)

# Define servo variables
def servo_left():
    servo1 += rateServo1

def servo_right():
    servo1 -= rateServo1

def servo_up():
    servo2 += rateServo2

def servo_down():
    servo2 -= rateServo2

# Check if any servos exceed limits and constrain to limit
if servo1 > servoMax:
    servo1 = servoMax
if servo1 < servoMax:
    servo1 = servoMax
if servo2 > servoMax:
    servo2 = servoMax
if servo2 < servoMin:
    servo2 = servoMin

# Set our new servo positions
    UB.SetServoPosition1(servo1)
    UB.SetServoPosition2(servo2)

# Define motor variables
def forwards():
    PBR.SetMotor1(+0.8)
    PBR.SetMotor2(+0.7)

def back():
    PBR.SetMotor1(-0.8)
    PBR.SetMotor2(-0.7)

def left():
    PBR.SetMotor1(-0.6)
    PBR.SetMotor2(+0.6)
    
def right():
    PBR.SetMotor1(+0.6)
    PBR.SetMotor2(-0.6)
    
def stop():
    PBR.MotorsOff()

def shutdown():
    os.system("sudo shutdown -P now")
      
while True:
    pygame.display.flip()
    keystate=pygame.key.get_pressed()
    
    if keystate[pygame.K_DOWN]:
        print 'backwards'
        back()

    elif keystate[pygame.K_UP]:
        print 'forwards'
        forwards()

    elif keystate[pygame.K_RIGHT]:
        print 'right'
        right()

    elif keystate[pygame.K_LEFT]:
        print 'left'
        left()

    elif keystate[pygame.K_a]:
        print 'servo left'
        servo_left()

    elif keystate[pygame.K_d]:
        print 'servo right'
        servo_right()

    elif keystate[pygame.K_w]:
        print 'servo up'
        servo_up()

    elif keystate[pygame.K_x]:
        print 'servo down'
        servo_down()

    elif keystate[pygame.K_SPACE]:
        print 'shutdown'
        shutdown()

    else:
        stop()

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            stop()
            exit(0)
            
    time.sleep(0.01)
piborg's picture

I think your problem is due to how Python uses variables.
Put simply if you are trying to read a value then Python will use anything it can find.
If you are trying to change a value it expects it to exist locally.

The simplest way to fix this would be to make the servo1 and servo2 variables global.

First change the initial settings to be global:

# Initial settings
global servo1
global servo2
servo1 = 0.0
servo2 = 0.0

Then any function which needs them should also make them global, for example:

# Define servo variables
def servo_left():
    global servo1
    servo1 += rateServo1

def servo_right():
    global servo1
    servo1 -= rateServo1

def servo_up():
    global servo2
    servo2 += rateServo2

def servo_down():
    global servo2
    servo2 -= rateServo2

now these functions will change the global version instead.

Hi piborg,

IT LIVES!

Thank you very much for your superbly swift and very helpful reply.

It has been a pretty busy week, so please accept my apology for not replying sooner.

I have managed to implement your code correctly and the pan/tilt mechanism is finally working.

I will tweak the code that limits the up/down and left/right limits and add a key-press that centres the mechanism, but, right now it works and I'm smiling from ear to ear.

I may be re-inventing the wheel a bit with this code, as I know that you have a web GUI. I will find time to explore it.

This code runs without wifi, controlled by a bluetooth keyboard and there are merits to that.

It has been a superb learning experience and your help has been the icing on the cake.

I wish you all the very best of fortune.

Kind regards,

TankMan

Subscribe to Comments for &quot;UltraBorg PBR BattBorg and pygame robot. Help request for Python code.&quot;