Raspberry Pi and Gamepad Programming Part 2: Controlling the GoPiGo

Welcome to part 2 of my series on working with programming the GoPiGo  and a Gamepad controller with Python.

In part 1 I talked about what a gamepad “looks” like to a Raspberry Pi and how the excellent evdev package makes it easy to read and process information from it. I finished the post with a script that reads buttons on the gamepad and prints the direction it would send the GoPiGo in.

The final script from part 1 and all of the scripts from this part (and all future posts) can be found on github.

Let’s pick up where we left off and add code for the GoPiGo.

#!/usr/bin/python

from evdev import InputDevice, categorize, ecodes, KeyEvent
from gopigo import *

gamepad = InputDevice('/dev/input/event0')

for event in gamepad.read_loop():
    if event.type == ecodes.EV_KEY:
        keyevent = categorize(event)
    if keyevent.keystate == KeyEvent.key_down:
        if keyevent.keycode[0] == 'BTN_A':
            print "Back"
            bwd()
        elif keyevent.keycode == 'BTN_Y':
            print "Forward"
            fwd()
        elif keyevent.keycode == 'BTN_B':
            print "Right"
            right()
        elif keyevent.keycode == 'BTN_X':
            print "Left"
            left()
        elif keyevent.keycode == 'BTN_THUMBR' or keyevent.keycode == 'BTN_THUMBR':
            print "Stop"
            stop()

This script looks familiar. The only changes are an import for the gopigo  module, and then calls to it for each button press. I also added a “stop” command at the end. It’s activated by the gamepad’s joystick buttons.

Stop Buttons

Try running the script.

pi@raspberrypi ~/gopigo-tutorial/part2 $ ./gamepad.py
Traceback (most recent call last):
 File "./gamepad.py", line 17, in 
 from gopigo import *
 File "build/bdist.linux-armv6l/egg/gopigo.py", line 30, in 
IOError: [Errno 13] Permission denied

Oops. We need root access to run anything that accesses the Gopigo device. Run the script with sudo.

pi@raspberrypi ~/gopigo-tutorial/part2 $ sudo ./gamepad.py
Back
Stop

Everything works now. Why is that? Let’s look at line 30 of gopigo.py. as it is called out in the error message.

I am running the Raspbian image from Dexter Industries, so there’s a copy of the GoPiGo scripts in the gopigo folder in the pi user’s home folder. You can also find the scripts here on github.

if rev == 2 or rev == 3:
    bus = smbus.SMBus(1) #

Smbus is a Python package that allows us to communicate with devices connected to Pi’s General Purpose In Out (GPIO) connection. When you assembled your GoPiGo you connected this to the circuit board on the robot. Here is a (slightly blurry) picture of a Pi with the GPIO highlighted with a red rectangle.

gpio

This GPIO has a file interface similar to the gamepad:

pi@raspberrypi ~ $ cd /dev
pi@raspberrypi /dev $ ls -l i2c-1
crw-rw---T 1 root i2c 89, 1 Jun 7 14:33 i2c-1

And here is the gamepad we saw earlier in part1.

pi@raspberrypi /dev $ ls -l input/event0
crw-rw---T+ 1 root input 13, 64 Jun 7 14:33 input/event0

Why does one require sudo and not the other? Let’s look closely at the listings side-by-side:

crw-rw—T 1 root i2c 89, 1 Jun 7 14:33 i2c-1

crw-rw—T+ 1 root input 13, 64 Jun 7 14:33 nput/event0

The first column shows the UNIX file bits, which contain information about the file type and permission. The first letter in both listings , ‘c’, indicates a “character special” file. In other words, a device we read and/or write bytes from.

The next 9 letters indicate the permissions for the file’s owner, the file’s group, and then for everyone else (“world”). Each user has 3 settings: r – read. w – write, and x – eXecute. Character special files are not executable they are not programs.

These files have the same permissions: we see ‘rw’ for both owner and group.

