Dans cet article, nous allons voir comment mesurer la température ambiante avec deux types de sondes thermomètres très différentes : la sonde numérique DS18B20 et la sonde analogique TMP36. Dans les deux cas, il s’agit d’un minuscule composant à trois pattes, dont la résistance des composants internes varie en fonction de la température.
Archives par étiquette : gpio
GPIO – Servos moteurs, joypad et WiFi
Nous allons voir dans cet article comment réaliser une station de pilotage à distance pour commander des servos moteurs, à l’aide d’un Raspberry Pi, d’un joypad et d’un lien WiFi. Dans cet exemple j’uitiliserai un eeePC 901 pour la station de pilotage, mais il est tout à fait possible d’utiliser un deuxième Raspberry Pi.
Voici un schéma global :
La construction de ce dispositif se fait en trois étapes :
- Contrôle des servos moteurs par le Pi
- Utilisation du joypad
- Envoi des commandes à distance par wifi
Liste du matériel utilisé dans cet article
1 – Contrôle des servos moteurs par le Pi
Pour piloter plusieurs servos moteurs avec un Pi, nous n’avons d’autre choix que de passer par une carte contrôleur. Le site Adafruit propose justement un circuit permettant de contrôler jusqu’à 16 servos moteurs en utilisant le bus I²C (disponible sur le GPIO du Pi comme expliqué dans cet article GPIO – Entrée en matière).
Vous pouvez acheter ce circuit directement sur le site d’Adafruit : Adafruit 16-Channel 12-bit PWM/Servo Driver – I2C interface – PCA9685
Vous devrez sortir votre fer et souder les broches sur le circuit imprimé 🙂 Un bornier est prévu pour connecter une source d’alimentation. J’utilise un bloc coupleur de pile avec 4 piles AA pour fournir une tension de 6V, parfait pour alimenter mes servos moteurs.
Côté servos, je dispose de deux gros FUTABA S3010 et d’un minuscule FUTABA S3114.
Le branchement de la carte sur le Pi peut se faire simplement à l’aide de wire jumpers. Il suffit de connecter l’alimentation (3,3V et la masse/ground) ainsi que les broches SCL et SDA comme sur le schéma ci-dessous :
Une fois les branchements effectués, il convient d’activer le support de l’I²C sur le Raspberry Pi. Ceci se fait en deux étapes :
1 – Editez le fichier /etc/modules et ajoutez les deux lignes suivantes :
i2c-bcm2708 i2c-dev
2 – Editez ensuite le fichier /etc/modprobe.d/raspi-blacklist.conf et commentez les deux lignes suivantes (en ajoutant # au début de ces deux lignes) :
# blacklist spi-bcm2708 # blacklist i2c-bcm2708
Pour finir, installez l’outil i2c-tools et redémarrez le Pi :
apt-get install i2c-tools shutdown -r now
Pour vérifer que la carte est bien reconnue par le Pi, lancez la commande suivante :
i2cdetect -y 1 # pour la révision 2 du Pi ou i2cdetect -y 0 # pour la première version du Pi
Vous devriez obtenir ce résultat :
root@raspberrypi:~# i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: 70 -- -- -- -- -- -- --
Bien ! Nous allons maintenant écrire le programme en Python qui va nous permettre de piloter ces servos moteurs. Python est installé par défaut sur Raspbian, il ne manque que certains paquets :
apt-get install python-dev python-rpi.gpio python-smbus
Adafruit propose une librairie Python qui permet de dialoguer facilement avec les différents composants distribués par son site. Nous n’allons pas nous en priver 🙂 Pour télécharger la dernière version disponible de cette librairie, il suffit d’en récupérer les sources sur le dépôt GIT :
git clone https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code.git
La partie qui nous intéresse ici se trouve dans le répertoire Adafruit-Raspberry-Pi-Python-Code/Adafruit_PWM_Servo_Driver.
Dans un premier temps, voici un petit script qui permet de tester les servos test_servo.py :
#!/usr/bin/python from Adafruit_PWM_Servo_Driver import PWM import sys pwm = PWM(0x40, debug=True) pwm.setPWMFreq(60) pwm.setPWM(int(sys.argv[1]), 0, int(sys.argv[2]))
Pensez à rendre ce script exécutable grâce à la commande chmod 755 test_servo.py
Ce script prend deux paramètres :
- l’id du port contrôlant un servo de 0 à 15
- une valeur, généralement entre 150 et 600 qui détermine la position que doit prendre le servo
Exemples pour commander le servo branché sur le premier port (ayant pour id 0) :
./test_servo.py 0 480 ./test_servo.py 0 240
Et voilà, si tout s’est bien passé, vous devriez pouvoir piloter vos servos de cette manière. Nous verrons plus loin dans cet article comment les piloter avec un joypad et à distance 🙂
Note : Je ne sais absolument pas pourquoi le troisième paramètre de la fonction setPWM() doit être entre 150 et 600… De même, je ne sais pas à quoi correspond le deuxième paramètre attendu par cette fonction. Si quelqu’un connaît la réponse, merci de nous expliquer cela en commentaire de cet article 🙂
2 – Utilisation du joypad
Je dispose d’un magnifique joypad USB, modèle Saitek P990 munis de deux mini-joysticks ou « chapeaux chinois ». Nous allons utiliser ces deux joysticks pour piloter nos servos.
Un joystick qu’est ce que c’est ? En fait, c’est simplement un potentiomètre dont la valeur (la résistance) est interprétée et traduite en nombre. Sur ce modèle de joypad, les valeurs sont échantillonnées de 0 à 1023 (soit 1024 valeurs possibles). Pour obtenir deux axes, il y a deux potentiomètres par joystick. Avec deux joysticks, nous avons donc de quoi piloter indépendamment 4 servos 🙂
La librairie Python evdev permet d’interagir facilement avec les événements déclenchés par des périphériques USB. Pour l’installer :
apt-get install python-pip python-dev pip install evdev
Avant d’écrire un script Python qui sache interpréter les actions de ces joysticks, vous devez connaître l’identifiant « event » attribué par le système au moment où vous branchez votre joypad USB.
lsusb
Bus 001 Device 003: ID 05e3:0608 Genesys Logic, Inc. USB-2.0 4-Port HUB Bus 001 Device 005: ID 05e3:0505 Genesys Logic, Inc. Bus 002 Device 003: ID 06a3:040b Saitek PLC P990 Dual Analog Pad Bus 005 Device 002: ID 0b05:b700 ASUSTek Computer, Inc. Broadcom Bluetooth 2.1 Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 001 Device 006: ID 11b0:6148 ATECH FLASH TECHNOLOGY Bus 001 Device 007: ID 05af:3062 Jing-Mold Enterprise Co., Ltd Cordless Keyboard Bus 001 Device 008: ID 046d:c016 Logitech, Inc. Optical Wheel Mouse
Mon joypad est bien reconnu par le système avec la dénomination : « Saitek PLC P990 Dual Analog Pad« .
cat /proc/bus/input/devices
Cherchez la référence à votre joypad et repérez l’identifiant « event », ici nous avons l’identifiant « event6« .
[...] I: Bus=0003 Vendor=06a3 Product=040b Version=0100 N: Name="Saitek P990 Dual Analog Pad" P: Phys=usb-0000:00:1d.0-2/input0 S: Sysfs=/devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/input/input15 U: Uniq= H: Handlers=event6 js0 B: PROP=0 B: EV=1b B: KEY=3fff 0 0 0 0 0 0 0 0 0 B: ABS=30027 B: MSC=10 [...]
A chaque fois que l’on va presser un bouton sur le joypad, ou actionner un de ses joysticks, un événement sera déclenché. Il s’agit donc de surveiller en permanence les événements déclenchés et d’agir en fonction. Voici maintenant un petit script Python qui permet de tester votre joypad et d’identifier les différents événements liés à chaque joystick et chaque bouton : test_joypad.py
#!/usr/bin/python from evdev import InputDevice, categorize, ecodes from time import sleep from datetime import date import os, sys, socket dev = InputDevice('/dev/input/event6') # reprendre le même identifiant "event" print(dev) for event in dev.read_loop(): # boucle qui surveille l'arrivée d'un événement e_code=event.code e_type=event.type e_value=event.value print(str(e_type)+' - '+str(e_code)+' - '+str(e_value))
A chaque fois que vous toucherez quelque chose sur votre joypad, ce script affichera trois variables, e_code, e_type et e_value :
./test_joystick.py device /dev/input/event6, name "Saitek P990 Dual Analog Pad", phys "usb-0000:00:1d.0-2/input0" 3 - 0 - 508 3 - 0 - 412 3 - 0 - 347 3 - 0 - 391 3 - 0 - 457 3 - 0 - 511 3 - 1 - 602 3 - 1 - 701 3 - 1 - 771 3 - 1 - 659 3 - 1 - 561 3 - 1 - 511
Voilà ce que j’obtiens en actionnant le joystick gauche de mon joypad, identifié par l’e_code 3. Dans l’axes des X, j’obtiens un e_type 0, et un e_type 1 pour l’axe des Y. Lorsque je relâche le joystick en position centrale, les valeurs sont proches de 512 (valeur médiane entre 0 et 1023). Ces caractéristiques sont propres à ce modèle de joypad, mais le principe de fonctionnement est le même pour tous 🙂 Ce petit script vous permettra de noter l’e_code et l’e_type de chaque bouton et joystick que vous voulez utiliser.
Pour ma part, j’ai trois servos à piloter, et je dispose de deux joysticks avec chacun deux axes. J’utiliserai l’axe X du joystick gauche (e_code 3, e_type 0) pour piloter le servo 1. L’axe Y du joystick gauche (e_code 3, e_type 1) pour piloter le servo 2. Et enfin l’axe X joystick droit (e_code 3, e_type 5) pour piloter le servo 3 🙂
A partir de là, vous pouvez facilement imaginer associer le servo 1 au roulis d’un avion, le servo 2 au tangage et le servo 3 au lacet par exemple 🙂
La dernière étape consiste à envoyer les commandes du joypad, branché sur la station de pilotage, au Raspberry Pi qui répercutera les ordres sur ses servos 🙂
3 – Envoi des commandes à distance par wifi
Nous avons d’un côté un script Python qui tourne sur un Raspberry Pi qui a pour rôle de piloter des servos. De l’autre, nous avons un eeePC (ou autre machine…), qui exécute un second script Python dont le but est d’interpréter les commandes envoyées par un joypad. Il s’agit maintenant de faire communiquer ces deux scripts entre eux, ce que nous pouvons facilement faire grâce aux sockets 🙂
Sans trop rentrer dans les détails, il s’agit d’ouvrir une socket au niveau du script qui s’exécute sur le Pi afin qu’il soit à l’écoute de messages envoyés par le script côté « station de pilotage ». Le script côté « station de pilotage » se connecte à cette socket en passant par le réseau IP (via WiFi), et envoie les commandes déclenchées par le joypad.
Côté Raspberry Pi :
#!/usr/bin/python from Adafruit_PWM_Servo_Driver import PWM import sys, os, socket listen_address = ('0.0.0.0', 12800) # écoute sur toutes les interface sur le port 12800 srv_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # protocole UDP srv_socket.bind(listen_address) print "server enabled" pwm = PWM(0x40, debug=True) # initialisation de la carte contrôleur pwm.setPWMFreq(60) while True: query, clt_address = srv_socket.recvfrom(1024) # écoute les message order=query.split('_') # on découpe les messages reçus servo=order[0] pos=order[1] print str(query)+' - '+str(servo)+' - '+str(pos) # on affiche les infos pwm.setPWM(int(servo), 0, int(pos)) # on envoie la commande au servo sys.exit(0)
Côté Station de pilotage :
#!/usr/bin/python from evdev import InputDevice, categorize, ecodes from time import sleep from datetime import date import os, sys, socket now = date.today() print(now) clt_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # protocole UDP srv_address = ('192.168.101.27', 12800) # on vise l'adresse IP du Pi sur le port 12800 dev = InputDevice('/dev/input/event6') # initialisation du joypad print(dev) def convertAxis (value, axis_max): # fonction qui convertie les valeurs des joystick facteur=axis_max/490 new_value=int(round((value/facteur)+150, 0)) return new_value for event in dev.read_loop(): # pour chaque événement détecté e_code=event.code e_type=event.type e_value=event.value print(str(e_type)+' - '+str(e_code)+' - '+str(e_value)) if e_type == 3: if e_code == 0: # à destination du servo 1 servo_pos=str(convertAxis (e_value, 1024)) clt_socket.sendto("0_"+servo_pos, srv_address) elif e_code == 1: # à destination du servo 2 servo_pos=str(convertAxis (e_value, 1024)) clt_socket.sendto("1_"+servo_pos, srv_address) elif e_code == 5: # à destination du servo 3 servo_pos=str(convertAxis (e_value, 512)) clt_socket.sendto("2_"+servo_pos, srv_address)
Conclusions
En déclinant ce principe, vous pouvez piloter de nombreux servos moteurs à distance et commencer à envisager la construction systèmes complexes comme des robots ou des drones 🙂
En parlant de drone, ces articles relatifs au GPIO me serviront à construire un drone avion, comme expliqué ici : Raspberry Pi BOA Drone 🙂
Cependant, certaines zones d’ombre persistes, notamment sur le pilotage de servos. L’utilisation de la lib distribuée par Adafruit évite de se poser de question, cela fonctionne immédiatement. La contre partie, c’est qu’on ne comprend pas forcément tout ce qui se passe. Aussi, j’invite les lecteurs de ce blog à intervenir en commentaire de cet article afin d’apporter des informations complémentaires, des idées ou simplement des remarques 🙂
Merci à vous 🙂
GPIO – Entrée en matière
Grâce à son port GPIO (General Purpose Input/Output), le Raspberry Pi peut interagir avec le monde réel en communiquant avec des capteurs, des moteurs, et un tas d’autres composants électroniques (sondes de température, LEDs, capteurs gyroscopiques, boussoles, GPS, servos moteurs, récepteurs IR/RF…). De la petite commande relais pour piloter vos guirlandes de Noël, au robot, en passant par la station météo et le drone, les possibilités sont sans limites, ou presque 🙂
Le matériel de base
Qui dit GPIO, dit composants électroniques 🙂 Il va de soit que des compétences en électronique de base sont requises. De plus, il convient de s’équiper d’un minimum de matériel afin de pouvoir tester et réaliser de petits circuits.
Voici, selon moi, le stricte minimum du matériel à acheter avant de démarrer :
- une carte d’expérimentation ou « breadbord » : vous permet de réaliser des connexions/branchements entre composants sans soudures
- des câbles « wire jumper » : permet de relier les composants entre eux
- un bloc coupleur de pile : pour alimenter les composants
- Vous pouvez également vous procurer un kit comprenant des composants électroniques de base (LED, résistances,…)
Le port GPIO
Le port GPIO du Pi comporte 26 broches qui peuvent être utilisées de manières différentes. Le schéma ci-dessous (publié par le site eLinux) montre le rôle de chaque broches ainsi que les protocoles qu’elles supportent.
On distingue 7 types de broches et usages qu’on peut en faire :
- Alimentation : 3,3V ou 5V
- Ground : masse 0V
- GPIO : port standard d’entrée/sortie
- I²C : Inter Integrated Circuit
- SPI : Serial Peripheral Interface
- UART : Universal Asynchronous Receiver Transmitter
- PWM : Pulse-width modulation
Ces différents « bus » et « protocoles » permettent d’interfacer le Pi avec d’autres cartes, modules ou composants électroniques.
Les exemples d’utilisation les plus simples des broches de type GPIO sont l’allumage et l’extinction d’une LED, l’interaction avec un bouton/interrupteur, le contrôle de relais, etc,…
L’I²C, le SPI, l’UART et le PWM permettent quant à eux de communiquer avec des microcontrôleurs pour réaliser des opérations plus complexes telles que le contrôle de servos moteurs, la lecture de mesures prises par des capteurs etc,…
Alimentation des broches
Avant toute chose il est important de préciser les broches du port GPIO sont alimentées en 3,3V. Seules les deux broches d’arrivée de courant (en rouge) fournissent une tension de 5V.
Ce qui veut dire qu’en mode ouput (sortie) la tension fournie par une broche est de 3,3V et délivrera un courant de 50mA max. Vous devrez donc vous assurer que les composants que vous reliez à ces broches supportent se type de courant. En mode input (entrée), une broche ne tolérera qu’une tension maximum de 3,3V ! Vous devrez donc toujours faire attention à vos branchements pour éviter d’endommager votre Raspberry Pi 🙂
En outre, il est préférable d’utiliser une source d’alimentation tierce pour les composants et modules électroniques que vous souhaitez ajouter dans votre circuit. En effet, le Raspberry Pi n’est pas suffisamment robuste pour alimenter correctement et sans danger des circuits électroniques. Pour allumer une LED pas de problème, mais pour faire tourner un moteur, prévoyez une source d’alimentation dédiée.
Dans l’absolue, et pour des raisons évidentes de sécurité, je conseille d’utiliser des piles plutôt que de travailler directement sur le secteur (d’où le coupleur de pile dans la liste du matériel de base) 😉
Prendre la main sur le port GPIO
WiringPi est un outil qui permet de contrôler les différentes broches du port GPIO. Pour installer WiringPi :
git clone git://git.drogon.net/wiringPi cd ./wiringPi ./build
A partir de là, vous pouvez obtenir l’état de toutes les broches grâce à la commande :
gpio readall
Ce qui devrait vous afficher un tableau de ce type :
Chaque ligne du tableau représente une broche du port GPIO et vous indique sont mode IN/OUT (entrée/sortie) et sont état/valeur 0/1 (low/high). La colonne GPIO représente le numéro de la broche tel que décrit sur le schéma en haut de cet article. La colonne wiringPi représente le numéro de broche que vous devez utiliser en utilisant la commande gpio.
De manière très simplifiée, si vous voulez allumer une LED, vous devez mettre la broche en mode sortie/output. En mettant l’état de la broche à 1/up, la LED s’allumera. Si vous voulez savoir si un bouton/interrupteur est ouvert ou fermé, vous devez mettre la broche en mode entrée/input. Si vous lisez la valeur 0/down, alors l’interrupteur est ouvert. Si vous lisez la valeur 1/up, alors l’interrupteur est fermé 🙂 Dans la pratique c’est un tout petit peu plus complexe, mais il s’agit là de comprendre le principe.
Pour chaque broche, vous pouvez changer le mode entrée/sortie ou in/out grâce à la commande (<pin> étant le numéro de la broche ciblée) :
gpio mode <pin> in gpio mode <pin> out
En mode entrée/read vous pouvez lire l’état d’une broche avec la commande :
gpio read <pin>
En mode sortie/write, vous pouvez changer l’état d’une grâce à la commande :
gpio write <pin> 0 gpio write <pin> 1
Pour plus d’information sur la commande gpio : http://wiringpi.com/the-gpio-utility/
Quelques exemples de montages simples
En cherchant un peu sur le web vous trouverez une multitude de tutos qui expliquent comment faire de petits montages simples. Inutile de plagier la terre entière en recopiant ici ces tutos, je préfère vous donner directement quelques liens :
- LEDs : http://blog.idleman.fr/raspberry-pi-06-utiliser-le-gpio-et-interagir-avec-le-monde-reel/
- Interrupteurs : http://arduino103.blogspot.fr/2012/10/raccorder-un-bouton-poussoir-sur.html
- Usages divers : http://www.pobot.org/Entrees-sorties-GPIO-sur-Raspberry.html