3.10. Ingresso GPIO¶
La lettura di un interruttore (o di qualsiasi segnale digitale) da un pin GPIO passa nuovamente attraverso machine.Pin, questa volta configurato come ingresso. L’interfaccia è simmetrica rispetto all’uscita: configura la modalità, quindi esegui il polling del valore del pin nel ciclo principale oppure registra un gestore di interrupt che si attiva quando il valore cambia.
3.10.1. Configurazione di un ingresso¶
Passa Pin.IN al costruttore e, facoltativamente, un resistore di pull:
from machine import Pin
button = Pin("P0", Pin.IN, Pin.PULL_UP)
Questo configura P0 come ingresso con il resistore di pull-up interno dell’MCU abilitato. Senza nulla collegato al pin, il pull-up lo tiene alto; chiudere un interruttore dal pin alla massa lo porta basso.
3.10.2. Lettura del valore¶
value() senza argomenti restituisce lo stato corrente – 0 per basso, 1 per alto:
if button.value() == 0:
print("button pressed")
else:
print("button released")
Nel pattern del ciclo principale, il polling appare così:
while True:
if button.value() == 0:
do_action()
time.sleep_ms(50)
La pausa di 50 ms impedisce al ciclo di girare a piena CPU.
3.10.3. Ingresso guidato da interrupt¶
Il polling funziona, ma ogni iterazione del ciclo principale costa tempo di CPU. Per gli ingressi che cambiano raramente – la pressione di un pulsante una volta al minuto, un segnale di allarme – irq() registra un gestore che viene eseguito solo quando il pin cambia.
Il gestore viene eseguito nel contesto di interrupt, che vincola ciò che può fare:
Nessuna allocazione di memoria. La creazione di nuovi oggetti – liste, stringhe, eccezioni, stringhe formattate – può fallire all’interno di un ISR perché l’heap è bloccato. Pre-alloca a livello di modulo qualsiasi buffer di cui il gestore ha bisogno.
Nessun lavoro di lunga durata. Il gestore dovrebbe delegare e ritornare. Spendere tempo reale all’interno di un ISR ritarda tutto il resto (altri interrupt, il ciclo principale, il traffico USB).
Nessuna stampa in un ISR serrato.
print()alloca, si blocca sull’UART ed è una delle operazioni più costose che un gestore possa eseguire.
Il pattern standard prevede che l’ISR pianifichi il lavoro reale tramite micropython.schedule(), che accoda una funzione da eseguire nuovamente nel contesto principale al successivo punto sicuro:
import micropython
def handle_press(pin):
print("button pressed")
def on_press(pin):
micropython.schedule(handle_press, pin)
button.irq(handler=on_press, trigger=Pin.IRQ_FALLING)
L’ISR è una sola riga: accoda il callback e ritorna. handle_press viene quindi eseguito nel contesto normale, dove l’allocazione, print() e l’I/O lento sono di nuovo tutti sicuri.
L’argomento trigger seleziona quale fronte attiva:
Pin.IRQ_FALLING– da 1 a 0.Pin.IRQ_RISING– da 0 a 1.Pin.IRQ_FALLING|Pin.IRQ_RISING– entrambi i fronti.