3.29. Modos de bajo consumo y suspensión¶
Las cámaras alimentadas por batería y los sensores activos de forma intermitente no necesitan que la CPU funcione a máxima velocidad todo el tiempo. El módulo machine expone cuatro estados de ahorro de energía progresivamente más profundos: active, idle(), lightsleep() y deepsleep(). Cada paso más profundo apaga una porción mayor del chip y ahorra más energía, a costa de un despertar más lento. Elegir el adecuado es un compromiso entre cuánta energía ahorra la cámara y con qué rapidez puede reaccionar cuando ocurre algo.
3.29.1. Active¶
El estado predeterminado. La CPU está ejecutando Python, todos los periféricos reciben reloj y el consumo de corriente alcanza su máximo: decenas de miliamperios en el riel lógico de la cámara, además de lo que consuman a través de él los accesorios conectados.
3.29.2. idle()¶
machine.idle() detiene el reloj de la CPU hasta que se dispara cualquier interrupción (un periférico, un temporizador, una IRQ de pin). La RAM permanece activa, los periféricos siguen encendidos y los relojes continúan funcionando: solo se pausa la propia CPU, que despierta en microsegundos cuando hay trabajo que hacer.
Úsalo dentro de cualquier bucle de sondeo ajustado que esté esperando a que ocurra algo externo:
import machine
while not button_pressed():
machine.idle()
La CPU deja de consumir ciclos en la propia comprobación del while y despierta de forma natural cuando llega el siguiente evento: un pequeño ahorro que se acumula a lo largo de un bucle que se ejecuta millones de veces.
3.29.3. lightsleep()¶
machine.lightsleep() es el siguiente paso hacia abajo. La CPU se detiene por completo y la mayoría de los relojes internos del chip se apagan, pero el estado de la RAM y de los periféricos se conserva. Cuando la fuente de despertar se dispara, el script se reanuda exactamente desde donde llamó a lightsleep (con las variables, los descriptores abiertos y los datos pendientes intactos) unos milisegundos después.
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
La fuente de despertar (aquí una IRQ de pin) debe configurarse antes de la llamada de suspensión. El consumo de corriente se reduce significativamente respecto al modo activo; el valor exacto depende de la placa y de qué periféricos sigan configurados.
3.29.4. deepsleep()¶
machine.deepsleep() es el estado más profundo. La CPU se detiene, los periféricos se apagan y el contenido de la RAM puede perderse. Lo único que sigue consumiendo energía es el circuito de despertar y una pequeña parte de lógica siempre activa.
Cuando la fuente de despertar se dispara, el chip arranca desde el inicio del script principal: deepsleep no retorna. El script distingue un despertar desde deepsleep de un encendido nuevo o un reinicio forzado 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
El argumento en milisegundos de deepsleep() activa internamente la alarma del RTC integrado en el chip: el RTC es lo que mantiene la temporización del despertar durante la suspensión, ya que la mayoría de los demás temporizadores se apagan. Llamar a deepsleep() sin argumento deja el despertar a cargo de la fuente que hayas configurado por separado (una IRQ de pin, una alarma de RTC activada externamente).
Como el script se reinicia, todo lo que necesite la siguiente iteración debe reconstruirse al principio de main.py o persistirse en la memoria flash (o en los registros de respaldo del RTC, en las piezas que los tienen). Deepsleep ofrece el mayor ahorro de energía, pero impone la mayor reestructuración del programa: la aplicación tiene que comportarse como una serie de breves «ráfagas de medición» separadas por suspensiones, en lugar de como un bucle de larga duración con estado en RAM.
3.29.5. Elegir un estado¶
El estado adecuado depende de qué esté esperando la cámara:
Bucle de sondeo ajustado, esperando milisegundos. Usa
idle(). El ahorro es pequeño por ciclo pero grande en conjunto, y el despertar es imperceptible.Inactiva durante segundos o minutos entre eventos. Usa
lightsleep(). El estado se conserva, el despertar es rápido y el consumo de corriente es una fracción del modo activo.Inactiva durante minutos o más entre breves ráfagas de trabajo. Usa
deepsleep(). El chip está prácticamente apagado entre eventos, y la estructura del script pasa a un bucle de despertar, medir y suspender.
Sea cual sea el estado, la fuente de despertar importa tanto como el estado en sí: un deepsleep que despierta solo con un temporizador es un bucle de medición con ciclo de trabajo; un lightsleep que despierta con una IRQ de pin es un sensor controlado por eventos. Las funciones de suspensión del módulo machine, las alarmas de RTC y irq() proporcionan en conjunto los componentes básicos.