3.29. Moduri de consum redus și de repaus

Camerele alimentate cu baterie și senzorii activați intermitent nu au nevoie ca CPU-ul să ruleze la viteză maximă tot timpul. Modulul machine expune patru stări de economisire a energiei tot mai profunde – active, idle(), lightsleep() și deepsleep(). Fiecare pas mai profund oprește mai multe părți din cip și economisește mai multă energie, cu prețul unei treziri mai lente. Alegerea celei potrivite este un compromis între cât de multă energie economisește camera și cât de repede poate reacționa atunci când se întâmplă ceva.

3.29.1. Active

Starea implicită. CPU-ul rulează Python, fiecare periferic este sincronizat, iar consumul de curent este la maxim – zeci de miliamperi pe șina de logică a camerei, plus orice consumă accesoriile atașate prin aceasta.

3.29.2. idle()

machine.idle() blochează ceasul CPU-ului până când se declanșează orice întrerupere (un periferic, un temporizator, un IRQ de pin). RAM-ul este activ, perifericele rămân pornite, ceasurile continuă să ruleze – doar CPU-ul în sine este pus în pauză și se trezește în microsecunde când există lucru de făcut.

Folosește-l în orice buclă strânsă de interogare care așteaptă ca ceva extern să se întâmple:

import machine

while not button_pressed():
    machine.idle()

CPU-ul nu mai consumă cicluri pe verificarea while în sine și se trezește natural când sosește următorul eveniment – o mică economie care se adună de-a lungul unei bucle ce rulează de milioane de ori.

3.29.3. lightsleep()

machine.lightsleep() este pasul următor mai jos. CPU-ul este oprit complet și majoritatea ceasurilor interne ale cipului sunt dezactivate, dar RAM-ul și starea perifericelor sunt păstrate. Când se declanșează sursa de trezire, scriptul reia exact din locul unde a apelat lightsleep – variabile, descriptori deschiși și date în așteptare, toate intacte – la o distanță de ordinul milisecundelor.

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

Sursa de trezire – aici un IRQ de pin – trebuie configurată înainte de apelul de repaus. Consumul de curent scade semnificativ față de modul activ; valoarea exactă depinde de placă și de ce periferice rămân configurate.

3.29.4. deepsleep()

machine.deepsleep() este starea cea mai profundă. CPU-ul se oprește, perifericele sunt scoase de sub tensiune, iar conținutul RAM-ului poate fi pierdut. Singurele lucruri care mai consumă energie sunt circuitul de trezire și o mică parte de logică mereu pornită.

Când se declanșează sursa de trezire, cipul pornește de la începutul scriptului principaldeepsleep nu returnează. Scriptul distinge o trezire din deepsleep de o pornire proaspătă sau de un reset hardware folosind 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

Argumentul în milisecunde dat lui deepsleep() armează intern alarma RTC de pe cip – RTC-ul este cel care duce sincronizarea trezirii pe durata repausului, deoarece majoritatea celorlalte temporizatoare sunt scoase de sub tensiune. Apelarea lui deepsleep() fără argument lasă trezirea în seama oricărei surse pe care ai configurat-o separat (un IRQ de pin, o alarmă RTC armată extern).

Deoarece scriptul repornește, tot ceea ce are nevoie următoarea iterație trebuie fie reconstruit la începutul fișierului main.py, fie persistat în memoria flash (sau în registrele de backup ale RTC-ului, pe componentele care le au). Deepsleep oferă cea mai mare economie de energie, dar impune cea mai multă restructurare a programului – aplicația trebuie să se comporte ca o serie de scurte „rafale de măsurare” separate de repausuri, mai degrabă decât o buclă de lungă durată cu stare în RAM.

3.29.5. Alegerea unei stări

Starea potrivită depinde de ceea ce așteaptă camera:

  • Buclă strânsă de interogare, care așteaptă milisecunde. Folosește idle(). Economiile sunt mici per ciclu, dar mari în ansamblu, iar trezirea este invizibilă.

  • Inactivă timp de secunde sau minute între evenimente. Folosește lightsleep(). Starea este păstrată, trezirea este rapidă, iar consumul de curent este o fracțiune din modul activ.

  • Inactivă timp de minute sau mai mult între scurte rafale de lucru. Folosește deepsleep(). Cipul este practic oprit între evenimente, iar structura scriptului se mută la o buclă de trezire, măsurare, repaus.

Oricare ar fi starea, sursa de trezire contează la fel de mult ca starea în sine – un deepsleep care se trezește doar pe un temporizator este o buclă de măsurare cu ciclu de funcționare; un lightsleep care se trezește pe un IRQ de pin este un senzor bazat pe evenimente. Funcțiile de repaus ale modulului machine, alarmele RTC și irq() oferă împreună blocurile de construcție.