🎯 Programação não bloqueante

Em poucas palavras

Técnica de firmware em que o laço principal nunca espera parado: a cada volta verifica, pelo relógio do sistema, se é hora de executar cada tarefa, permitindo atender sensores, rede e interface ao mesmo tempo.


📝 Notas e Desenvolvimento

O problema do delay()

delay(2000) (ou time.sleep(2)) congela o processador: durante a espera o microcontrolador não lê botões, não responde à rede e não atende outras tarefas.

A solução: verificar em vez de esperar

Guarda-se o instante da última execução e, a cada volta do laço, compara-se com o relógio (millis() em C; time.ticks_ms() em MicroPython):

if (millis() - ultima >= INTERVALO) { ultima = millis(); tarefa(); }

Escalonador cooperativo

Generalização com uma tabela de tarefas [período, última execução, função], percorrida a cada volta. Cada tarefa deve set curta e nunca bloquear — daí “cooperativo”: o escalonamento depende de todas cooperarem.

for tarefa in tarefas:
    periodo, ultima, acao = tarefa
    if time.ticks_diff(agora, ultima) >= periodo:
        tarefa[1] = agora
        acao()

O “vira” do contador

Contadores de milissegundos são finitos e voltam a zero (Arduino: ~49 dias; MicroPython na ESP32: ~12 dias). A comparação deve usar aritmética sem sinal (C) ou time.ticks_diff() (MicroPython); a subtração ingênua gera um bug que só aparece após dias de operação.

Além do escalonador cooperativo

  • Interrupções: respondem a eventos de hardware imediatamente.
  • RTOS (a ESP32 roda FreeRTOS): tarefas preemptivas em núcleos distintos.
  • asyncio em MicroPython: corrotinas com await.

Teste prático: um LED de sinal de vida piscando em ritmo fixo revela visualmente qualquer bloqueio.


🔗 Notas Relacionadas