Raspberry Pi and Gamepad Programming Part 1: Reading the Device

A friend of mine recently asked if I could help out with a Raspberry Pi project he is working on. Pi was one of those things I had read about and always wanted to take a look at — and here was my excuse!

Moreover, Python, the language most Raspberry Pi tools are written in, is something else I had been meaning to take a look at.

Of course playing around with Raspberry Pi very quickly led to this:

gopigo with gamepad
A GoPiGo and a Logitech Gamepad

On the left is a GoPiGo (affiliate link), while on the right is a Logitech F710 wireless gamepad. These 2 devices do not work together “out of the box.” The GoPiGo has tutorials and sample scripts for working with a keyboard or mouse, but not for a gamepad. Here’s a chance to learn some basics and have a little fun!

Much of what makes working with the Raspberry Pi easy is that it runs Linux. (It runs other operating systems, but we’ll stick with Linux here.) As a matter of fact, this first tutorial will work on Linux running on pretty much any hardware.


For this tutorial you need a Raspberry Pi (or a computer running Linux, but you will need a GoPiGo for the next article in this series) and a gamepad. I am using a Logitech Gamepad F710 (affiliate link,) which lists for $40 right now. I picked mine up at a local Target for $25. Other USB gamepads should work similarly to the F710, including wired models. (But wireless will work a lot better once you get your robot moving.)

You need to be comfortable with a Linux command line, as well as having as basic knowledge of Python. Nothing fancy: just the ability to enter a program in your favorite text editor and run it.

Reading from Device Files

In order to use the gamepad we need to get information from it into our program. Linux, like most UNIX-like operating systems, makes this easy via device files. When the gamepad (or it’s receiver in the case of a wireless device) is connected a file appears that can be read from.

Without the joystick or USB receiver connected, open a shell on your system and list the contents of /dev/input (click on the image for a larger version if you cannot read it):


On my system I see only a default file named mice, as I do not have an actual mouse or keyboard connected.

Now connect the gamepad or its USB receiver and wait a few seconds (especially if you are using a Pi B+ or Original) for your system to notice the device:


On my system we see 2 new files and 2 new folders. The event0 and js0 devices correspond the my gamepad. The by-id and by-path folders provide an alternative method to access the devices, as well as additional information about the device.

Since these devices are files, we can treat them as such. Let’s see what’s “in” them. Opening them in an editor will not work well, but we can use good old cat to have some fun.

Cat the event0 (or eventN if you had one before you connected the new gamepad) and then press a button on the gamepad:


The image above is for a single button press. That’s a lot of characters! And most of them seem garbled.  But we do see that the gamepad device file is just like any other file that can be read.

Reading the Gamepad

We’re going to use the evdev package to interpret the input from the gamepad. I’ll explain what this package does as we go. The package has not been installed on any of the Pi distributions I have worked with, so let’s start by installing it with pip:

Pip will do it’s thing and after a bit (it can take a while on a slower Pi) the package is installed.

Now let’s open the gamepad and print some information about it. For these exercises I am using idle but a command line session with Python or running these lines from a script will work too. (Again, click on the image for a larger version.)


The first line imports a few things from the evdev package: InputDevice, categorize, and ecodes.

The second line creates an InputDevice by passing the path to the gamepad device file.

And the we finally print this new device object to standard output and see some interesting information about it.

While the mechanics of reading from the gamepad device are as simple as any other file, this quick 3 line program demonstrates how evdev makes it even simpler. The package has a termendous of code built that for managing devices like a joystick or gamepad.

Let’s use evdev to read some buttons. Start with the same import statement and create an InputDevice like we did above, but now replace printing the device with the 2 lines below. Then press a button on your gamepad.

Basic Read Loop

Instead of the garbled characters we saw earlier, we see something that is at least readable.

Before we discuss the events, let’s talk about this line:

This illustrates another feature of the evdev package. The package provides a simple for loop that reads the device and creates events for us. Without this feature our code would look something like this:

