Hack-wipy-button

De MCHobby - Wiki
Sauter à la navigation Sauter à la recherche
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.


MCHobby investit du temps et de l'argent dans la réalisation de traduction et/ou documentation. C'est un travail long et fastidieux réalisé dans l'esprit Open-Source... donc gratuit et librement accessible.
SI vous aimez nos traductions et documentations ALORS aidez nous à en produire plus en achetant vos produits chez MCHobby.

Ce que nous faisons

Nous allons apprendre à lire l'état d'une entrée sur le WiPy. Pour cela, nous allons configurer une broche comme entrée (et activer la résistance pull-up). Lorsque l'utilisateur pressera la bouton, nous allumerons la LED HeartBeat de la carte pendant 3 secondes.

Pour commencer, attrapez les éléments listés ci-dessous et raccordez le tout comme indiqué. Une fois le circuit monté, vous devez charger le programme sur la carte WiPy.

Pour cet exemple, vous aurez besoin d'un WiPy, un Breadboard, un bouton poussoir et une résistance et un câble micoUSB.

Résistance Pull-up

Le but d'une résistance pull-up est de maintenir le niveau de la broche d'entrée au niveau haut (3.3v) par défaut. Cela signifie que si le montage n'impose pas une tension sur la broche, celle-ci reste au niveau haut.

Avec certains microcontrôleurs, cette résistance doit être montée par vos soins, avec d'autres (comme le WiPy) cette résistance existe dans le microcontrôleur et il suffit alors de l'activer.

