3.29. Modalità a basso consumo e di sospensione¶
Le camere alimentate a batteria e i sensori attivi a intermittenza non hanno bisogno che la CPU giri sempre alla massima velocità. Il modulo machine espone quattro stati di risparmio energetico progressivamente più profondi – active, idle(), lightsleep() e deepsleep(). Ogni passo più profondo spegne una parte maggiore del chip e risparmia più energia, al costo di un risveglio più lungo. Scegliere quello giusto è un compromesso tra quanta energia la camera risparmia e quanto velocemente può reagire quando succede qualcosa.
3.29.1. Active¶
Lo stato predefinito. La CPU esegue Python, ogni periferica riceve il clock e l’assorbimento di corrente è al massimo – decine di milliampere sul rail logico della camera, più ciò che gli eventuali accessori collegati assorbono attraverso di esso.
3.29.2. idle()¶
machine.idle() blocca il clock della CPU finché qualsiasi interrupt non scatta (una periferica, un timer, un IRQ su un pin). La RAM è attiva, le periferiche restano accese, i clock continuano a girare – solo la CPU stessa viene messa in pausa e si risveglia in pochi microsecondi quando c’è lavoro da fare.
Usalo all’interno di qualsiasi ciclo di polling stretto che attende che qualcosa di esterno accada:
import machine
while not button_pressed():
machine.idle()
La CPU smette di consumare cicli sul controllo while stesso e si risveglia naturalmente quando arriva l’evento successivo – un piccolo risparmio che si accumula su un ciclo eseguito milioni di volte.
3.29.3. lightsleep()¶
machine.lightsleep() è il passo successivo verso il basso. La CPU viene fermata completamente e la maggior parte dei clock interni del chip viene disattivata, ma lo stato della RAM e delle periferiche viene preservato. Quando la sorgente di risveglio scatta, lo script riprende esattamente dal punto in cui aveva chiamato lightsleep – variabili, handle aperti e dati in sospeso tutti intatti – nell’ordine di millisecondi più tardi.
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 sorgente di risveglio – qui un IRQ su un pin – deve essere configurata prima della chiamata di sospensione. L’assorbimento di potenza cala notevolmente rispetto alla modalità active; il valore esatto dipende dalla scheda e da quali periferiche sono ancora configurate.
3.29.4. deepsleep()¶
machine.deepsleep() è lo stato più profondo. La CPU si ferma, le periferiche vengono spente e il contenuto della RAM può andare perso. Le uniche cose che assorbono ancora energia sono il circuito di risveglio e una piccola parte di logica sempre attiva.
Quando la sorgente di risveglio scatta, il chip si avvia dall’inizio dello script principale – deepsleep non ritorna. Lo script distingue un risveglio da deepsleep da un’accensione a freddo o da un hard reset 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
L’argomento in millisecondi di deepsleep() arma internamente l’allarme RTC integrato nel chip – è l’RTC a portare avanti la temporizzazione del risveglio attraverso la sospensione, dato che la maggior parte degli altri timer viene spenta. Chiamare deepsleep() senza argomenti lascia il risveglio a qualunque sorgente tu abbia configurato separatamente (un IRQ su un pin, un allarme RTC armato esternamente).
Poiché lo script riparte, tutto ciò di cui ha bisogno l’iterazione successiva deve essere ricostruito all’inizio di main.py oppure reso persistente nella flash (o nei registri di backup dell’RTC, sui componenti che li hanno). Il deepsleep offre il massimo risparmio energetico ma impone la maggiore ristrutturazione del programma – l’applicazione deve comportarsi come una serie di brevi «raffiche di misurazione» separate da sospensioni, anziché come un ciclo a lunga durata con lo stato in RAM.
3.29.5. Scegliere uno stato¶
Lo stato giusto dipende da cosa la camera sta aspettando:
Ciclo di polling stretto, in attesa di millisecondi. Usa
idle(). Il risparmio è piccolo per ciclo ma grande nel complesso, e il risveglio è invisibile.Inattivo per secondi o minuti tra un evento e l’altro. Usa
lightsleep(). Lo stato viene preservato, il risveglio è rapido e l’assorbimento di potenza è una frazione di quello della modalità active.Inattivo per minuti o più tra brevi raffiche di lavoro. Usa
deepsleep(). Il chip è di fatto spento tra un evento e l’altro, e la struttura dello script passa a un ciclo di risveglio, misurazione e sospensione.
Qualunque sia lo stato, la sorgente di risveglio conta tanto quanto lo stato stesso – un deepsleep che si risveglia solo su un timer è un ciclo di misurazione a ciclo di lavoro fisso; un lightsleep che si risveglia su un IRQ di un pin è un sensore guidato dagli eventi. Le funzioni di sospensione del modulo machine, gli allarmi RTC e irq() forniscono insieme i mattoni di base.