Formation PUB420 : Système domotique DIY, 2020 Scripts Python pour interagir avec le GPIO

10.2 La base des scripts avec RPi.GPIO


Le script Python qui sera en charge d'envoyer ou de recevoir un signal des broches GPIO du Raspberry Pi peut être écrit :

  • directement sur le Pi à l'aide d'un éditeur comme nano.
  • sur l'ordinateur à l'aide de l'éditeur de votre choix, par exemple Geany ou PyCharm. 

La bibliothèque RPi.GPIO sera utilisée dans cette démonstration. Elle est installée par défaut sur Raspberry Pi OS.

Notez que si vous utilisez un éditeur comme PyCharm sur votre ordinateur, il vous donnera des erreurs si votre code utilise des bibliothèques qui sont sur le Pi mais pas sur votre ordinateur. Vous pourrez ignorer ces erreurs.

Le script doit être placé directement sur le Raspberry Pi pour être exécuté. Si vous l'avez écrit sur votre ordinateur, vous devrez le copier sur le Pi Conseil après l'avoir édité.

▼Publicité Le texte se poursuit plus bas

Nom du fichier

Par convention, les scripts Python seront inscrits dans un fichier texte dont le nom se termine par .py.

Le nom du fichier peut :

  • être tout en minuscules (ex : monscript.py)

    ou

  • utiliser la casse serpent (ex : mon_script.py)

Entête du script Python

Lançons-nous dans la programmation!

Tout programme Python doit débuter par une ligne, qu'on appellera shebang ou hash bang.

Le shebang permet de spécifier quel interpréteur doit être utilisé.

Python

#!/usr/bin/env python3

Vient ensuite une ligne qui indique l'encodage du fichier. Cette ligne était nécessaire en Python 2 mais elle est optionnelle en Python 3 puisque l'encodage par défaut est UTF-8.

Python

# -*- coding:utf-8 -*-

Tout programme qui se respecte doit contenir un en-tête standard. Cet en-tête indique notamment le but du script, les paramètres attendus, le montage physique requis, la date de création et l'auteur.

En Python, les commentaires de documentation utilisent la syntaxe DocString et sont placés entre triples guillemets.

Python

"""
Fait clignoter une LED rouge sur le Raspberry Pi
Paramètres : aucun
Montage : LED rouge branchée sur GPIO.BCM 23 et résistance de 330 Ohms
Auteur : Christiane Lagacé
Date : 8 novembre 2021
"""

Vient ensuite le chargement des bibliothèques, ici RPi.GPIO.

Python

import RPi.GPIO as GPIO

Choisir le type d'adressage

Les broches du GPIO peuvent être référées par leur adresse physique (position de la broche sur le Pi, numérotée de 1 à 40) ou par leur adresse broadcom (numéros de ports).

L'adresse BCM est généralement utilisée. Il faut l'indiquer au script comme suit :

Python

GPIO.setmode(GPIO.BCM)

Variables pour les numéros de ports

Le script sera plus facile à lire si vous utilisez des variables pour reternir les numéros des ports que vous utilisez.

Python

led = 23

bouton = 25

Déterminer le sens du signal 

Pour chaque port que vous souhaitez utiliser dans le script, il faut indiquer si le signal sera en entrée ou en sortie.

GPIO.OUT : le Pi peut envoyer un signal au port

Par exemple, pour que le Pi envoie un signal au port 23 afin d'allumer une LED :

Python

GPIO.setup(led, GPIO.OUT)

Il est possible de changer l'état (d'envoyer un signal) dans une instruction indépendante (voir plus bas) ou encore de le faire dans la même instruction :

Python

GPIO.setup(led, GPIO.OUT, initial=1)

GPIO.IN : le Pi peut recevoir un signal du port

Si le programme devait lire la valeur envoyée par un composant branché sur le port 12, par exemple un bouton poussoir :

Python

GPIO.setup(bouton, GPIO.IN)

L'état initial d'un composant peut être « flottant », c'est-à-dire qu'on ne sait pas quel voltage il donne au départ. Ceci n'est pas souhaitable.

Pour régler ce problème, il est possible d'ajouter, par exemple, des résistances pour forcer un état initial à zéro.

Il est également possible de forcer l'état initial du composant à zéro de façon logique, sans nécessiter l'ajout de résistances puisque le Pi a déjà tout ce qu'il faut à l'interne. 

Python

