3.29. Pienitehoiset tilat ja lepotilat

Akkukäyttöisten kameroiden ja ajoittain aktiivisten sensoreiden ei tarvitse pitää suoritinta täydellä nopeudella koko ajan. machine-moduuli tarjoaa neljä asteittain syvenevää virransäästötilaa – active, idle(), lightsleep() ja deepsleep(). Jokainen syvempi askel sammuttaa enemmän sirua ja säästää enemmän virtaa pidemmän herätysajan kustannuksella. Oikean valitseminen on kompromissi sen välillä, kuinka paljon kamera säästää virtaa ja kuinka nopeasti se voi reagoida, kun jotain tapahtuu.

3.29.1. Active

Oletustila. Suoritin ajaa Pythonia, jokaista oheislaitetta kellotetaan ja virrankulutus on suurimmillaan – kymmeniä milliampeereja kameran logiikkakiskolla, sekä kaikki kytkettyjen lisälaitteiden sen kautta vetämä virta.

3.29.2. idle()

machine.idle() portittaa suorittimen kellon, kunnes mikä tahansa keskeytys laukeaa (oheislaite, ajastin, nastan IRQ). RAM on aktiivinen, oheislaitteet pysyvät päällä ja kellot käyvät – vain itse suoritin on pysäytetty, ja se herää mikrosekunneissa, kun on töitä tehtävänä.

Käytä sitä missä tahansa tiukassa kyselysilmukassa, joka odottaa jonkin ulkoisen tapahtuman tapahtumista:

import machine

while not button_pressed():
    machine.idle()

Suoritin lakkaa kuluttamasta sykliä itse while-tarkistukseen ja herää luonnollisesti, kun seuraava tapahtuma saapuu – pieni säästö, joka kertyy silmukan aikana, joka suoritetaan miljoonia kertoja.

3.29.3. lightsleep()

machine.lightsleep() on seuraava askel alaspäin. Suoritin pysäytetään kokonaan ja useimmat sirun sisäiset kellot kytketään pois päältä, mutta RAM ja oheislaitteiden tila säilytetään. Kun herätyslähde laukeaa, skripti jatkuu täsmälleen siitä kohdasta, jossa se kutsui lightsleep-funktiota – muuttujat, avoimet kahvat ja keskeneräiset tiedot ovat kaikki ehjinä – millisekuntien luokkaa myöhemmin.

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

Herätyslähde – tässä nastan IRQ – on määritettävä ennen lepokutsua. Virrankulutus laskee merkittävästi aktiiviseen tilaan verrattuna; tarkka luku riippuu kortista ja siitä, mitkä oheislaitteet ovat yhä määritettyinä.

3.29.4. deepsleep()

machine.deepsleep() on syvin tila. Suoritin pysähtyy, oheislaitteet sammutetaan ja RAM-sisältö saattaa kadota. Ainoat asiat, jotka vielä vetävät virtaa, ovat herätyspiiri ja pieni osa aina päällä olevaa logiikkaa.

Kun herätyslähde laukeaa, siru käynnistyy pääskriptin alustadeepsleep ei palaa. Skripti erottaa deepsleep-heräyksen tuoreesta virrankytkennästä tai laitteistonollauksesta käyttämällä machine.reset_cause()-funktiota:

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

deepsleep()-funktion millisekuntiargumentti virittää sirun sisäisen RTC-hälytyksen sisäisesti – RTC on se, joka kuljettaa herätysajoituksen läpi lepotilan, koska useimmat muut ajastimet on sammutettu. deepsleep()-funktion kutsuminen ilman argumenttia jättää heräyksen erikseen määrittämääsi lähteeseen (nastan IRQ, ulkoisesti viritetty RTC-hälytys).

Koska skripti käynnistyy uudelleen, kaikki seuraavan iteraation tarvitsema on joko rakennettava uudelleen main.py-tiedoston alussa tai säilytettävä flash-muistissa (tai RTC:n varmistusrekistereissä niillä osilla, joilla niitä on). Deepsleep antaa suurimman virransäästön mutta vaatii eniten ohjelman uudelleenjärjestelyä – sovelluksen on käyttäydyttävä sarjana lyhyitä ”mittauspurskeita”, joita erottavat lepotilat, eikä pitkään käyvänä silmukkana, jonka tila on RAM-muistissa.

3.29.5. Tilan valitseminen

Oikea tila riippuu siitä, mitä kamera odottaa:

  • Tiukka kyselysilmukka, joka odottaa millisekunteja. Käytä idle()-funktiota. Säästöt ovat pieniä syklikohtaisesti mutta suuria yhteensä, ja herätys on näkymätön.

  • Joutilaana sekuntien tai minuuttien ajan tapahtumien välillä. Käytä lightsleep()-funktiota. Tila säilytetään, herätys on nopea ja virrankulutus on murto-osa aktiivisesta tilasta.

  • Joutilaana minuutteja tai pidempään lyhyiden työpurskeiden välillä. Käytä deepsleep()-funktiota. Siru on käytännössä pois päältä tapahtumien välillä, ja skriptin rakenne siirtyy herää, mittaa, lepää -silmukaksi.

Mikä tila tahansa, herätyslähde on yhtä tärkeä kuin tila itse – deepsleep, joka herää vain ajastimesta, on käyttösuhteistettu mittaussilmukka; lightsleep, joka herää nastan IRQ:sta, on tapahtumavetoinen sensori. machine-moduulin lepofunktiot, RTC-hälytykset ja irq() antavat yhdessä rakennuspalikat.