3.29. Modos de baixo consumo e de suspensão

Câmeras alimentadas por bateria e sensores ativados de forma intermitente não precisam que a CPU rode em velocidade máxima o tempo todo. O módulo machine expõe quatro estados de economia de energia progressivamente mais profundos – active, idle(), lightsleep() e deepsleep(). Cada passo mais profundo desliga mais partes do chip e economiza mais energia, ao custo de um despertar mais lento. Escolher o estado certo é um compromisso entre quanta energia a câmera economiza e com que rapidez ela consegue reagir quando algo acontece.

3.29.1. Active

O estado padrão. A CPU está executando Python, todos os periféricos estão recebendo clock e o consumo de corrente está no máximo – dezenas de miliamperes no trilho lógico da câmera, mais o que quer que os acessórios conectados consumam através dele.

3.29.2. idle()

machine.idle() interrompe o clock da CPU até que qualquer interrupção dispare (um periférico, um timer, uma IRQ de pino). A RAM permanece ativa, os periféricos continuam ligados, os clocks seguem funcionando – apenas a própria CPU é pausada, e ela desperta em microssegundos quando há trabalho a fazer.

Use-o dentro de qualquer laço de polling apertado que esteja aguardando que algo externo aconteça:

import machine

while not button_pressed():
    machine.idle()

A CPU para de queimar ciclos na própria verificação do while e desperta naturalmente quando o próximo evento chega – uma pequena economia que se acumula ao longo de um laço que roda milhões de vezes.

3.29.3. lightsleep()

machine.lightsleep() é o próximo passo abaixo. A CPU é completamente parada e a maioria dos clocks internos do chip é desligada, mas o estado da RAM e dos periféricos é preservado. Quando a fonte de despertar dispara, o script retoma exatamente de onde chamou lightsleep – variáveis, handles abertos e dados pendentes todos intactos – na ordem de milissegundos depois.

import machine
from machine import Pin

wake_pin = Pin("P0", Pin.IN, Pin.PULL_UP)
wake_pin.irq(lambda _: None, trigger=Pin.IRQ_FALLING, wake=machine.SLEEP)

while True:
    do_work()
    machine.lightsleep()   # wakes on a falling edge on P0

A fonte de despertar – aqui uma IRQ de pino – deve ser configurada antes da chamada de suspensão. O consumo de energia cai significativamente em relação ao modo active; o número exato depende da placa e de quais periféricos ainda estão configurados.

3.29.4. deepsleep()

machine.deepsleep() é o estado mais profundo. A CPU para, os periféricos são desligados e o conteúdo da RAM pode ser perdido. As únicas coisas que ainda consomem energia são o circuito de despertar e um pequeno trecho de lógica sempre ativa.

Quando a fonte de despertar dispara, o chip inicializa a partir do começo do script principaldeepsleep não retorna. O script distingue um despertar de deepsleep de uma ligação inicial ou de um reset físico usando machine.reset_cause():

import machine

if machine.reset_cause() == machine.DEEPSLEEP_RESET:
    # Woke from deepsleep -- restore state from non-volatile storage,
    # take a measurement, etc.
    pass
else:
    # Fresh boot
    pass

do_work()
machine.deepsleep(60_000)    # arm RTC wake for 60 s, sleep, then restart

O argumento em milissegundos de deepsleep() arma internamente o alarme do RTC no chip – o RTC é o que carrega a temporização do despertar durante a suspensão, já que a maioria dos outros timers fica desligada. Chamar deepsleep() sem argumento deixa o despertar a cargo de qualquer fonte que você tenha configurado separadamente (uma IRQ de pino, um alarme de RTC armado externamente).

Como o script reinicia, qualquer coisa de que a próxima iteração precise tem de ser reconstruída no topo de main.py ou persistida na flash (ou nos registradores de backup do RTC, nas peças que os têm). O deepsleep proporciona a maior economia de energia, mas impõe a maior reestruturação do programa – a aplicação tem de se comportar como uma série de curtos “bursts de medição” separados por suspensões, em vez de um laço de longa duração com estado na RAM.

3.29.5. Escolhendo um estado

O estado certo depende daquilo que a câmera está aguardando:

  • Laço de polling apertado, aguardando milissegundos. Use idle(). A economia é pequena por ciclo, mas grande no agregado, e o despertar é invisível.

  • Ocioso por segundos ou minutos entre eventos. Use lightsleep(). O estado é preservado, o despertar é rápido e o consumo de energia é uma fração do modo active.

  • Ocioso por minutos ou mais entre breves rajadas de trabalho. Use deepsleep(). O chip fica efetivamente desligado entre os eventos, e a estrutura do script passa para um laço de despertar, medir e suspender.

Seja qual for o estado, a fonte de despertar importa tanto quanto o próprio estado – um deepsleep que desperta apenas por um timer é um laço de medição com ciclo de trabalho; um lightsleep que desperta por uma IRQ de pino é um sensor orientado a eventos. As funções de suspensão do módulo machine, os alarmes de RTC e irq() juntos fornecem os blocos de construção.