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.
Sommaire
- 1 Installer Python et la librairie evdev sur Raspberry Pi OS
- 2 Comment identifier le port USB sur lequel est branché le Gamepad ou le joystick ?
- 3 Présentation (rapide) de la librairie Python evdev
- 4 Comment récupérer les codes d’un Gamepad USB SNES ?
- 5 Code Python pour décoder les actions sur le Gamepad
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
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 ?