Broches E/S en entrée

Ce que l'on va faire ici

Ici, nous allons voir comment utiliser les broches GPIO en entrée avec MicroPython

Exemple : Détecter l'appui sur un bouton poussoir

Le montage :

Le circuit à réaliser est le suivant :

Le code

Le code est le suivant :

from machine import Pin, Timer
import utime

bp=Pin(17, Pin.IN, Pin.PULL_UP) # initialisation de la broche en entrée avec rappel au PLUS
led=Pin(25, Pin.OUT)

timer=Timer()

appui=0 # variable état appuyé
#if bp.pull()==Pin.PULL_UP: appui=0 # version "automatique"
# rappel au moins = actif sur niveau HAUT => BP doit être connecté au niveau 3.3V
# rappel au plus = actif sur niveau BAS => BP doit être connecté au 0V

#while(True): # boucle sans fin - à éviter 
def loop(timer):
        if bp.value()==appui: # test si appui
                led.on()
                print ('Appui sur BP')
                utime. sleep_ms(250) # pause anti rebond entre 2 appuis
                led.off()

timer.init(freq=1000, callback=loop) # test le BP 1000 fois par seconde !

L'appui sur le bouton poussoir est détecté !

Une variante plus "propre" : utilisation d'une interruption

Une possibilité très intéressante fournie par Micropython sur la carte Pi Pico est la possibilité d'utiliser une interruption pour détecter une modification de la broche. Voici un code d'exemple :

from machine import Pin

bp = Pin(17, Pin.IN, Pin.PULL_UP) # broche en entree pullup actif

bp.irq( #définition de l'interruption sur la broche 
        lambda pin: print("Appui BP"), # fonction inline
        Pin.IRQ_FALLING # mode de déclenchement
       )

Note

Remarquer :

  • que le code est particulièrement "propre", concis : il n'est plus nécessaire de lire la broche à intervalle régulier, son changement d'état étant intercepté au niveau matériel.

  • comment il est possible "d'éclater" sur plusieurs lignes les paramètres d'une fonction contenus entre parenthèses, d'y placer des commentaires. Cela fait penser par exemple à ce qui est possible en Javascript par exemple. Donc, bien que Python soit sensible à l'indentation, il est plutôt tolérant lorsque l'on est au sein de parenthèses.

  • la façon d'utiliser une fonction "inline" avec le mot-clé lambda

Quelques explications :

  • la définition de l'interruption passe par l'appel de la fonction irq() de la broche que l'on configure. Cette fonction reçoit :

    • la fonction de gestion de l'interruption
    • l'évènement déclencheur, définit à l'aide des propriétés IRQ_FALLING (déclenchement sur front descendant) ou IRQ_RISING (déclenchement sur front montant)
  • la fonction lambda inline reçoit l'objet déclencheur de l'interruption, à savoir ici le bp, que l'on appelle pin : cet objet représente la broche déclencheuse.

Exemple : l'appui sur le BP allume la LED

Le circuit à réaliser est le suivant :

Le code est le suivant :

from machine import Pin, Timer

bp=Pin(17, Pin.IN, Pin.PULL_UP) # initialisation de la broche en entrée avec rappel au PLUS
led=Pin(16, Pin.OUT) # Led en sortie

timer=Timer()

appui=0 # variable état appuyé

def loop(timer):
        if bp.value()==appui: # test si appui
                led.on()
        else:
                led.off()

timer.init(freq=1000, callback=loop) # test le BP 1000 fois par seconde !

Et quand on appuie sur le BP, la LED s'allume... !

Variante avec la Led onboard

from machine import Pin, Timer

bp=Pin(17, Pin.IN, Pin.PULL_UP) # initialisation de la broche en entrée avec rappel au PLUS
led=Pin(25, Pin.OUT) # Led en sortie

timer=Timer()

appui=0 # variable état appuyé

def loop(timer):
        if bp.value()==appui: # test si appui
                led.on()
        else:
                led.off()

timer.init(freq=1000, callback=loop) # test le BP 1000 fois par seconde !

Et une autre variante : le BP inverse l'état de la LED :

from machine import Pin, Timer
import utime

bp=Pin(17, Pin.IN, Pin.PULL_UP) # initialisation de la broche en entrée avec rappel au PLUS
led=Pin(16, Pin.OUT) # Led en sortie

timer=Timer()

appui=0 # variable état appuyé

def loop(timer):
        timer.deinit()# desactive timer le temps de la fonction
        if bp.value()==appui: # test si appui
                led.toggle()
                utime.sleep_ms(250) # anti rebond
        timer.init(freq=1000, callback=loop) # relance la boucle

timer.init(freq=1000, callback=loop) # 1er lancement

# Si on ne desactive pas le timer dans la fonction, alors l'appel est ré-entrant

Voir également :