Modifications

Sauter à la navigation Sauter à la recherche
6 855 octets ajoutés ,  13 juin 2016 à 18:13
Ligne 153 : Ligne 153 :  
L'interruption est déclenchée (voir la flèche bleue) lorsque le signal passe du niveau bas au niveau haut.
 
L'interruption est déclenchée (voir la flèche bleue) lorsque le signal passe du niveau bas au niveau haut.
   −
[[Fichier:Hack-wipy-button-irq-rising.jpg]]
+
[[Fichier:Hack-wipy-button-irq-rising.jpg|480px]]
    
==== Les flans descendant (dit "'''falling'''") ====
 
==== 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.
 
L'interruption est déclenchée (voir la flèche bleue) lorsque le signal passe du niveau bas au niveau haut.
   −
[[Fichier:Hack-wipy-button-irq-falling.jpg]]
+
[[Fichier:Hack-wipy-button-irq-falling.jpg|480px]]
 +
 
 +
=== Limitation des interruptions ===
 +
{{ambox-stop|text=Une interruption et l'éxecution de la fonction ''callback'' reste un processus exceptionnel qui prend place (qui s'insère sauvagement) dans l'exécution d'un programme principal.
 +
 
 +
Il y a donc des limitations et contraintes à l'utilisation d'une fonction d'interruption avec MicroPython}}
 +
 
 +
# Vous ne pouvez pas utiliser la fonction {{fname|print()}} dans la fonction de callback. Il ne se passera rien.
 +
# Vous ne pouvez pas faire d'allocation de mémoire dans la fonction d'interruption (cela pourrait changer dans le futur).<br />Toutes les variables et objets doivent exister {{underline|avant}} le premier appel de la fonction callback.
 +
# ... <small>d'autres contraintes peuvent exister, référez vous à la [https://micropython.org/resources/docs/en/latest/wipy/library/machine.Pin.html documentation de MicroPython]</small> 
 +
 
 +
=== 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.
 +
 
 +
<syntaxhighlight lang="python">
 +
# 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 )
 +
</syntaxhighlight>
 +
 
 +
Voila, vous pouvez maintenant presser le bouton et voir la LED HeartBeat changer d'état à chaque pression.
 +
 
 +
Nous avons utilisé l'option {{fname|1=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
 +
<syntaxhighlight lang="python">
 +
# Appel direct de la fonction callback
 +
i()
 +
</syntaxhighlight>
 +
 
 +
Une interruption peut également être désactivée avec {{i.disable()}} et réactivée avec {{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.
 +
 
 +
[[Fichier:Switchbounce.jpg|480px]]<small><br />Exemple de contact parasite lors du relâchement d'un bouton.<br />Le même phénomène se produit lorsque le bouton est pressé.</small>
 +
 
 +
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.
 +
* [http://wiki.mchobby.be/index.php?title=Entr%C3%A9e_Bouton#D.C3.A9parasitage_des_boutons Déparasitage des boutons pour Arduino] (information utile en tous les cas)
 +
* [http://www.eng.utah.edu/~cs5780/debouncing.pdf http://www.eng.utah.edu/~cs5780/debouncing.pdf] (''anglais'') - document très intéressant avec explications détaillées et différentes techniques de déparasitage.
 +
 
 +
=== 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.
 +
 
 +
<font color="red">Nous avons créé une classe {{fname|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'''</font>
 +
 
 +
Vous pouvez télécharger le fichier '''debounce.py''' et le placer directement dans le répertoire {{fname|/flash/lib/}} de votre WiPy.
 +
 
 +
{{download-box|Téléchargez debounce.py|http://df.mchobby.be/wipy/debounce.py}}
 +
 
 +
[[Fichier:Hack-wipy-button-debounce.jpg|800px]]
 +
 
 +
Voici comment exploiter la classe {{fname|PullUpButton}}, cet exemple attends que le bouton soit presser 5x pour sortir de la boucle de comptage.
 +
 
 +
<syntaxhighlight lang="python">
 +
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 )
 +
</syntaxhighlight>
 +
 
 +
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.
 +
 
 +
<nowiki>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</nowiki>
 +
 
 +
==== Classe PullUpButton ====
 +
Pour les plus curieux, voici l'implémentation de la classe {{fname|PullUpButton}} que vous trouverez dans le fichier {{fname|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.
 +
 
 +
<syntaxhighlight lang="python">
 +
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
 +
</syntaxhighlight>
    
{{HACK-WIPY-TRAILER}}
 
{{HACK-WIPY-TRAILER}}
29 917

modifications

Menu de navigation