Rasp-Hack-PiButton

De MCHobby - Wiki
Sauter à la navigation Sauter à la recherche

Introduction

Savoir lire l'état d'une entrée du port GPIO du Raspberry PI est une action fondamentale en hacking électronique.
La détection de la pression d'un bouton permet de re-initialiser un programme, de passer à l'étape suivante, jouer du son, etc.

Voici un exemple qui vous propose de lire l'état d'un bouton (actuateur) placé sur le broche 24 du GPIO.
Note: Cet exemple aurait pu également utiliser la broche 23 ou 25.

En fonction de l'état du bouton, le programme allumera la led Rouge ou Verte.

Un Pi Cobbler d'AdaFruit (disponible chez MC Hobby) est utiliser pour faciliter le montage.

Prérequis

Assurez-vous d'avoir mis votre environnement Python à jour.

Matériel

  • Un Pi-Cobbler
  • 2 x résistance de 330 Ohms (Orange, Orange, Brun)
  • 1 x Led Rouge
  • 1 x Led Verte
  • 1 x résistance de 10 KOhms (Brun, Noir, Orange)
  • 1 x Bouton poussoir momentané (aussi appelé actuateur)
  • Un Rapsberry, fil pour breadboard, breadboard.

Résistance Pull-up

Tout comme pour un montage Arduino, il faut utiliser une résistance pull-up pour ramener le potentiel de la broche GPIO à HIGH (niveau haut).
Lorsque l'on pousse le bouton poussoir, le potentiel de la broche GPIO est forcé à LOW (niveau bas). On évite le court-circuit grâce à la résistance Pull-Up.

Pour connecter un bouton sur un GPIO, il faut utiliser le montage suivant:

3.3v --> Résistance pull-up de 10k --> GPIO --> Bouton --> GND

PiButton-schematic.jpg

Note: Ceux d'entre-vous qui utilisent un Arduino noterons que la tension du GPIO d'un Raspberry est 3.3v (et non 5v comme pour un Arduino)

Montage

Voici le détail du montage

PiButton bb2.jpg


PiButton bb.jpg

Le script Python

Pour créer facilement ce script sur votre python, nous vous proposons une méthode à base de copier/coller à l'aide des étapes suivantes à réaliser dans un terminal (ou une connexion SSH).

Copier/coller le code

Voici une méthode Copier/Coller super simple

On commence par demander la création du fichier

cat <<! > raspi-button.py

On fait ensuite le copier/coller du code

 #!/usr/bin/env python
# -*- coding: latin-1 -*-

import RPi.GPIO as GPIO, time

GPIO.setmode(GPIO.BCM)
GREEN_LED = 18
RED_LED = 23
BUTTON1 = 24

GPIO.setup(GREEN_LED, GPIO.OUT)
GPIO.setup(RED_LED, GPIO.OUT)
GPIO.setup(BUTTON1, GPIO.IN)

while True:
        # Si le bouton est pressé, la broche GPIO est raccordée
        #   à la masse. Le GPIO est donc à LOW (bas).
        # Bouton pressé -> Input = LOW = False 
        if( GPIO.input( BUTTON1 ) == False ):
        	GPIO.output(GREEN_LED, True)
        	GPIO.output(RED_LED, False)
	else:
        	GPIO.output(GREEN_LED, False)
        	GPIO.output(RED_LED, True)

On termine l'opération de saisie simplement avec:

!

Rendre le fichier exécutable

Par défaut, les fichier sont considéré comme des fichiers texte non exécutable... même s'il contiennent des scripts.

Il faut donc indiquer au système d'exploitation qu'il peut autoriser l'exécution de notre raspi-blink.py

chmod +x raspi-button.py

Executer le programme

Taper simplement la commande suivante:

 sudo ./raspi-button.py

Déparasitage Logiciel du bouton

Le contact d'un bouton poussoir momentané (actuateur) n'est pas franc.
Il s'accompagne généralement d'une série de "contacts parasites" avant le contact franc et définitif.

Switchbounce.jpg

Voici un exemple issus d'un article dédié au déparasitage des boutons pour Arduino (voir cet article sur notre blog).

Cette période de "contact parasite" est appelée période transitoire.

Comme un Raspberry est terriblement rapide, il pourrait détecter plusieurs fois les signaux haut et bas durant la période transitoire.
Dans le cadre de ce projet, cela pourrait se manifester de différentes façon:

  • La Led rouge semble clignoter légèrement avant de s'éteindre ou l'allumer.
  • La Led verte ne semble pas s'allumer d'un coup et clignote un peu.
  • Les deux leds "semblent" allumées en même temps pendant une très courte période.

Conséquences du parasitage

dans le cas de ce projet, les conséquences néfastes du parasitage sont purement esthétique.
Par contre, lors de la conception d'un compteur (qui compte le nombre de pression), cette période transitoire fera grimper artificiellement la valeur du compteur.
Difficile dans ce cas de compter le nombre de fois qu'un événement s'est produit.

Solution: le déparasitage logiciel

xxx

Script Python - déparasitage logiciel

Voici le script Python incluant le déparasitage logiciel du bouton.
En plus de faire le déparasitage, il stocke également l'état du bouton dans la variable BUTTON1_STATE en faisant en sorte qu'il soit le vrai reflet de l'état du bouton.
Lorsque le bouton est enfoncé, BUTTON1_STATE est True, lorsque le bouton est relâché BUTTON1_STATE est False.

Copier/coller le code

Voici une méthode Copier/Coller super simple

On commence par demander la création du fichier

cat <<! > raspi-button.py

On fait ensuite le copier/coller du code

#!/usr/bin/env python
# -*- coding: latin-1 -*-

import RPi.GPIO as GPIO, time

GPIO.setmode(GPIO.BCM)
GREEN_LED = 18
RED_LED = 23

BUTTON1 = 24
# Dernier état connu du bouton
# Par defaut: le bouton n'est pas considéré comme activé
BUTTON1_STATE = False

GPIO.setup(GREEN_LED, GPIO.OUT)
GPIO.setup(RED_LED, GPIO.OUT)
GPIO.setup(BUTTON1, GPIO.IN)

while True:
        # -- Lecture avec déparasitage logiciel
        # Si le bouton est pressé, la broche GPIO est raccordée
        #   à la masse. Le GPIO est donc à LOW (bas).
        #   Bouton pressé -> Input = LOW = False         
        gpioRead1 = GPIO.input( BUTTON1 )
        state1    = not(gpioRead1)
        # SI changer d'etat ALORS refaire lecture de déparasitage
        if( state1 != BUTTON1_STATE ):
                # - attendre 10ms
                time.sleep( 10 / 1000 )
                # faire une 2ieme lecture
                gpioRead2 = GPIO.input( BUTTON1 )
                state2 = not(gpioRead2)
                # SI les deux lectures concordent
                # ALORS memoriser le nouvel etat du bouton
                if( state1 == state2 ):
                        BUTTON1_STATE = state2


        # -- Programme principal --
        # SI le bouton est pressé
        # ALORS allumer la LED verte  
        if( BUTTON1_STATE == True ):
                GPIO.output(GREEN_LED, False)
                GPIO.output(RED_LED, True)
        else:
                GPIO.output(GREEN_LED, True)
                GPIO.output(RED_LED, False)