Dans un des premiers articles de hardware-libre, j’ai expliqué comment ajouter un bouton d’extinction ou de reboot au Raspberry Pi.
Nous allons aujourd’hui améliorer ce système en rajoutant une possibilité bien pratique : des fonctions différentes selon la durée d’appui sur le bouton.
Pour faire suite à l’article précédent, nous aurons désormais 2 fonctions :
– reboot sur un appui entre 1 et 4 secondes,
– arrêt complet sur un appui long de plus de 4 secondes
Le code fourni ici rajoute une autre possibilité d’appui très court, entre 0.2 et 1 seconde, mais nous l’utiliserons simplement afin d’éviter un reboot en cas d’appui malencontreux.
Bien que ce ne soit pas obligatoire, nous allons modifier un peu le circuit. La raison est qu’en ayant le bouton directement entre le GPIO et le GND, si une erreur dans un script configure le GPIO en sortie, et qu’on le presse à ce moment là, on va créer un court-circuit au niveau du GPIO, qui risque de griller.
Nous allons donc supprimer complètement ce risque en rajoutant simplement une résistance de pull-up. Voici un petit schéma rapide de cette modification :
La résistance de pull-up permet de limiter le courant si le GPIO est malencontreusement configuré en sortie, et le bouton pressé.
Coté code, les commentaires sont je pense suffisant pour expliquer le tout :
#!/usr/bin/env python2.7 from time import sleep import subprocess import RPi.GPIO as GPIO # On choisit le GPIO 23 (pin 16) pour notre bouton CHANNEL = 23 # On definit nos durees long_press = 1 very_long_press = 4 # on met RPi.GPIO en mode notation BCM GPIO.setmode(GPIO.BCM) # on initialise le GPIO 23 en mode entree GPIO.setup(CHANNEL, GPIO.IN, pull_up_down=GPIO.PUD_UP) # notre fonction extinction def shutdown(): subprocess.call(['shutdown -h now "Arret du systeme par bouton GPIO" &'], shell=True) # notre fonction reboot def reboot(): subprocess.call(['sudo reboot "Reboot du systeme par bouton GPIO" &'], shell=True) # notre fonction de gestion du bouton def system_button(CHANNEL): # cette variable servira a stocker le temps de pression button_press_timer = 0 while True: if (GPIO.input(CHANNEL) == False) : # le bouton a ete presse... button_press_timer += 0.2 # ... on enregistre le temps que cela dure else: # le bouton a ete relache, on compte combien de temps cela a dure if (button_press_timer > very_long_press) : print "very long press : ", button_press_timer shutdown() elif (button_press_timer > long_press) : print "long press : ", button_press_timer reboot() elif (button_press_timer > 0.2): print "short press : ", button_press_timer button_press_timer = 0 # on attend 0.2 secondes avant la boucle suivante afin de reduire la charge sur le CPU sleep(0.2) # on met le bouton en ecoute par interruption, detection falling edge sur le canal choisi, et un debounce de 200 millisecondes GPIO.add_event_detect(CHANNEL, GPIO.FALLING, callback=system_button, bouncetime=200) # ici vous pouvez mettre du code qui sera execute normalement, sans influence de la fonction bouton try: while True: # faites ce qui vous plait sleep (2) # on reinitialise les ports GPIO en sortie de script except KeyboardInterrupt: GPIO.cleanup() GPIO.cleanup()
Vous remarquerez qu’on a introduit le module subprocess à la place du module os pour appeler nos commandes shutdown et reboot, ce qui est bien plus efficace « pythoniquement » parlant. Je vous invite à suivre ce lien pour en apprendre plus à ce sujet.
L’option « bouncetime=200 » de la fonction « GPIO.add_event_detect », quant à elle, effectue un premier filtrage du bouton (pour éviter par exemple les micro-relachements lors d’un appui).
Pour améliorer le système, on pourrait également par exemple rajouter une led,
– allumée pour signaler que le Pi est démarré et prêt,
– clignotement rapide pour signaler un reboot,
– clignotement lent pour signaler une extinction,
……
A vous de faire preuve d’imagination, tout est possible 😉
Edit :
– En cas d’erreur du type « TypeError: set_callback() takes at most 3 arguments (4 given) » lors de l’execution du script, il vous faudra installer / mettre à jour le composant RPi.GPIO :
sudo apt-get update sudo apt-get install python-dev sudo apt-get install python-rpi.gpio
– En cas d’erreur avec la fonction reboot (usage: reboot [-n] [-w] [-d] [-f] [-h] [-i] …), il suffit de modifier la ligne 26 :
subprocess.call(['sudo reboot -f "Reboot du systeme par bouton GPIO" &'], shell=True)
ou encore :
subprocess.call(['sudo shutdown -r now "Reboot du systeme par bouton GPIO" &'], shell=True)
Merci à Djeremaille 😉
26 réflexions au sujet de « Raspberry Pi : Plusieurs fonctions avec un seul bouton »