Dans les tutoriels précédents, nous avons vu comment intercepter les actions d’un Gamepad SNES USB sur un PC Linux ou un Raspberry Pi (lire l’article). Nous avons également vu comment communiquer très rapidement (on pourrait presque dire en temps réel) avec un Arduino ou un ESP8266 à l’aide du protocole WebSocket. Aujourd’hui, nous allons assembler ces connaissances pour piloter un bras robotique équipé de 6 servomoteurs (5 axes + 1 pince).
Pour ce tutoriel, nous utiliserons le kit ROT2U 6DOF présenté en détail dans cet tutoriel.
Sommaire
- 1 Un peu de lecture avant de commencer
- 2 Piloter un bras robotique en WiFi : notions abordées dans le tutoriel
- 3 Communication WebSocket entre le Raspberry Pi et la carte ESPduino
- 4 Matériel nécessaire
- 5 Installer les librairies Sumotoy PCA9685 et WebSocket sur l’IDE Arduino
- 6 Installer les librairies Python ws4py et evdev sur le Raspberry Pi
- 7 Assemblage : shield PCA9685 Geekcreit, bras robotisé ROT2U 6DOF, ESPDuino
- 8 Code Python, client WebSocket envoyant les ordres de mouvement en interceptant les actions depuis un Gamepad USB
- 9 Mappage des boutons du Gamepad SNES
- 10 Code Arduino compatible ESP8266 ou ESPDuino, serveur WebSocket et contrôle des axes
- 11 Démo
Un peu de lecture avant de commencer
Avant de commencer, vous pouvez lire ces articles qui expliquent plus en détail les différents aspects techniques abordés dans ce projet.
Pour piloter le bras robotique, vous aurez besoin d’un shield I2C PCA9685 permettant de piloter plusieurs servomoteurs
Vous aurez besoin de connaître les fonctions proposées par la librairie Python evdev qui permet d’intercepter les actions sur les boutons d’un Gamepad (par exemple celui d’une console SNES USB).
Si la technologie Websocket vous parait trop difficile à mettre en oeuvre ou inadaptée à votre projet, vous pouvez utiliser de simples requêtes HTTP. Le déplacement des axes sera toutefois plus saccadé.
Piloter un bras robotique en WiFi : notions abordées dans le tutoriel
Le bras robotisé peut être un simple jeu mais également un excellent outil d’apprentissage en mécanique, électronique, programmation, communication HTTP. Dans cette série d’articles, nous allons aborder les notions suivantes :
- En programmation Arduino en C++
- Comment piloter des servomoteurs
- Comment connecter un Arduino/ESP8266 à un réseau WiFi
- Créer un serveur WebSocket sur un Arduino ou ESP8266. Réception et envoi de messages
- En programmation en Python
- Utilisation des packages evdev, ws4py, threading, time
- Initiation aux threads (fonctions exécutées en parallèle du programme principale)
- Créer un client WebSocket en Python. Envoyer et recevoir des messages de façon asynchrone
- Intercepter les actions sur un Gamepad à l’aide de la librairie evdev pour Linux. Envoyer des ordres de déplacement jusqu’à ce que le bouton soit relâché (à l’aide d’un thread)
- Matériel
Le bras robotique est un très bon outil d’apprentissage en programmation. Cette année, j’espère pouvoir aborder des notions plus complexes en vision industrielle et en programmation de trajectoires. En embarquant une webcam sur la pince on pourrait faire du tri ou de la reconnaissance de forme avec le projet Open Source OpenCV (vous pouvez découvrir OpenCV en lisant cet article). Le top serait de maitriser la programmation de trajectoire à l’aide du projet ROS (Robot Operating System)… 😀
Communication WebSocket entre le Raspberry Pi et la carte ESPduino
Vous l’avez compris, ce projet est un prétexte pour aborder de nombreuses notions de programmation. Dans un prochain tutoriel, nous verrons comment récupérer directement les actions du Gamepad directement sur un ESP8266 ou un Arduino. Ici, on va donc utiliser un Raspberry Pi 3 (ou RPIZero W) pour récupérer les actions à l’aide de la librairie Python evdev. Le script Python créé un client WebSocket. Dès qu’une action est interceptée par la librairie evdev sur le Gamepad, un message est envoyé au serveur WebSocket hébergé sur l’ESP8266. Le code Arduino sera chargé de décoder le message et de déplacer le servomoteur dans la direction demandée.
Si on doit se déplacer de 180° sur un axe, avec un pas d’un degré, on serait obligé d’appuyer 180 fois sur la flèche. Heureusement, la librairie evdev permet de savoir lorsqu’un bouton est appuyé (PRESS) et lorsqu’il est relâché (RELEASE). On va utiliser le système de Thread (fonction qui s’exécute en tâche de fond) de Python pour envoyer à intervalle régulier (par exemple toutes les 50ms) un ordre de déplacement dans la direction souhaitée. L’envoi des messages est interrompu dès qu’on relâche le bouton.
Matériel nécessaire
Pour ce projet, vous aurez besoin du matériel suivant pour le bras robotique
- Un bras robotisé. Je vous conseille le kit ROT2U 6DOF qui est livré avec 6 servomoteurs. Certains kits ne sont pas livrés avec les servomoteurs. Suivez ce tutoriel pour assembler le bras robotique
- Une carte de développement ESPDuino (présentée ici). C’est une carte au format Arduino Uno basée sur un ESP8266. Il est compatible avec les shields (carte d’extension) pour Arduino Uno
- Un shield PCA9685 16 servomoteurs (environ 11€) ou une carte PCA9685 (environ 2€). Je vous conseille le shield Geekcreit (Doit.am) parfaitement géré par la librairie Sumotoy. Pour la mise en route, lisez cet article
- Un jeu de Jumper Dupont (si les câbles fournis sont trop court).
Coté télécommande vous aurez besoin du matériel suivant
- Un Raspberry Pi 3 ou RPIZero W
- Un Gamepad SNES USB ou bluetooth
Installer les librairies Sumotoy PCA9685 et WebSocket sur l’IDE Arduino
Pour ce projet, vous aurez donc besoin d’installer les deux librairies suivantes :
- Sumotoy, la librairie Arduino qui permet de piloter jusqu’à 16 LED ou 16 servomoteurs PWM à l’aide du circuit PCA9685 à l’aide du bus I2C. Allez sur la page du projet pour télécharger la librairie. Lisez ce tutoriel pour plus de détails sur l’emploi de la librairie. Décompressez l’archive ZIP dans le dossier librairies qui se trouve dans vos Documents. Relancez l’IDE Arduino (surtout par avoir accès aux exemples).
- Websocket de Markus Sattler depuis le gestionnaire de bibliothèque de l’IDE Arduino
Installer les librairies Python ws4py et evdev sur le Raspberry Pi
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. La librairie evdev qui permet intercepter les actions d’un Gamepad sur un système Linux (y compris sur un Raspberry Pi). Le dépôt de la librairie se trouve sur cette page GitHub. Lisez ce tutoriel pour plus de détails.
sudo apt-get install python-pip sudo pip install evdev
Pour connaître le port USB sur lequel est branché le Gamepad, 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
Exécutez enfin cette commande pour installer la librairie WebSocket ws4py
pip install ws4py
Assemblage : shield PCA9685 Geekcreit, bras robotisé ROT2U 6DOF, ESPDuino
Une fois votre bras robotique assemblé, il y a très peu de câblage à réaliser. En effet, en utilisant une carte PCA9685 au format Arduino Uno, il n’y a rien à faire à part brancher les servomoteurs ! Si votre ordinateur délivre une tension trop faible à l’ESPDuino, il est possible d’ajouter une alimentation complémentaire. La carte Geekcreit dispose de deux connecteurs 6-18V. Le premier (VM) est destiné à l’alimentation des 2 moteurs à courant continu. Le second à alimenter les servomoteurs (VS).
Code Python, client WebSocket envoyant les ordres de mouvement en interceptant les actions depuis un Gamepad USB
Nous avons vu en détail comment récupérer les actions sur un Gamepad (flèches et boutons) dans ce tutoriel. Regardons comment envoyer les ordres de mouvement au serveur WebSocket hébergé sur l’ESP8266. On va utiliser les Thread Python pour envoyer régulièrement (toutes les 50ms) un ordre de déplacement jusqu’à ce que le bouton (ou la flèche) soit relâchée. Ici, j’ai utilisé des variables globales pour passer des paramètres au Thread :
- servo, l’axe à déplacer (servo0, servo1…servo5)
- direction, la direction du déplacement (UP, DIWN, OPEN, CLOSE)
- send, c’est le booléen qui permet de déclencher ou interrompre l’envoi des requêtes HTTP
Avant de démarrer le Thread, il faut déjà que la connexion avec le serveur WebSocket soit active. Pour cela on va créer un client WebSocket comme nous l’avons vu dans le tutoriel précédent. Avec la librairie ws4py, on créé un objet DummyClient qui permet de récupérer l’état de la connexion ainsi que les messages envoyés par le serveur. Dès que la connexion sera ouverte, on pourra créer le Thread qui contiendra la fonction sendRequest chargée d’envoyer au serveur WebSocket les ordres de mouvement.
class DummyClient(WebSocketClient): def opened(self): t1 = Thread(target=sendRequest) t1.daemon = True t1.start() print("Start Websocket thread") def closed(self, code, reason=None): print "Connexion closed down", code, reason def received_message(self, m): print m
Ensuite, dès qu’une action est détectée sur le Gamepad (event.value == 1 pour les boutons), on modifie les variables servo et direction puis on passe send à True pour déclencher l’envoi des ordres de déplacement. Par défaut la variable httpFreq est réglée à 50ms (.050). Lorsque le bouton est relâché (event.value == 1), on passe send = False pour arrêter l’envoi des requêtes de déplacement. Voici un code qui illustre le fonctionnement général
import requests, time
from evdev import InputDevice, categorize, ecodes
from threading import Thread
# Adresse IP et point d entree de la requete HTTP sur l'ESP8266 | ESP8266 Http and end point
esp8266url = "http://192.168.1.65/cmd"
gamepad = InputDevice('/dev/input/event2')
servo = ""
direction = ""
send = False
httpFreq = .050
class DummyClient(WebSocketClient):
def opened(self):
t1 = Thread(target=sendRequest)
t1.daemon = True
t1.start()
print("Start Websocket thread")
def closed(self, code, reason=None):
print "Connexion closed down", code, reason
def received_message(self, m):
print m
def sendRequest():
global servo
global direction
global send
while True:
payload = servo+":"+direction
if send:
ws.send(payload)
time.sleep(httpFreq)
# Demarre le thread
t1 = Thread(target=sendRequest)
t1.start()
if __name__ == '__main__':
try:
ws = DummyClient(esp8266host, protocols=['http-only', 'chat'])
ws.connect()
print("Ready !")
#evdev takes care of polling the controller in a loop
for event in gamepad.read_loop():
print("Event: ",categorize(event)," |value: ",event.value)
if event.type == ecodes.EV_KEY:
print("button is pressed",categorize(event))
if event.value == 1:
if event.code == xBtn:
servo = "servo2"
direction = "up"
send = True
print("X")
elif event.value == 0:
send = False
except KeyboardInterrupt:
ws.close()
Créez un nouveau script (par exemple nano robotws.py) et collez le code ci-dessous. Vous devez modifier deux paramètres :
- L’adresse IP du serveur WebSocket
- Le port USB sur lequel est branché le Gamepad
Le script Python ne fonctionne que lorsque le serveur WebSocket est démarré. La combinaison de touche CTRL + C permet d’interrompre le script à n’importe quel moment. La connexion WebSocket est automatiquement fermée.
Mappage des boutons du Gamepad SNES
Voici la correspondance des touches du script Python. Libre à vous de le modifier. Comme le mappage est réalisé coté Raspberry Pi, inutile de modifier le code Arduino. Le servo0 correspond à l’axe de rotation de la base. Le servo 5 correspond à la pince.
← | Servo0 (base) | gauche |
→ | Servo0 (base) | droite |
↑ | Servo1 | monter – up |
↓ | Servo1 | descendre – down |
X | Servo2 | monter – up |
B | Servo2 | descendre – down |
Y | Servo3 | monter – up |
A | Servo3 | descendre – down |
L | Servo4 | monter – up |
R | Servo4 | descendre – down |
Select | Servo5 (pince) | ouvrir – open |
Start | Servo5 (pince) | fermer – close |
Code Arduino compatible ESP8266 ou ESPDuino, serveur WebSocket et contrôle des axes
Créez un nouveau croquis et collez le code ci-dessous. Plusieurs paramètres doivent être adaptés à votre configuration :
- ssid, identifiant du réseau WiFi
- password, mot de passe réseau
- SERVO_SPEED, par défaut, le servo fait un pas de 1 degré à chaque mouvement (précis mais pas rapide)
- posServo0 à 5, angle de la position garage (Home)
- pinServo0 à 5, broche sur lequel est branché le servomoteur
Inutile de rentrer dans les détails du code. Tout a déjà été expliqué précédemment. Ici, tous les axes sont gérés.
Démo
Téléversez le programme et ouvrez le moniteur série pour connaître l’adresse IP attribuée au module ESP8266. Vous pouvez la reporter coté client dans le code Python. Dès que le module est connecté au réseau WiFi, vous devez entendre le “ronronnement” des servomoteurs qui sont maintenant alimentés. Lancez le script Python avec la commande python robotws.py . Dès que le client indique qu’il est connecté, vous pouvez commercer à jouer avec le bras robotique à l’aide du Gamepad.
J’espère que vous avez apprécié ce tutoriel. Comme vous pourrez le constater, la technologie Websocket est parfaitement adaptée à ce type de projet. Les mouvements du bras sont très fluides. Le code pourrait encore être amélioré en ajouter la notion de vitesse de déplacement. Dans le prochain tutoriel, nous verrons comment faire avec des requêtes HTTP plus classiques. Vous pourrez constater que les déplacements sont beaucoup plus saccadés.
Avez-vous aimé cet article ?