Evdev eliminates the outer While loop, as well as the call to select. In terms of lines of code, the difference is negligible, however the read_loop() version is a little easier to read and we’ll stick with it.

(In an application that needs to monitor more than one input device, such as a mouse and a keyboard, read_loop() won’t work, as it only lets us read one device. Select is excellent for reading and writing from multiple devices.)

Let’s identify what’s actually being pressed on the gamepad:

Categorize Events

Now for every event we examine the type value and see if it is a button. finally we are using the ecodes we imported.

If it is a button, we use categorize to return a more specific type of event to us and print it. If it is not, we simply print a message.

Here we see where evdev saves us a lot of work. In addition to reading the events a gamepad sends to our app, it also categorizes them for us too.

Note two things about this event info: we see the button I pressed (‘A’) and we see “down.” After a mysterious “not a button” event we then see the same button going up.

We know a lot about how to read the gamepad at this point. Let’s write a script that we could use to control the robot using the A-B-X-Y buttons on the gamepad. Enter the following into a text editor and save it.

I saved this as gamepad.py.

Run the script and press a few buttons.

As we receive each event we first check to see if it is a button. If it is, we check to see that the button is down (it’s been pressed) and then finally we check to see if it is one of the four buttons we currently care about.

That’s it for this week. Next week we’ll add code to make the GoPiGo respond to the buttons, and we’ll also a some more controls.

See you then! And feel free to leave a comment below.

12 thoughts on “Raspberry Pi and Gamepad Programming Part 1: Reading the Device

Add yours

      1. I had the same problem. I looked into multi threading using the thread lib.
        Please excuse the rough code as it is to display a concept without over complicating it with my end goal. and I haven’t learned how to cleanly exit the threads on endless loops.

        import threading
        import time
        from evdev import InputDevice
        from select import select
        i = 0
        gamepad = InputDevice(‘/dev/input/event0’)

        def ctl_event():
        while True:
        r,w,x = select([gamepad],[],[])
        for event in gamepad.read():

        def iterate_i(i):
        while True:
        print(“i = “)

        t1 = threading.Thread(target=ctl_event)
        t2 = threading.Thread(target=iterate_i, args=(i,))


  1. Thank you very much it helps me a lot to play with my little robot. My gamepad send different code, but with your command it is easy to see what I needed. I also add [0] at the end of lines “elif keyevent.keycode”, otherwise I get more information.

    1. Thanks for the feedback. I’m not surprised your gamepad sends different codes. I just had 2 d-pads that were supposed to be the same model send slightly different codes.

  2. Great Great post! I have been looking for a step-by-step tutorial like this one for a while (hey, just bookmarked your blog …and waiting to do the same for http://putteringabout.net/). I am using the GameSir G3, and I notice that when I press a button, instead of detecting 1 event, 7 events are detected. I used the following code:

    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”
    elif keyevent.keycode == ‘BTN_Y’:
    print “Forward”
    elif keyevent.keycode == ‘BTN_B’:
    print “Right”
    elif keyevent.keycode == ‘BTN_X’:
    print “Left”

    When pressing the ‘A’ button for example, the following would be printed:

    Do you see similar output?

  3. Thanks! I’m using an SNES controller to run a photo booth and your tutorial was just what I needed to get the buttons mapped.

  4. The whole joystick interaction with Python ghas to be fixed, Pygame is writting on console screen al time and evdrv waits for the event to be produced – so no other activities are possible if the event did not happen. I can eventually “keep a button pressed al time”

    I’m looking since a while to find a decent solution for using joysticks with a controled output to console screen – I want to avoid the pygame graph interface for speeed resons. Yes there are solutions if I swithch to C or Java but not Python at least as I see it.

    In some way this is going deep in the reason for which Linux is advancing so slow in regular users world.

    Let me know if you have suggestions

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Proudly powered by WordPress | Theme: Baskerville 2 by Anders Noren.

Up ↑

%d bloggers like this: