3.10. Entrada GPIO

Ler um interruptor (ou qualquer sinal digital) a partir de um pino GPIO passa novamente por machine.Pin, desta vez configurado como entrada. A interface é simétrica com a saída: configure o modo, depois faça polling do valor do pino no ciclo principal ou registe um handler de interrupção que dispare quando o valor mudar.

3.10.1. Configurar uma entrada

Passe Pin.IN ao construtor e, opcionalmente, uma resistência de pull:

from machine import Pin

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

Isso configura P0 como entrada com a resistência de pull-up interna do MCU ativada. Sem nada ligado ao pino, o pull-up mantém-no alto; fechar um interruptor do pino para a massa puxa-o para baixo.

3.10.2. Ler o valor

value() sem argumentos devolve o estado atual – 0 para baixo, 1 para alto:

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

No padrão de ciclo principal, o polling é feito assim:

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

O sleep de 50 ms impede que o ciclo corra à velocidade máxima da CPU.

3.10.3. Entrada por interrupção

O polling funciona, mas cada iteração do ciclo principal consome tempo de CPU. Para entradas que mudam raramente – a pressão de um botão uma vez por minuto, um sinal de alarme – irq() regista um handler que corre apenas quando o pino muda.

O handler corre em contexto de interrupção, o que limita o que pode fazer:

  • Sem alocação de memória. Criar novos objetos – listas, strings, exceções, strings formatadas – pode falhar dentro de uma ISR porque o heap está bloqueado. Pré-aloque todos os buffers de que o handler necessita no âmbito do módulo.

  • Sem trabalho demorado. O handler deve delegar e retornar. Gastar tempo real dentro de uma ISR atrasa tudo o resto (outras interrupções, o ciclo principal, tráfego USB).

  • Sem impressão numa ISR apertada. print() aloca, bloqueia no UART e é uma das operações mais dispendiosas que um handler pode fazer.

O padrão standard é a ISR agendar o trabalho real através de micropython.schedule(), que coloca uma função na fila para ser executada de volta no contexto principal no próximo ponto 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)

A ISR tem uma linha: coloca o callback na fila e retorna. handle_press executa depois em contexto normal, onde a alocação, print() e E/S lenta são novamente seguras.

O argumento trigger seleciona qual a transição que dispara: