3.10. Entrada GPIO

La lectura de un interruptor (o de cualquier señal digital) desde un pin GPIO se realiza de nuevo a través de machine.Pin, esta vez configurado como entrada. La interfaz es simétrica con la de salida: configura el modo y luego sondea el valor del pin en el bucle principal o registra un manejador de interrupciones que se dispara cuando el valor cambia.

3.10.1. Configurar una entrada

Pasa Pin.IN al constructor y, opcionalmente, una resistencia de polarización:

from machine import Pin

button = Pin("P0", Pin.IN, Pin.PULL_UP)

Eso configura P0 como entrada con la resistencia pull-up interna del MCU habilitada. Sin nada conectado al pin, el pull-up lo mantiene en alto; cerrar un interruptor desde el pin a tierra lo lleva a bajo.

3.10.2. Leer el valor

value() sin argumentos devuelve el estado actual – 0 para bajo, 1 para alto:

if button.value() == 0:
    print("button pressed")
else:
    print("button released")

En el patrón de bucle principal, el sondeo tiene este aspecto:

while True:
    if button.value() == 0:
        do_action()
    time.sleep_ms(50)

La espera de 50 ms evita que el bucle se ejecute a plena CPU.

3.10.3. Entrada controlada por interrupciones

El sondeo funciona, pero cada iteración del bucle principal consume tiempo de CPU. Para entradas que cambian raramente – la pulsación de un botón una vez por minuto, una señal de alarma – irq() registra un manejador que se ejecuta solo cuando el pin cambia.

El manejador se ejecuta en contexto de interrupción, lo que restringe lo que puede hacer:

  • Sin asignación de memoria. La creación de objetos nuevos – listas, cadenas, excepciones, cadenas formateadas – puede fallar dentro de una ISR porque el montículo (heap) está bloqueado. Reserva con antelación, en el ámbito del módulo, cualquier búfer que necesite el manejador.

  • Sin trabajo de larga duración. El manejador debe delegar y volver. Pasar tiempo real dentro de una ISR retrasa todo lo demás (otras interrupciones, el bucle principal, el tráfico USB).

  • Sin imprimir dentro de una ISR ajustada. print() asigna memoria, se bloquea en la UART y es una de las operaciones más costosas que puede realizar un manejador.

El patrón estándar es que la ISR programe el trabajo real mediante micropython.schedule(), que encola una función para ejecutarse de nuevo en el contexto principal en el siguiente punto seguro:

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)

La ISR ocupa una sola línea: encolar la función de retorno (callback) y volver. handle_press se ejecuta entonces en contexto normal, donde la asignación de memoria, print() y la E/S lenta vuelven a ser seguras.

El argumento trigger selecciona qué borde dispara: