Pi with PS2/PS3/XBox/Generic Keypads

For a lot of Pi projects it’s nice to have some kind of handheld controller.

Our goal was to create a simple Meccano crane that we could control with one of the game controllers that we had around the house.

PS3_crane1

There are some options like PyGame that offer a keyboard and joystick interface, but we found the evdev library to be a little simpler and more straight-forward.

The Python evdev Libraray

The Python evdev library offers is a simple way to connect up almost any USB keypad type device, the libary is installed by:

sudo apt-get install python-evdev

A simple monitoring program

The first step is to figure out what the PS2, PS3 or Xbox button codes are. The code below will show you the keycodes and key descriptions for your key presses:

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

for event in gamepad.read_loop():
    if event.type == ecodes.EV_KEY and event.value == 1:
        try:
            keyevent = categorize(event)
            print (keyevent) # comment to remove key messages

        except:
            print ("Problem key pressed...")

The output will appears something like:


key event at 1488557515.714249, 295 (BTN_BASE2), down
key event at 1488557517.491448, 294 (BTN_BASE), down
key event at 1488557519.594712, 293 (BTN_PINKIE), down

Once you’ve got the required keycode then you’re ready to start your main project.

Generic Keypad

There are many low cost generic pads that can be used. Below is a picture of a generic gamepad with some sample code to pick up its keys. (Note: the joystick keys are not addressed in this project).

gamepad_pi

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

for event in gamepad.read_loop():
    if event.type == ecodes.EV_KEY and event.value == 1:
        try:
            keyevent = categorize(event)
            if keyevent.keycode == "BTN_THUMB":
                print ("Right - 'A' button")
            if keyevent.keycode == "BTN_THUMB2":
                print ("Bottom - 'B' button")
            if 'BTN_TRIGGER' in keyevent.keycode: # ['BTN_JOYSTICK', 'BTN_TRIGGER']
                print ("Top - 'X' button")
            if keyevent.keycode == "BTN_TOP":
                print ("Left - 'Y' button")
            if keyevent.keycode == "BTN_TOP2":
                print ("Left shoulder button")
            if keyevent.keycode == "BTN_PINKIE":
                print ("Right shoulder button")
            if keyevent.keycode == "BTN_BASE3":
                print ("SELECT button")
            if keyevent.keycode == "BTN_BASE4":
                print ("START button")

            print (keyevent) # comment to remove key messages

        except:
            print ("Problem key pressed...")

PS2 Controller

The PS2 key mapping is not the same as a generic keypad. Some issues that we found using PS2 controllers:

  • the PS2 controller may require the “PS” key to be pushed before the controller is active
  • the right “triangle”, “circle” and “X” are not directly supported in the keyevent.keycode.

controller_ps2_diagram

Below is some Python code to pick up the PS2 keys.

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

for event in gamepad.read_loop():
    if event.type == ecodes.EV_KEY and event.value == 1:
        try:
            keyevent = categorize(event)
            if 'BTN_TRIGGER_HAPPY1' in keyevent.keycode: #'BTN_TRIGGER_HAPPY', 'BTN_TRIGGER_HAPPY1'
                print ("Playstation button")

            if keyevent.keycode == "BTN_TOP2":
                print ("Top D-Pad button")
            if keyevent.keycode == "BTN_BASE":
                print ("Bottom D-Pad button")
            if keyevent.keycode == "(BTN_BASE2":
                print ("Left D-Pad button")
            if keyevent.keycode == "(BTN_PINKIE":
                print ("Right D-Pad button")

            if keyevent.keycode == "BTN_BASE5":
                print ("Left top shoulder button")
            if keyevent.keycode == "BTN_BASE6":
                print ("Right top shoulder button")
            if keyevent.keycode == "BTN_BASE3":
                print ("Left bottom shoulder button")
            if keyevent.keycode == "BTN_BASE4":
                print ("Right bottom shoulder button")

            if "BTN_TRIGGER" in keyevent.keycode: #'BTN_JOYSTICK', 'BTN_TRIGGER'
                print ("SELECT button")
            if keyevent.keycode == "BTN_TOP":
                print ("START button")

            if keyevent.keycode == "BTN_DEAD":
                print ("SQUARE button")

            print (keyevent) # comment to remove key messages

        except:
            print ("Problem key pressed...")

Wireless Keyboards

We found that evdev also worked well with wireless keyboards. One of the advantages of evdev is that it will get the key stroke directly and you don’t need to do an “Enter”.

We used a wireless keyboard to drive and control a mobile missile launcher.

wl_kb_missile2

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s