3.29. Stromsparende Modi und Schlafmodi

Batteriebetriebene Kameras und nur zeitweise aktive Sensoren müssen die CPU nicht ständig mit voller Geschwindigkeit laufen lassen. Das machine-Modul stellt vier schrittweise tiefere Energiesparzustände bereit – active, idle(), lightsleep() und deepsleep(). Jeder tiefere Schritt schaltet mehr vom Chip ab und spart mehr Strom, auf Kosten einer längeren Aufwachzeit. Die richtige Wahl ist ein Kompromiss zwischen der Menge an Strom, die die Kamera spart, und der Geschwindigkeit, mit der sie reagieren kann, wenn etwas passiert.

3.29.1. Active

Der Standardzustand. Die CPU führt Python aus, jedes Peripheriegerät wird getaktet und die Stromaufnahme ist am höchsten – mehrere zehn Milliampere auf der Logikversorgung der Kamera, zuzüglich dessen, was angeschlossenes Zubehör darüber zieht.

3.29.2. idle()

machine.idle() blockiert den CPU-Takt, bis irgendein Interrupt ausgelöst wird (ein Peripheriegerät, ein Timer, ein Pin-IRQ). Der RAM bleibt aktiv, Peripheriegeräte bleiben eingeschaltet, die Takte laufen weiter – nur die CPU selbst wird angehalten und wacht innerhalb von Mikrosekunden auf, wenn es etwas zu tun gibt.

Verwenden Sie es in jeder engen Polling-Schleife, die darauf wartet, dass etwas Externes passiert:

import machine

while not button_pressed():
    machine.idle()

Die CPU verschwendet keine Zyklen mehr mit der while-Prüfung selbst und wacht natürlich auf, wenn das nächste Ereignis eintrifft – eine kleine Ersparnis, die sich über eine millionenfach durchlaufene Schleife summiert.

3.29.3. lightsleep()

machine.lightsleep() ist der nächste Schritt nach unten. Die CPU wird vollständig gestoppt und die meisten internen Takte des Chips werden abgeschaltet, aber der RAM- und Peripheriezustand bleibt erhalten. Wenn die Aufwachquelle auslöst, wird das Skript genau dort fortgesetzt, wo es lightsleep aufgerufen hat – Variablen, offene Handles und ausstehende Daten alle intakt – in der Größenordnung von Millisekunden später.

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

Die Aufwachquelle – hier ein Pin-IRQ – muss vor dem Schlafaufruf konfiguriert werden. Die Stromaufnahme sinkt im Vergleich zum aktiven Modus erheblich; der genaue Wert hängt vom Board ab und davon, welche Peripheriegeräte noch konfiguriert sind.

3.29.4. deepsleep()

machine.deepsleep() ist der tiefste Zustand. Die CPU stoppt, die Peripheriegeräte werden abgeschaltet und der RAM-Inhalt kann verloren gehen. Die einzigen Dinge, die noch Strom ziehen, sind die Aufwachschaltung und ein kleiner Teil dauerhaft aktiver Logik.

Wenn die Aufwachquelle auslöst, bootet der Chip vom Anfang des Hauptskriptsdeepsleep kehrt nicht zurück. Das Skript unterscheidet ein Aufwachen aus dem Deepsleep von einem frischen Einschalten oder einem Hard-Reset mithilfe von 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

Das Millisekunden-Argument von deepsleep() aktiviert intern den On-Chip-RTC-Alarm – die RTC ist es, die das Aufwach-Timing durch den Schlaf hindurch trägt, da die meisten anderen Timer abgeschaltet sind. Ein Aufruf von deepsleep() ohne Argument überlässt das Aufwachen der von Ihnen separat konfigurierten Quelle (einem Pin-IRQ, einem extern aktivierten RTC-Alarm).

Da das Skript neu startet, muss alles, was die nächste Iteration benötigt, entweder am Anfang von main.py neu aufgebaut oder im Flash persistiert werden (oder in den Backup-Registern der RTC, bei Bauteilen, die diese besitzen). Deepsleep bringt die größte Stromersparnis, erzwingt aber die meiste Programmumstrukturierung – die Anwendung muss sich wie eine Reihe kurzer „Messstöße“ verhalten, die durch Schlafphasen getrennt sind, statt wie eine langlaufende Schleife mit Zustand im RAM.

3.29.5. Auswahl eines Zustands

Der richtige Zustand hängt davon ab, worauf die Kamera wartet:

  • Enge Polling-Schleife, die Millisekunden wartet. Verwenden Sie idle(). Die Ersparnis ist pro Zyklus gering, in der Summe aber groß, und das Aufwachen ist unsichtbar.

  • Sekunden oder Minuten zwischen Ereignissen untätig. Verwenden Sie lightsleep(). Der Zustand bleibt erhalten, das Aufwachen ist schnell und die Stromaufnahme beträgt einen Bruchteil des aktiven Modus.

  • Minuten oder länger zwischen kurzen Arbeitsstößen untätig. Verwenden Sie deepsleep(). Der Chip ist zwischen Ereignissen praktisch ausgeschaltet, und die Skriptstruktur verschiebt sich zu einer Aufwachen-Messen-Schlafen-Schleife.

Welcher Zustand auch immer gewählt wird, die Aufwachquelle ist ebenso wichtig wie der Zustand selbst – ein Deepsleep, der nur per Timer aufwacht, ist eine taktgesteuerte Messschleife; ein Lightsleep, der bei einem Pin-IRQ aufwacht, ist ein ereignisgesteuerter Sensor. Die Schlaffunktionen des machine-Moduls, RTC-Alarme und irq() liefern gemeinsam die Bausteine.