3.10. Entrada GPIO

Ler uma chave (ou qualquer sinal digital) de um pino GPIO passa novamente por machine.Pin, desta vez configurado como entrada. A interface é simétrica à da saída: configure o modo e então faça polling do valor do pino no laço principal ou registre um manipulador de interrupção que dispara quando o valor muda.

3.10.1. Configurando uma entrada

Passe Pin.IN ao construtor e, opcionalmente, um resistor de pull:

from machine import Pin

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

Isso configura P0 como entrada com o resistor de pull-up interno do MCU habilitado. Sem nada conectado ao pino, o pull-up o mantém em nível alto; fechar uma chave do pino para o terra o puxa para nível baixo.

3.10.2. Lendo o valor

value() sem argumentos retorna o estado atual – 0 para nível baixo, 1 para nível alto:

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

No padrão de laço principal, o polling fica assim:

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

O sleep de 50 ms evita que o laço seja executado com a CPU em capacidade total.

3.10.3. Entrada orientada a interrupção

O polling funciona, mas cada iteração do laço principal custa tempo de CPU. Para entradas que mudam raramente – um toque de botão uma vez por minuto, um sinal de alarme – irq() registra um manipulador que é executado somente quando o pino muda.

O manipulador é executado em contexto de interrupção, o que restringe o que ele 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 quaisquer buffers de que o manipulador precise no escopo de módulo.

  • Sem trabalho de longa duração. O manipulador deve repassar e retornar. Gastar tempo real dentro de uma ISR atrasa tudo o mais (outras interrupções, o laço principal, o tráfego USB).

  • Sem impressão em uma ISR curta. print() aloca, bloqueia na UART e é uma das coisas mais caras que um manipulador pode fazer.

O padrão recomendado é a ISR agendar o trabalho real via micropython.schedule(), que enfileira uma função 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: enfileirar o callback e retornar. handle_press então é executado em contexto normal, onde alocação, print() e I/O lenta são todos seguros novamente.

O argumento trigger seleciona qual borda dispara: