Python library evdev on Raspberry Pi to use a Gamepad in your DIY projects (servomotor, games, robotic…)

The Python evdev library makes it possible to decode the codes sent by the input devices (keyboard, mouse, analog joystick, gamepad …) to exploit them in any project. We can for example use a gamepad in a game project or drive the servomotors of a robotic arm as the ROT2U 6DOF presented in this article. In this article we will learn how to decode the codes of an analog Gamepad compatible with Nintendo consoles that are very commonly found for less than $2.5 / €2 on AliExpress. The Python evdev library works on Linux systems. We can develop projects on Raspberry Pi 3 (or RPIZero) or a Linux PC (Ubuntu for example). On the other hand, as it exploits Linux kernel events, it is not available on Windows or macOS.

Install python and the evdev library on Raspbian for Raspberry Pi 3

Python 2.7 is installed by default on the Raspbian distribution. To make sure, open a Terminal and run the following command

#python --version
Python 2.7.9

Now check that the pip package for easily installing libraries is installed

#pip --version
pip 9.0.1 from /Library/Python/2.7/site-packages/pip-9.0.1-py2.7.egg (python 2.7)

If pip is not installed, run this command

sudo apt-get install python-pip

Then python-dev and the evdev librarie

sudo apt-get install python-pip
sudo pip install evdev

That’s it, it remains only to update the system to have the latest versions of the libraries

sudo apt-get update && apt-get upgrade -y

Identify the USB port to which the Gamepad or joystick is connected

Input devices (keyboard, mouse) as well as joysticks, gamepads and joysticks are input devices under Linux. Run the ls / dev / input command a first time

# ls /dev/input/
by-id  by-path  event0  event1  mice

Now connect the Gamepad (or a joystick) and run the command again to identify the port. Here, we can recover the Gamepad actions on the event2.

# ls /dev/input/
by-id  by-path  event0  event1  event2  mice

The evdev library comes with a script that decodes the input device codes connected to the Linux PC or Raspberry Pi. The script asks you which device to listen to. Here is the # 2 on the device  /dev/input/event2 . Press the buttons and arrows to retrieve the codes. As you can see, the library can detect the press and release of a button.

#python /usr/local/lib/python2.7/dist-packages/evdev/evtest.py
ID  Device               Name                                Phys
------------------------------------------------------------------------------------------
0   /dev/input/event0    Dell Dell USB Keyboard              usb-3f980000.usb-1.2.1/input0
1   /dev/input/event1    Dell Dell USB Keyboard              usb-3f980000.usb-1.2.1/input1
2   /dev/input/event2    usb gamepad                         usb-3f980000.usb-1.5/input0

Select devices [0-2]: 2
Listening for events (press ctrl-c to exit) ...
time 1513586374.34    type 4 (EV_MSC), code 4    (MSC_SCAN), value 589826
time 1513586374.34    type 1 (EV_KEY), code 289  (BTN_THUMB), value 1
time 1513586374.34    --------- SYN_REPORT --------
time 1513586374.54    type 4 (EV_MSC), code 4    (MSC_SCAN), value 589826
time 1513586374.54    type 1 (EV_KEY), code 289  (BTN_THUMB), value 0
time 1513586374.54    --------- SYN_REPORT --------
time 1513586377.8     type 4 (EV_MSC), code 4    (MSC_SCAN), value 589828
time 1513586377.8     type 1 (EV_KEY), code 291  (BTN_TOP), value 1
time 1513586377.8     --------- SYN_REPORT --------
time 1513586377.96    type 4 (EV_MSC), code 4    (MSC_SCAN), value 589828
time 1513586377.96    type 1 (EV_KEY), code 291  (BTN_TOP), value 0
time 1513586377.96    --------- SYN_REPORT --------
time 1513586379.36    type 3 (EV_ABS), code 1    (ABS_Y), value 0
time 1513586379.36    --------- SYN_REPORT --------
time 1513586379.53    type 3 (EV_ABS), code 1    (ABS_Y), value 127
time 1513586379.53    --------- SYN_REPORT --------

Presentation (fast) of the Python evdev library

The evdev library for Linux therefore allows to recover the code of the keys or the buttons as well as the position of each axis of the analog joysticks. All orders are detailed here. Some gamepad behave like analog joysticks. For example, for this Nintendo gamepad clone, the horizontal arrows constitute the X axis. The two vertical arrows, the Y axis. The central position returns the value 127. Each end returns 0 or 255. For example, at the top (Up ), the Y axis returns 255. Down (Down), the Y axis returns 0.

The library can retrieve three pieces of information for each event:

  • His type. EV_KEY for keys or buttons. EV_ABS to retrieve the position of an analog axis
  • His code
  • Its value. 1 (press, press) or 0 (release, release) for a button. A position coded on 8bits. It depends on each manufacturer. Here, the gamepad returns 0, 127 (center) or 255

snes gamepad joystick

Recover codes from a USB SNES Gamepad

Let’s go to practice now. For the tutorial, I used a USB Gamepad. It is very easy to find this clone of the Gamepad Nintendo Super NES for less than $2.5 / 2€ on AliExpress for example. It may also be suitable for making a Recalbox arcade terminal (shown here) or Retropie.

Create a new script (nano joy.py ) and paste the code below. Change the Gamepad address to line 5

#import evdev
from evdev import InputDevice, categorize, ecodes

#cree un objet gamepad | creates object gamepad
gamepad = InputDevice('/dev/input/event2')

#affiche la liste des device connectes | prints out device info at start
print(gamepad)

#affiche les codes interceptes |  display codes
for event in gamepad.read_loop():
    #Boutons | buttons 
    if event.type == ecodes.EV_KEY:
        print(event)
    #Gamepad analogique | Analog gamepad
    elif event.type == ecodes.EV_ABS:
        absevent = categorize(event)
        print ecodes.bytype[absevent.event.type][absevent.event.code], absevent.event.value

Save with CTRL + X then Y or O (in French). Launch the python script joy.py. To stop the script, press CTRL + C on the keyboard. As you can see, we now get the code for each button. When a button is pressed, the val (value) goes to 1. When released, the value goes to 0. The same applies for the X and Y directions tested successively. Each time the arrow is released, the axis returns to its central position 127.

# python joy.py 
device /dev/input/event2, name "usb gamepad           ", phys "usb-3f980000.usb-1.5/input0"
event at 1513587909.748564, code 289, type 01, val 01
event at 1513587910.412649, code 289, type 01, val 00
ABS_Y 0
ABS_Y 127
ABS_Y 255
ABS_Y 127
ABS_X 0
ABS_X 127
ABS_X 255
ABS_X 127

Decode all Gamepad actions

Now that we know all the codes associated with the gamepad buttons, it only remains to test each event to retrieve the actions in a game or drive the servomotors of a robotic arm. Create a new script and paste the code below by editing the event.

#import evdev
from evdev import InputDevice, categorize, ecodes

#cree un objet gamepad | creates object gamepad
gamepad = InputDevice('/dev/input/event2')

#affiche la liste des device connectes | prints out device info at start
print(gamepad)

aBtn = 289
bBtn = 290
xBtn = 288
yBtn = 291
lBtn = 292
rBtn = 293
selBtn = 296
staBtn = 297

#affiche les codes interceptes |  display codes
for event in gamepad.read_loop():
    #Boutons | buttons 
    if event.type == ecodes.EV_KEY:
        #print(event)
        if event.value == 1:
            if event.code == xBtn:
                print("X")
            elif event.code == bBtn:
                print("B")
            elif event.code == aBtn:
                print("A")
            elif event.code == yBtn:
                print("Y")
            elif event.code == lBtn:
                print("LEFT")
            elif event.code == rBtn:
                print("RIGHT")
            elif event.code == selBtn:
                print("Select")
            elif event.code == staBtn:
                print("Start")
        elif event.value == 0:
          print("Relache | Release")

    #Gamepad analogique | Analog gamepad
    elif event.type == ecodes.EV_ABS:
        absevent = categorize(event)
        #print ecodes.bytype[absevent.event.type][absevent.event.code], absevent.event.value
        if ecodes.bytype[absevent.event.type][absevent.event.code] == "ABS_X":
             if absevent.event.value == 0:
                print("Gauche | Left")
             elif absevent.event.value == 255:
                print("Droite | Right")
             elif absevent.event.value == 127:
                print("Centre | Center")
        elif ecodes.bytype[absevent.event.type][absevent.event.code] == "ABS_Y":
             if absevent.event.value == 0:
                print("Haut | Up")
             elif absevent.event.value == 255:
                print("Bas | Down")
             elif absevent.event.value == 127:
                print("Centre | Center")

Now we can decode each action on the gamepad very easily. In the next tutorial, we will see how to use the library to drive the robotic arm presented previously.

Subscribe to the weekly newsletter

No spam and no other use will be made of your email. You can unsubscribe anytime.

DIY Projects