Accueil > GNU/LINUX & RASPBERRY PI > Utilisation du GPIO avec Wiringpi-python
samedi 1er octobre 2016, par
Le site du projet https://github.com/WiringPi/WiringPi-Python
La bibliothèque WiringPI est une bibliothèque C écrite par Gordon ’drogon’ Henderson qui permet de contrôler le GPIO du raspberry pi.
Il existe une bibliothèque python Wiring-python qui permet d’utiliser WiringPi.
L’un gros avantage de cette bibliothèque est d’utiliser les sorties matériels PWM (hard pwm) alors que RPi.GPIO n’utilise que des versions logicielles des PWM (soft PWM) qui amènent beaucoup de jitter sur les sorties suivant le taux de charge du raspi.
Enfin, WiringPI utilise une syntaxe proche de celle d’Arduino.
NE PAS OUBLIER : LES ENTREES/SORTIES DU GPIO SONT EN 3,3V
git clone --recursive https://github.com/WiringPi/WiringPi-Python.git
cd WiringPi-Python
./build.sh
1ère étape : appeler la bibliothèque import wiringpi
2ème étape : initialiser la bibliothèque
Lors de l’initialisation, on a 3 choix pour nommer les broches du connecteur :
Nom de la fonction | description | |
---|---|---|
wiringpi.wiringPiSetup() | On utilise la numérotation des broches propre à la bibliothèque | |
wiringpi.wiringPiSetupGpio() | On utilise la numérotation des broches suivant les noms des E/S du GPIO Broadcom | |
wiringpi.wiringPiSetupPhys() | On utilise la numérotation des broches suivant l’ordre des broches sur le connecteur "physique" P1 du raspberry |
Pour voir les broches en ligne :http://pinout.xyz/
Dans la suite, je vais utiliser la numérotation "physique" des broches sur le connecteur. Nous allons faire l’équivalent du "Hello World !" : faire "clignoter" la sortie broche 11.
Il va être nécessaire de configurer la broche 11 en sortie. Pour cela, on utilise les fonctions :
Nom de la fonction | description | |
---|---|---|
wiringpi.pinMode (n,1) | configure la broche n en sortie (1) | |
wiringpi.digitalWrite(n,0) | met à 0 la broche n | |
wiringpi.digitalWrite(n,1) | met à 1 la broche n |
Le programme blink.py. On utilise la bibliothèque time pour réaliser les temporisations de 1s.
import wiringpi import time wiringpi.wiringPiSetupPhys() wiringpi.pinMode(11,1) while True : wiringpi.digitalWrite(11,0) time.sleep(1) wiringpi.digitalWrite(11,1) time.sleep(1)
Le programme doit être lancé en mode administrateur à l’aide de la commande sudo.
sudo python blink.py
On obtient le signal suivant sur la broche 11 :
On va lire l’entrée sur la broche 12 et afficher cet état dans la console.
Les fonctions utilisées :
Nom de la fonction | description | |
---|---|---|
wiringpi.pinMode(n,0) | configure la broche n en entrée (0) | |
wiringpi.digitalRead(n) | lit l’état sur l’entrée n |
le programme input.py
import wiringpi wiringpi.wiringPiSetupPhys() wiringpi.pinMode(12,0) while True : input=wiringpi.digitalRead(12) if (input==0): print "broche 12 = 0" if (input==1): print "broche 12 = 1"
Les résistances de pull-up et de pull-down permettent de contrôler l’état des entrées lorsque celles-ci sont en l’air (typiquement, lorsque l’on utilise un interrupteur en entrée).
Nom de la fonction | description | |
---|---|---|
wiringpi.pullUpDnControl(n,0) | pas de résistance de pull-up ou pull-down | |
wiringpi.pullUpDnControl(n,1) | résistance de pull-down enclenchée | |
wiringpi.pullUpDnControl(n,2) | résistance de pull-up enclenchée |
Avec résistance de pull down :
interrupteur | état entrée GPIO | |
---|---|---|
ouvert | 0 (0V) | |
fermé | 1 (3.3V) |
Avec résistance de pull up :
interrupteur | état entrée GPIO | |
---|---|---|
ouvert | 1 (3.3V) | |
fermé | 0 (0V) |
Exemple input2.py avec une résistance de pull-up :
import wiringpi wiringpi.wiringPiSetupPhys() wiringpi.pinMode(12,0) wiringpi.pullUpDnControl(12,2) while True : input=wiringpi.digitalRead(12) if (input==0): print "broche 12 = 0" if (input==1): print "broche 12 = 1"
Pour l’exécuter en administrateur : sudo python input2.py
Le raspberry pi est équipé de 2 sorties PWM : broche 32 (BCM18) et broche 33 (BCM 27).
Le raspberry peut avoir 2 modes de fonctionnement (cf datasheet p139)
Nom de la fonction | description | |
---|---|---|
wiringpi.pinMode(n,2) | Sortie n en PWM | |
wiringpi.pwmSetMode(n,0) | mode M/S | |
wiringpi.pwmSetMode(n,1) | mode balanced | |
wiringpi.pwmWrite(n,rapport cyclique) | commande la sortie PWM sur la broche n, avec un rapport cyclique compris entre 0 et 1024 (codé sur 10 bit) |
Le programme pwm1.py suivant permet de générer un signal de rapport cyclique 700/1024=0.68=68%.
import wiringpi wiringpi.wiringPiSetupPhys() wiringpi.pinMode(32,2) wiringpi.pwmSetMode(0) wiringpi.pwmWrite(32,700)
Pour l’exécuter en administrateur : sudo python pwm1.py
Remarque : on peut aussi utiliser la broche 33 comme expliqué précédemment
Le chronogramme obtenu sur la broche 32 est le suivant :
Le période du signal est d’environ 3,4 x 500 us = 1,7 ms, soit une fréquence de 586 Hz environ (voir paragraphe suivant pour le calcul).
Réglage de la fréquence des sorties PWM et de la plage du codage du rapport cyclique
La fréquence des sortie PWM est définie par la relation :
pwmFrequency in Hz = 19.2 MHz / (pwmClock x pwmRange)
Ainsi, dans l’essai précédent (fonctionnement par défaut), on a pwmClock=33, et pwmRange=1024.
Par conséquent, si on souhaite augmenter le fréquence à quelques KHz, il faut changer le rapport de pwmClock (et diminuer pwmRange si on veut obtenir une fréquence supérieure à 18.75 kHz).
Le choix pwmClock=10 permet d’avoir une fréquence en sortie de 1.875kHz, ce qui est plus adapté pour un moteur.
Les fonctions pour configurer les sorties PWM :
Nom de la fonction | description | |
---|---|---|
wiringpi.pwmSetMode(n,0) | mode M/S | |
wiringpi.pwmSetClock(pwmClock) | modifie la valeur du diviseur pwmClock | |
wiringpi.pwmSetRange(pwmRange) | modifie la valeur du code max du rapport cyclique |
Cela donne le programme pwm2.py suivant :
import wiringpi wiringpi.wiringPiSetupPhys() wiringpi.pinMode(32,2) wiringpi.pwmSetMode(0) wiringpi.pwmSetRange(1024) wiringpi.pwmSetClock(10) wiringpi.pwmWrite(32,700)
Pour l’exécuter en administrateur : sudo python pwm2.py
et le chronogramme qui correspond à la fréquence calculée :
La bibliothèque permet de gérer des temporisations et des mesures de durées.
Pour utiliser ces fonctions, il est obligatoire d’initialiser la bibliothèque à l’aide d’une des 3 commandes wiringpi.wiringPiSetup...()
.
Lorsque l’évènement (front montant, descendant ou les deux) est détecté sur l’entrée, on quitte le programme principal pour exécuter une fonction
Nom de la fonction | description | |
---|---|---|
wiringpi.millis() | mesure le nombre de millisecondes ms écoulées depuis l’initalisation avec wiringpi.wirinPiSetup...() | |
wiringpi.micros() | mesure le nombre de micro-secondes us écoulées depuis l’initalisation avec wiringpi.wirinPiSetup...() | |
wiringpi.delay(durée) | temporisation de "durée" en millisecondes | |
wiringpi.delayMicroseconds(durée) | temporisation de "durée" en microsecondes |
ATTENTION : nous ne sommes pas avec un système "temps réel" comme avec un microcontrôleur. Du fait de l’OS GNU/Linux qui est multitâches et qui ne gère donc pas que notre programme (mais aussi l’affichage, le réseau ...) les durées des tempos sont des durées minimales qui peuvent être légèrement supérieures dans la pratique.
Exemple timing1.py qui permet d’afficher toutes les 500ms la durée depuis le lancement du programme (plus précisément depuis l’initialisation wiringpi.wiringPiSetup...() )
import wiringpi wiringpi.wiringPiSetupPhys() while True : wiringpi.delay(500) instant=wiringpi.millis() print instant
Voici ce que l’on obtient (on voit bien de légers décalages temporels qui apparaissent) :
Un 2ème exemple d’utilisation de la bibliothèque. On reprend le programme blink.py du début du tuto (faire changer d’état la sortie 11 toutes les secondes) mais sans utiliser la bibliothèque time.
Le programme timing2.py :
import wiringpi wiringpi.wiringPiSetupPhys() wiringpi.pinMode(11,1) while True : wiringpi.digitalWrite(11,0) wiringpi.delay(1000) wiringpi.digitalWrite(11,1) wiringpi.delay(1000)
Le bibliothèque permet de gérer les interruptions sur n’importe quelle broche du connecteur.
Cela peut être très pratique lorsque l’on ne veut pas faire du "polling" d’entrée (c’est à dire scruter constamment l’état des entrées).
Avec les interruptions, on peut détecter les changements d’états suivants : front montant (EDGE RISING), front descendant (EDGE FALLING), et les 2 (EDGE_BOTH).
Fonction :
Nom de la fonction | description | |
---|---|---|
wiringpi.wiringPiISR(n,1,fonction) | interruption sur front montant sur l’entrée n provoquant l’exécution de "fonction" | |
wiringpi.wiringPiISR(n,2,fonction) | interruption sur front descendant sur l’entrée n provoquant l’exécution de "fonction" | |
wiringpi.wiringPiISR(n,3,fonction) | interruption sur front descendant ou montant sur l’entrée n provoquant l’exécution de "fonction" |
Voici un programme interruption.py qui indique lorsqu’un front descendant (EDGE FALLING) est détecté sur la broche 11 du raspberry :
import wiringpi def afficher(): print "front descendant sur broche 11 ! " wiringpi.wiringPiSetupPhys() wiringpi.pinMode(11,0) wiringpi.wiringPiISR(11,1,afficher) while True : wiringpi.delay(1000) print "attente ..."