Voici un petit montage (provenant d'Arduino) qui explique le fonctionnement d'une résistance pull-up de 10 KOhms.

Button-PullUp-3.3v.png
Source: AdaFruit

Si le bouton n'est pas presser les deux résistances placent le potentiel de la broche sur 3.3v (comme il n'y a pas de courant... il n'y a pas vraiment de chute de tension dans les résistances). GP8 est donc à +3.3v.

Si le bouton est pressé, la broches GP8 est ramenée à la masse (0V) par l'intermédiaire de la résistance de 100 Ohms. La résistance de 10KOhms est alors également branchée à la masse, ce qui fait qu'un courant de 3.3 / 10000 = 0.33mA y passe (négligeable).

La résistance de 100 Ohms est une résistance de protection et n'est pas obligatoire. Elle est par ailleurs rarement utilisée par les habitués. Prenez la cas ou vous avez configuré la broche en sortie, placée au niveau haut (3.3v) par votre programme. Si vous pressez le bouton sans résistance de sortie et que vous pressiez le bouton? Et bien, s'il n'y avait pas la résistance de 100 Ohms, vous auriez un court-circuit franc, ce qui endommagerait votre WiPy. S'il y a une résistance de 100 Ohms, vous n'avez plus de court-circuit mais un courant de 3.3V / 100 = 33 mA (beaucoup de trop pour une sortie WiPy mais il s'es sortira peut être si vous n'insistez pas).

Le bouton tactile

Dans les montages présentés ci-dessous, le bouton tactile proposé par MC Hobby peut se monter très facilement.

Sa forme carrée peut laisser penser qu'il est facile de monter le bouton "de travers" puisqu'il est facile de le tourner d'un quart de tour, un demi tour.

Bouton tactile raccordement 1.jpg

Il n'est pourtant pas nécessaire d'avoir recourt à un multimètre pour être certain du montage, tout soucis de mauvais raccordement peut facilement être écarté en utilisant le principe suivant:

"Toujours utiliser les bornes de deux coins totalement opposés pour effectuer le raccordement" (simple et efficace)

Bouton tactile raccordement 2.jpg

Vous constaterez dans l'exemple ci-dessus que même si le bouton est tourné d'un quart de tour (à droite de l'image), la position des points de raccordements (en bleu) font que ce dernier opère toujours correctement. Il n'y a ni court-circuit, ni dysfonctionnement :-) .

Matériel nécessaire

PYBX-BTN.png

Bouton poussoir
x1

 

Schéma

Voici le schéma correspondant à nos raccordement.

WiPy-Button-schema.png

Brancher

Connectez tous les éléments ensembles comme présenté sur l'image.

WiPy-Hack-Button-01.jpg
Made with - réalisé avec - Fritzing fritzing.org

Programme simple

Lire l'état du bouton

Pour lire l'état du bouton, vous devez déclarer la broche en entrée et activer la résistance pull-up (voyez l'explication en début d'article)

from machine import Pin
gp8 = Pin( 'GP8', mode=Pin.IN, pull=Pin.PULL_UP )

Pour lire la valeur de la broche, vous pouvez utiliser les deux possibilités suivantes:

gp8()
gp8.value()

Dans les deux cas, la fonction retourne:

  • 0 si la broche est au niveau bas
  • 1 si la broche est au niveau haut

Attention: logique inversée

La broche GP8 sera:

  • au niveau haut (3.3v) lorsque personne ne presse sur le bouton
  • au niveau bas (0v) lorsque quelqu'un presse le bouton

L'appel gp8.value() retourne donc un valeur en logique inversée:

  • 1: signifie que le bouton N'EST PAS pressé
  • 0: signifie que le bouton EST pressé

Exemple

# Cet exemple controle la LED heartbeat et la fait clignoter jusqu'à ce que l'on presse 
#    sur le bouton raccordé sur GP8.
# Le but est d'apprendre a utiliser une entrée du WiPy avec un bouton
# 
#
# Ou acheter un WiPy et une carte d'extension
#   http://shop.mchobby.be/product.php?id_product=736 
#   http://shop.mchobby.be/product.php?id_product=737
#   http://shop.mchobby.be/category.php?id_category=68
#
# Voyez le tutoriel 
#   http://wiki.mchobby.be/index.php?title=Hack-wipy-button
#
# Auteur: Meurisse D. pour shop.mchoby.be
# Licence: CC-BY-SA
#
from machine import Pin
import time
import wipy

# Desactiver HeartBeat + reconfigurer
wipy.heartbeat( False )
led = Pin( 'GP25', mode=Pin.OUT )
led.value( 0 )

# Declare la broche en entrée
gp8 = Pin( 'GP8', mode=Pin.IN, pull=Pin.PULL_UP )

# tant que le bouton n'est pas pressé
while gp8.value() == 1:
    led.toggle()         # changer etat led
    time.sleep_ms( 200 ) # attendre 0.2 sec

# Eteindre la LED
led.value( 0 )

# Réactiver heartbeat
del( led )
wipy.heartbeat( True )

Interruption et callback

Ce qui serait idéal, c'est d'appeler automatiquement une fonction lorsque le bouton est pressé. Une telle fonction est appelée fonction callback.

Nous allons utiliser le principe d'interruption qui permet d'interrompre le programme principal lorsqu'une broche change d'état.

Le processus d'interruption appel alors une fonction (dite fonction de rappel ou fonction callback) qui effectue la tâche attendue puis rend la main au système.

Mode d'interruption

il y a plusieurs modes d'interruption (comme décrits dans cet article Arduino), les plus utilisés sont:

Les flans montant (dit "rising")

L'interruption est déclenchée (voir la flèche bleue) lorsque le signal passe du niveau bas au niveau haut.

Hack-wipy-button-irq-rising.jpg

Les flans descendant (dit "falling")

L'interruption est déclenchée (voir la flèche bleue) lorsque le signal passe du niveau bas au niveau haut.

Hack-wipy-button-irq-falling.jpg

Limitation des interruptions

  1. Vous ne pouvez pas utiliser la fonction print() dans la fonction de callback. Il ne se passera rien.
  2. Vous ne pouvez pas faire d'allocation de mémoire dans la fonction d'interruption (cela pourrait changer dans le futur).
    Toutes les variables et objets doivent exister avant le premier appel de la fonction callback.
  3. ... d'autres contraintes peuvent exister, référez vous à la documentation de MicroPython

Exemple

Dans cet exemple nous allons prendre le contrôle de la LED HeartBeat et la faire changer d'état à chaque fois que l'on presse sur le bouton raccorder sur GP8.

# Cet exemple utilise les interruption et callback pour changer l'état de 
# la LED heartbeat à chaque fois que le bouton branché sur GP8 est pressé.
# 
#
# Ou acheter un WiPy et une carte d'extension
#   http://shop.mchobby.be/product.php?id_product=736 
#   http://shop.mchobby.be/product.php?id_product=737
#   http://shop.mchobby.be/category.php?id_category=68
#
# Voyez le tutoriel 
#   http://wiki.mchobby.be/index.php?title=Hack-wipy-button
#
# Auteur: Meurisse D. pour shop.mchoby.be
# Licence: CC-BY-SA
#
from machine import Pin
import wipy

# Réutilisation de la LED heartbeat
wipy.heartbeat( False )
led = Pin( 'GP25', mode=Pin.OUT )
led.value( 0 )

# Definir la fonction callback pour
# inverser l'etat de la LED Heartbeat
#
def pincb( pin ):
     led.toggle()

# Definir la broche GP8 comme entrée et activer 
# la résistance pull-up
p8 = Pin( 'GP8', mode=Pin.IN, pull=Pin.PULL_UP )

# Définir l'interruption sur flanc descendant (falling) pour 
# appeler la fonction callback
i = p8.irq( trigger=Pin.IRQ_FALLING, handler=pincb )

Voila, vous pouvez maintenant presser le bouton et voir la LED HeartBeat changer d'état à chaque pression.

Nous avons utilisé l'option trigger=Pin.IRQ_FALLING car l'entrée est configurée en Pull-Up. L'entrée GP8 est donc continuellement au niveau haut... et passe au niveau bas lorsque l'on presse sur le bouton poussoir. Il faut donc détecter le flanc descendant du signal.

Tel que définit ci-avant, il est possible de déclencher la fonction callback directement

# Appel direct de la fonction callback
i()

Une interruption peut également être désactivée avec Modèle:I.disable() et réactivée avec Modèle:I.enable().

Déparasitage des boutons

Vous aurez certainement remarqué que, suivant les cas, la LED heartbeat change d'état une ou plusieurs fois même si vous pressez une seule fois le bouton.

Cela arrive souvent avec les boutons mécaniques où le contact n'est pas franc mais passer pas une phase transitoire avec plusieurs rebond avant le contact définitif.

Switchbounce.jpg
Exemple de contact parasite lors du relâchement d'un bouton.
Le même phénomène se produit lorsque le bouton est pressé.

Ce sont ces rebonds qui déclenchent plusieurs fois l'interruption.

Déparasitage des boutons

Il y a différentes techniques de déparasitages. Si vous utilisez les interruptions & callback, vous aurez besoin d'utiliser une méthode de déparasitage matérielle.

déparasitage logiciel

Si vous avez lisez l'état du bouton dans votre programme, vous pourrez utiliser une méthode de déparasitage logiciel comme celle-ci utilisé ci-dessous.

Nous avons créé une classe PullUpButton qui fait du déparasitage logiciel sur une entrée équipée d'un bouton avec résistance pull-up. Cette classe est stockée dans le fichier debounce.py

Vous pouvez télécharger le fichier debounce.py et le placer directement dans le répertoire /flash/lib/ de votre WiPy.

Download-icon.pngTéléchargez debounce.py

Hack-wipy-button-debounce.jpg

Voici comment exploiter la classe PullUpButton, cet exemple attends que le bouton soit presser 5x pour sortir de la boucle de comptage.

from debounce import PullUpButton
import time

btn = PullUpButton( 'GP8' )

counter=0
while counter < 5:
    print( 'presser le bouton svp' )
    while not btn.is_pressed():
        time.sleep_ms( 100 )
    counter=counter+1
    print( 'counter = %i' % counter )

ce qui produit le résultat suivant après exactement 5 pressions physiques sur le bouton... les rebonds de contact ne viennent plus nous importuner.

presser le bouton svp
counter = 1
presser le bouton svp
counter = 2
presser le bouton svp
counter = 3
presser le bouton svp
counter = 4
presser le bouton svp
counter = 5

Classe PullUpButton

Pour les plus curieux, voici l'implémentation de la classe PullUpButton que vous trouverez dans le fichier debounce.py.

Vous pouvez clairement y voir une seconde relecture de l'entrée après un délais de 10 millisecondes. C'est là qu'intervient le déparasitage logicielle de l'entrée.

from machine import Pin
import time

class PullUpButton:
    """ Classe pour gérer un bouton pull-up sur une broche X. 
        Détecte lorsque la broche passe à 0 """
    p = None # Pin object
    state = None # Last known state

    def __init__( self, button_pin ):
        self.p = Pin( button_pin, Pin.IN, pull=Pin.PULL_UP )
        self.state = self.p.value()
    
    def is_pressed(self):
        """ vérifie si le bouton est pressé / détecte le changement
		    d'état. Ne sera signalé qu'une seule fois! """
        val = self.p.value()
        result = False
        if val != self.state:
            # relecture dans 10 ms (deboucing)
            time.sleep_ms( 10 )
            val2 = self.p.value()
            if val == val2: # valeur stable :)
                self.state = val
                result = (val == 0) # Is pressed
        return result

Modèle:HACK-WIPY-TRAILER