GPIO.setup(bouton, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

Envoi d'un signal

Pour les ports qui reçoivent un signal du Pi (GPIO.OUT), le Pi peut envoyer un signal à l'aide de trois systèmes qui sont équivalents :

  • GPIO.HIGH, GPIO.LOW
  • True, False
  • 1, 0

Pour allumer la LED, on envoie un signal positif :

Python

GPIO.output(led, 1)

Pour l'éteindre, on envoie un signal non positif :

Python

GPIO.output(led, 0)

Pour savoir par programmation dans quel état est le port :

Python

etat = GPIO.input(led)

Réception d'un signal

Pour les ports qui envoient un signal au pi (GPIO.IN), le Pi peut lire la valeur envoyée :

Python

valeur = GPIO.input(bouton)

Événements

Pour détecter quand un port reçoit un signal, par exemple quand un bouton est pressé, deux choix s'offrent à nous :

  • lire continuellement l'état dans une boucle
  • travailler avec les événements

L'événement sera rattaché à une fonction de rappel qui doit être définie dans le haut du programme.

La définition de la fonction commence par le mot-clé def et tout le corps de la fonction doit être décalé de 4 espaces.

Python

def bouton_presse(channel):
    print("Le bouton est enfoncé!")

Pour associer l'événement à la fonction de rappel :

Python

GPIO.add_event_detect(bouton,GPIO.RISING,callback=bouton_presse)

ou

Python

GPIO.add_event_detect(bouton, GPIO.RISING)
GPIO.add_event_callback(bouton, bouton_presse)

Réinitialisation des ports

En terminant, il est conseillé de réinitialiser les ports qui ont été utilisés dans le script. Ceci permet de les protéger d'un bris dû à un court-circuit.

Attention : si un script a pour but d'allumer une lumière et de la laisser allumée, il ne faut pas qu'il réinitialise les ports.

Dans tous les autres cas, il faut le faire.

En effet, un port qui demeurerait assigné en INPUT après l'exécution d'un script et que l'on souhaite assigner en OUTPUT dans un autre script pourrait griller quand on fera les branchements.

C'est pour cela qu'on fera la réinitialisation à la fin du programme.

Ceci fera en sorte, entre autres, que les LED allumées seront éteintes lorsque le programme se terminera.

Python

GPIO.cleanup()

Un programme qui se termine normalement passera toujours par cette ligne.

Pour assurer que la réinitialisation ait lieu même si le programme plante ou s'il se termine quand l'usager appuie sur les touches Ctrl+C, on placera le code dans un try et on fera la réinitialisation dans le finally.

Python

try:
    ...
except:
    ...
finally:
    GPIO.cleanup()

Note : le finally ne sera pas exécuté si l'usager termine le programme avec les touches Ctrl+Z. En effet, alors que Ctrl+C émet un signal SIGINT – qui arrête gentiment le programme, Ctrl+Z émet un signal SIGTSTP qui arrête immédiatement le programme.

Exemple complet : faire clignoter une LED

Pour faire un tout cohérent, voici un petit script qui fait clignoter une LED jusqu'à ce que quelqu'un appuie sur Ctrl+C.

Python

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

"""
Fait clignoter une LED rouge sur le Raspberry Pi
Paramètres : aucun
Montage : LED rouge branchée sur GPIO.BCM 23 et résistance de 330 Ohms
Auteur : Christiane Lagacé
Date : 8 novembre 2021
"""

import RPi.GPIO as GPIO    # il faudra mettre GPIO. devant le nom des classes du paquet
from time import sleep     # les classes du paquets peuvent être utilisées directement sans le nom du paquet

GPIO.setmode(GPIO.BCM)    # type d'adressage broadcom (numéros de ports)
led = 23                   # adresse broadcom du branchement de la LED
GPIO.setup(led, GPIO.OUT)  # sens du signal : le Pi peut envoyer un signal à sa broche (ici, au port 23)

print('Programme qui fait clignoter une LED')
print('Appuyez sur Ctrl+C pour terminer.')

try:
    while True:
        GPIO.output(led, 1)     # envoie 3.3V au port
        sleep(1)
        GPIO.output(led, 0)     # n'envoie rien au port
        sleep(1)
except KeyboardInterrupt:
    print('Fin du programme, vous avez appuyé sur Ctrl+C.')
except Exception as e:
    print('Une exception est survenue.' + str(e))
finally:
    GPIO.cleanup()     # réinitialise les ports
    print('Nettoyage final réalisé avec succès!')

Lancer le script

Pour exécuter le script, entrez la commande python3 suivie du nom du fichier.

Terminal

python3 monscript.py

Pour plus d'information

« RasPi.TV - RPi.GPIO Quick Reference ». RasPi.TV. https://raspi.tv/download/RPi.GPIO-Cheat-Sheet.pdf

« RPi.GPIO basics 3 – How to Exit GPIO programs cleanly, avoid warnings and protect your Pi ». RasPi.TV. https://raspi.tv/2013/rpi-gpio-basics-3-how-to-exit-gpio-programs-cleanly-avoid-warnings-and-protect-your-pi

« RPi.GPIO basics 6 – Using inputs and outputs together with RPi.GPIO – pull-ups and pull-downs ». RasPi.TV. https://raspi.tv/2013/rpi-gpio-basics-6-using-inputs-and-outputs-together-with-rpi-gpio-pull-ups-and-pull-downs

Veuillez noter que le contenu de cette fiche vous est partagé à titre gracieux, au meilleur de mes connaissances et sans aucune garantie.
Par Christiane Lagacé
Dernière révision le 11 février 2023
Merci de partager !

Site fièrement hébergé chez A2 Hosting.

Soumettre