Accueil > GNU/LINUX & RASPBERRY PI > Utilisation du GPIO avec Wiringpi-python

Utilisation du GPIO avec Wiringpi-python

samedi 1er octobre 2016, par thebault

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

Installation sur Raspbian Jessie

git clone --recursive https://github.com/WiringPi/WiringPi-Python.git
cd WiringPi-Python
./build.sh

Utiliser la bibliothèque

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 fonctiondescription
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/

JPEG - 305.3 ko

Commander une sortie logique

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 fonctiondescription
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.

  1. import wiringpi
  2. import time
  3.  
  4. wiringpi.wiringPiSetupPhys()
  5. wiringpi.pinMode(11,1)
  6.  
  7. while True :
  8. wiringpi.digitalWrite(11,0)
  9. time.sleep(1)
  10. wiringpi.digitalWrite(11,1)
  11. time.sleep(1)

Télécharger

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 :

BMP - 76.1 ko

Lire une entrée logique

On va lire l’entrée sur la broche 12 et afficher cet état dans la console.

Les fonctions utilisées :

Nom de la fonctiondescription
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

  1. import wiringpi
  2.  
  3. wiringpi.wiringPiSetupPhys()
  4. wiringpi.pinMode(12,0)
  5.  
  6. while True :
  7. input=wiringpi.digitalRead(12)
  8. if (input==0):
  9. print "broche 12 = 0"
  10. if (input==1):
  11. print "broche 12 = 1"

Télécharger

Contrôler les résistances de PULL UP et PULL DOWN

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 fonctiondescription
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 :

JPEG - 18.1 ko
interrupteurétat entrée GPIO
ouvert 0 (0V)
fermé 1 (3.3V)

Avec résistance de pull up :

JPEG - 17.8 ko
interrupteurétat entrée GPIO
ouvert 1 (3.3V)
fermé 0 (0V)

Exemple input2.py avec une résistance de pull-up :

  1. import wiringpi
  2.  
  3. wiringpi.wiringPiSetupPhys()
  4. wiringpi.pinMode(12,0)
  5. wiringpi.pullUpDnControl(12,2)
  6.  
  7. while True :
  8. input=wiringpi.digitalRead(12)
  9. if (input==0):
  10. print "broche 12 = 0"
  11. if (input==1):
  12. print "broche 12 = 1"

Télécharger

Pour l’exécuter en administrateur : sudo python input2.py

Les sorties PWM (Pulse Width Modulation)

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)

  • le mode "balanced" : la fréquence n’est pas constante, ce qui peut poser problème lors de la commande d’un moteur ou d’une led...
  • le mode "M/S" : c’est le mode que l’on utilisera car la fréquence est constante
Nom de la fonctiondescription
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%.

  1. import wiringpi
  2.  
  3. wiringpi.wiringPiSetupPhys()
  4. wiringpi.pinMode(32,2)
  5. wiringpi.pwmSetMode(0)
  6.  
  7. wiringpi.pwmWrite(32,700)

Télécharger

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 :

BMP - 76.1 ko

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)

  • pwmFrequency = fréquence des signaux PWM
  • pwmClock = diviseur du signal d’horloge
  • pwmRange = plage de variation du code du rapport cyclique

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 fonctiondescription
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 :

  1. import wiringpi
  2.  
  3. wiringpi.wiringPiSetupPhys()
  4. wiringpi.pinMode(32,2)
  5.  
  6. wiringpi.pwmSetMode(0)
  7. wiringpi.pwmSetRange(1024)
  8. wiringpi.pwmSetClock(10)
  9.  
  10. wiringpi.pwmWrite(32,700)

Télécharger

Pour l’exécuter en administrateur : sudo python pwm2.py

et le chronogramme qui correspond à la fréquence calculée :

BMP - 76.1 ko

Les temporisations

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 fonctiondescription
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...() )

  1. import wiringpi
  2.  
  3. wiringpi.wiringPiSetupPhys()
  4.  
  5. while True :
  6. wiringpi.delay(500)
  7. instant=wiringpi.millis()
  8. print instant

Télécharger

Voici ce que l’on obtient (on voit bien de légers décalages temporels qui apparaissent) :

JPEG - 30 ko

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 :

  1. import wiringpi
  2.  
  3. wiringpi.wiringPiSetupPhys()
  4. wiringpi.pinMode(11,1)
  5.  
  6. while True :
  7. wiringpi.digitalWrite(11,0)
  8. wiringpi.delay(1000)
  9. wiringpi.digitalWrite(11,1)
  10. wiringpi.delay(1000)

Télécharger

Gestion des interruptions

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 fonctiondescription
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 :

  1. import wiringpi
  2.  
  3. def afficher():
  4. print "front descendant sur broche 11 ! "
  5.  
  6. wiringpi.wiringPiSetupPhys()
  7. wiringpi.pinMode(11,0)
  8. wiringpi.wiringPiISR(11,1,afficher)
  9.  
  10. while True :
  11. wiringpi.delay(1000)
  12. print "attente ..."

Télécharger

SPIP | | Plan du site | Suivre la vie du site RSS 2.0
Habillage visuel © digitalnature sous Licence GPL