So what’s the difference? The answer is a couple of columns later, in red. After we see the file’s size (1) we see the owner “root,” then the group. For the i2c-1 it’s “i2c” and for the gamepad it is “input.”

What groups does pi belong to? Run the id command.

pi@raspberrypi /dev $ id
uid=1000(pi) gid=1000(pi) groups=1000(pi),4(adm),20(dialout),24(cdrom),27(sudo),29(audio),44(video),46(plugdev),60(games),100(users),105(netdev),999(input),1002(spi),1003(gpio)

There it is! We don’t see “i2c” in that long list of groups! We could remove the need for root access by adding pi to the i2c group.

But I have been off on this tangent for long enough. Let’s make the GoPiGo do something cool before I wrap this post up.

What we’re missing is a way to control the GoPiGo’s speed with the gamepad. But this requires a bit more code since speed is not “on” or “off” like a direction: a real speed control has “faster” or “slower.” We need 2 buttons and a way to track what our current speed is.

I want to use these 2 buttons:

Speed Buttons

So let’s write a quick script to identify the keycode for each button.

from select import select
from evdev import InputDevice, categorize, ecodes, KeyEvent
gamepad = InputDevice('/dev/input/event0')

for event in gamepad.read_loop():
    if event.type == ecodes.EV_KEY:
        keyevent = categorize(event)
        if keyevent.keystate == KeyEvent.key_down:
            print keyevent.keycode

Let’s run that and press the buttons we want to use.

pi@raspberrypi ~/gopigo-tutorial/part2 $ ./show_buttons.py
BTN_TR
BTN_TL

And we have the code for the two buttons on the front of the controller now. Let’s put it all together.

#!/usr/bin/python

from evdev import InputDevice, categorize, ecodes, KeyEvent
from gopigo import *

gamepad = InputDevice('/dev/input/event0')

speed=50
set_speed(speed)
for event in gamepad.read_loop():
    if event.type == ecodes.EV_KEY:
        keyevent = categorize(event)
    if keyevent.keystate == KeyEvent.key_down:
        if keyevent.keycode[0] == 'BTN_A':
            print "Back"
            bwd()
        elif keyevent.keycode == 'BTN_Y':
            print "Forward"
            fwd()
        elif keyevent.keycode == 'BTN_B':
            print "Right"
            right()
        elif keyevent.keycode == 'BTN_X':
            print "Left"
            left()
        elif keyevent.keycode == 'BTN_THUMBR' or keyevent.keycode == 'BTN_THUMBR':
            print "Stop"
            stop()  elif keyevent.keycode == 'BTN_TR':
        elif keyevent.keycode == 'BTN_TR':
            print "Faster"
            speed += 50
            if speed > 550:
               speed = 550
            set_speed(speed)
        elif keyevent.keycode == 'BTN_TL':
            print "Slower"
            speed -= 50
            if speed < 50:
                speed = 50
            set_speed(speed)

The GoPiGo module has functions for increasing and decreasing speed, but I wanted a little bit more control over how high or low we set the speed.

At the top speed  is set to a starting value of 50.

When each speed button is pushed it is incremented or decremented and then checked against a minimum or maximum setting. We use these checks to avoid setting speed to zero or a negative value to to avoid setting it too high. (I have no idea if there really is a too high, it ‘s just an example.)

Go ahead and play with the settings to suit your taste.

That’s it for this week, but we’re not done. Next week we’re going to get a little, er, flashy and then we’ll take a look at how to read joysticks instead of just buttons.  We need something to aim those joysticks with.,,

gun

2 Replies to “Raspberry Pi and Gamepad Programming Part 2: Controlling the GoPiGo”

  1. Shouldnt this:

    elif keyevent.keycode == ‘BTN_THUMBR’ or keyevent.keycode == ‘BTN_THUMBR’:

    be
    elif keyevent.keycode == ‘BTN_THUMBL’ or keyevent.keycode == ‘BTN_THUMBR’:

    Typo?

Leave a Reply