Librairie Python evdev sur Raspberry Pi. Récupérer les actions d'un Gamepad dans vos projets DIY (servomoteur, jeux…) • Domotique et objets connectés à faire soi-même

La librairie Python evdev permet de décoder les codes envoyés par les périphériques d’entrées (clavier, sourie, joystick analogique, gamepad…) pour les exploiter dans n’importe quel projet. On pourra par exemple utiliser un Gamepad dans un projet de jeu ou piloter les servomoteurs d’un bras robotique comme le ROT2U 6DOF présenté dans cet article.

Dans cet article nous allons apprendre comment décoder les codes d’un Gamepad analogique compatible avec les consoles Nintendo que l’on trouve très couramment pour moins de 2€ sur AliExpress. La librairie Python evdev fonctionne sur les systèmes Linux. On pourra développer des projets sur Raspberry Pi 3 (ou RPIZero) ou un PC Linux (Ubuntu par exemple). Par contre, comme elle exploite les événements du noyau (kernel) Linux, elle n’est pas disponible sur Windows ou macOS.

Installer Python et la librairie evdev sur Raspberry Pi OS

Python 2.7 est installé par défaut sur la distribution Raspbian. Pour vous en assurer, ouvrez un Terminal et exécutez la commande suivante

#python --version
Python 2.7.9

Maintenant vérifiez que le paquet pip permettant d’installer facilement des librairies est installé

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

Si pip n’est pas installé, exécutez cette commande

sudo apt-get install python-pip

Installez enfin python-dev et la librairie evdev

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

Voilà, il ne reste plus qu’à mettre à jour le système pour disposer des dernières versions des librairies

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

Comment identifier le port USB sur lequel est branché le Gamepad ou le joystick ?

Les périphériques de saisie (clavier, souris) ainsi que les manettes, gamepad et joysticks sont des périphériques input sous Linux. Exécutez une première fois la commande ls /dev/input

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

Maintenant connectez le Gamepad (ou un joystick) et exécutez de nouveau la commande pour identifier le port. Ici, on pourra récupérer les actions du Gamepad sur l’event2.

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

La librairie evdev est livrée avec un script qui permet de décoder les codes des périphériques d’entrées branchés au PC Linux ou au Raspberry Pi. Le script vous demande quel périphérique il doit écouter. Ici, c’est le n°2 sur le device /dev/input/event2 . Appuyez sur les boutons et les flèches pour récupérer les codes. Comme vous pouvez le constater, la librairie permet de détecter l’appui (press) et le relâchement (release) d’un bouton.

#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 --------

Présentation (rapide) de la librairie Python evdev

La librairie evdev pour Linux permet donc de récupérer le code des touches ou des boutons ainsi que la position de chaque axe des joysticks analogiques. Toutes les commandes sont détaillées ici. Certains gamepad se comportent comme des joysticks analogiques. Par exemple pour ce clone de gamepad Nintendo, les des flèches horizontales constituent l’axe X. Les deux flèches verticales, l’axe Y. La position centrale renvoi la valeur 127. Chaque extrémité renvoie 0 ou 255. Par exemple en haut (Up), l’axe Y renvoi 255. En bas (Down), l’axe Y renvoi 0.

La librairie permet de récupérer trois informations pour chaque événement :

  • Son type. EV_KEY pour les touches ou les boutons. EV_ABS pour récupérer la position d’un axe analogique
  • Son code
  • Sa valeur (value). 1 (appui, press) ou 0 (relâché, release) pour un bouton. Une position codée sur 8bits. Elle dépend de chaque fabricant. Ici, le gamepad renvoi 0, 127 (centre) ou 255

vhmxavnntoummeh0ljhb-9234708

Comment récupérer les codes d’un Gamepad USB SNES ?

Passons à la pratique maintenant. Pour le tutoriel, j’ai utilisé un Gamepad USB. On trouve très facilement ce clone du Gamepad de la Nintendo Super NES pour moins de 2€ sur AliExpress par exemple. Il pourra également convenir pour réaliser un borne d’arcade Recalbox (présentée ici) ou Retropie.

Créer un nouveau script (nano joy.py ) et collez le code ci-dessous. Modifiez l’adresse du Gamepad à la ligne 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

Enregistrez avec CTRL + X puis Y ou O (en français). Lancez le script python joy.py. Pour arrêter le script, faites CTRL+C au clavier. Comme vous pouvez le voir, on récupère maintenant le code pour chaque bouton. Lorsqu’on appuie sur un bouton, la val (value) passe à 1. Lorsqu’on relâche, la val passe à 0. Idem pour les directions X et Y testées successivement. A chaque fois qu’on relâche la flèche, l’axe retourne à sa position centrale 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

Code Python pour décoder les actions sur le Gamepad

Maintenant que l’on connait tous les codes associés aux boutons du gamepad, il ne reste plus qu’à tester chaque événement pour récupérer les actions dans un jeu ou piloter les servomoteurs d’un bras robotique. Créez un nouveau script et collez le code ci-dessous en modifiant l’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")

Maintenant, on peut décoder chaque action sur le gamepad très facilement. Dans le prochain tutoriel, nous verrons comment utiliser la librairie pour piloter le bras robotique présenté précédemment.

Avez-vous aimé cet article ?