3.29. Energiebesparende en slaapmodi

Camera’s op batterijvoeding en sensoren die slechts af en toe actief zijn, hoeven de CPU niet voortdurend op volle snelheid te laten draaien. De machine-module biedt vier steeds diepere energiebesparende toestanden – active, idle(), lightsleep() en deepsleep(). Elke diepere stap schakelt meer van de chip uit en bespaart meer energie, ten koste van een langere ontwaaktijd. De juiste kiezen is een afweging tussen hoeveel energie de camera bespaart en hoe snel hij kan reageren wanneer er iets gebeurt.

3.29.1. Active

De standaardtoestand. De CPU draait Python, elk randapparaat wordt geklokt en de stroomopname is op zijn hoogst – tientallen milliampère op de logica-rail van de camera, plus alles wat aangesloten accessoires daardoorheen trekken.

3.29.2. idle()

machine.idle() blokkeert de CPU-klok totdat een willekeurige interrupt afgaat (een randapparaat, een timer, een pin-IRQ). Het RAM blijft actief, randapparaten blijven aan, de klokken blijven draaien – alleen de CPU zelf wordt gepauzeerd, en die ontwaakt binnen microseconden wanneer er werk te doen is.

Gebruik het binnen elke strakke polling-lus die wacht tot er iets externs gebeurt:

import machine

while not button_pressed():
    machine.idle()

De CPU stopt met het verbranden van cycli aan de while-controle zelf en ontwaakt op natuurlijke wijze wanneer de volgende gebeurtenis aankomt – een kleine besparing die optelt over een lus die miljoenen keren draait.

3.29.3. lightsleep()

machine.lightsleep() is de volgende stap omlaag. De CPU wordt volledig gestopt en de meeste interne klokken van de chip worden uitgeschakeld, maar het RAM en de toestand van randapparaten blijven behouden. Wanneer de ontwaakbron afgaat, hervat het script precies vanaf waar het lightsleep aanriep – variabelen, open handles en in behandeling zijnde gegevens blijven allemaal intact – in de orde van milliseconden later.

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

De ontwaakbron – hier een pin-IRQ – moet vóór de slaapaanroep worden geconfigureerd. De stroomopname daalt aanzienlijk ten opzichte van de active-modus; het exacte getal hangt af van het bord en welke randapparaten nog geconfigureerd zijn.

3.29.4. deepsleep()

machine.deepsleep() is de diepste toestand. De CPU stopt, randapparaten worden uitgeschakeld en de inhoud van het RAM kan verloren gaan. De enige dingen die nog energie trekken zijn het ontwaakcircuit en een klein stukje altijd-aan logica.

Wanneer de ontwaakbron afgaat, start de chip op vanaf het begin van het hoofdscriptdeepsleep keert niet terug. Het script onderscheidt een deepsleep-ontwaking van een verse inschakeling of harde reset met behulp van 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

Het milliseconde-argument voor deepsleep() activeert intern het RTC-alarm op de chip – de RTC is wat de ontwaaktiming door de slaap heen draagt, aangezien de meeste andere timers uitgeschakeld zijn. Het aanroepen van deepsleep() zonder argument laat het ontwaken over aan welke bron je ook afzonderlijk hebt geconfigureerd (een pin-IRQ, een extern geactiveerd RTC-alarm).

Omdat het script opnieuw start, moet alles wat de volgende iteratie nodig heeft ofwel bovenaan main.py worden gereconstrueerd ofwel naar het flashgeheugen worden weggeschreven (of naar de backup-registers van de RTC, op onderdelen die die hebben). Deepsleep levert de grootste energiebesparing op, maar vereist de meeste programmaherstructurering – de applicatie moet zich gedragen als een reeks korte “meetbursts” gescheiden door slaapperiodes, in plaats van een langlopende lus met toestand in het RAM.

3.29.5. Een toestand kiezen

De juiste toestand hangt af van waar de camera op wacht:

  • Strakke polling-lus, wachtend op milliseconden. Gebruik idle(). De besparingen zijn klein per cyclus maar groot in totaal, en het ontwaken is onzichtbaar.

  • Inactief gedurende seconden of minuten tussen gebeurtenissen. Gebruik lightsleep(). De toestand blijft behouden, het ontwaken is snel en de stroomopname is een fractie van de active-modus.

  • Inactief gedurende minuten of langer tussen korte werkbursts. Gebruik deepsleep(). De chip is tussen gebeurtenissen effectief uitgeschakeld en de scriptstructuur verschuift naar een lus van ontwaken, meten, slapen.

Wat de toestand ook is, de ontwaakbron is net zo belangrijk als de toestand zelf – een deepsleep die alleen op een timer ontwaakt is een meetlus met arbeidscyclus; een lightsleep die op een pin-IRQ ontwaakt is een gebeurtenisgestuurde sensor. De slaapfuncties van de machine-module, RTC-alarmen en irq() vormen samen de bouwstenen.