Lab #7: Správa napájania a nízka spotreba

o tom, ako sa dá znížiť spotreba zariadenia pomocou softvérových a hardvérových prerušení, znížení pracovnej frekvencie, o režimoch spánku a spôsoboch prebudenia sa z neho

Motivácia

Jednou z hlavných výziev, ktorú priniesol Internet vecí, je dosiahnuť čo najnižšiu spotrebu energie zariadení. Efektívnym riadením spotreby dokážeme predĺžiť životnosť batériovo napájaných systémov z týždňov na mesiace či dokonca roky. V tomto cvičení si ukážeme niekoľko praktických spôsobov, ako znížiť spotrebu nášho chytrého senzora – znížením pracovnej frekvencie, využitím režimov spánku a prebúdzaním pomocou externého časovača alebo stlačením tlačidla.

Ciele

  1. naučiť sa uspať zariadenie

  2. naučiť sa zobudiť zariadenie pomocou externého prerušenia z tlačítka

  3. naučiť sa softvérovo meniť frekvenciu zariadenia

  4. porozumieť významu časovača Watchdog

  5. časovač cez externý RTC modul

Postup

USB multimeter

Na meranie budeme v tomto cvičení používať USB multimeter (označovaný aj ako USB tester), napr. UM24. Zapája sa medzi zdroj napájania a merané zariadenie a meria všetko, čo cez jeho USB konektor prechádza.

Obr. 1: USB multimeter UM24

USB multimeter zvyčajne zobrazuje tieto hodnoty:

  • napätie (V) a prúd (A), ktorý zariadenie odoberá,
  • výkon (W), ktorý je ich súčinom,
  • náboj (mAh) a energiu (mWh), ktoré zariadenie od začiatku merania spotrebovalo, a
  • čas, ako dlho meranie trvá.

Okamžité hodnoty prúdu a výkonu nám povedia, koľko zariadenie odoberá práve teraz. Kumulované hodnoty náboja a energie zase to, koľko spotrebovalo za celý čas merania. Práve tie sa budú hodiť, keď budeme chcieť porovnať, koľko energie spotrebuje jeden celý cyklus zariadenia od zobudenia až po opätovné uspanie.

Pri meraní dodržiavajte tieto všeobecné pravidlá:

  • Poznajte rozlíšenie a presnosť svojho merača. Napríklad merač UM24 meria prúd s rozlíšením 1 mA a s presnosťou ±(0,8 % + 3 digity), teda pri malých prúdoch s chybou až niekoľko mA. Hodnota, ktorá je porovnateľná s chybou merača, je len orientačná.
  • Používajte stabilný zdroj napájania. Zariadenie napájajte z USB nabíjačky. Ak ho napájate z počítača, meranie ovplyvní aj komunikácia cez USB. Powerbanka sa zase pri malom odbere môže sama vypnúť.
  • Merajte ustálený stav a dostatočne dlho. Merač obnovuje hodnoty len niekoľkokrát za sekundu, takže krátke špičky prúdu (napr. pri vysielaní cez WiFi) nemusí zachytiť. Kumulované hodnoty ich však zahrnú.
  • Pred každým meraním vynulujte kumulované hodnoty.
  • Medzi meraniami meňte vždy len jednu vec. Používajte rovnaký kábel, rovnaký zdroj a rovnaké zapojenie, aby ste mohli výsledky navzájom porovnať.
  • Zapisujte si podmienky merania spolu s nameranými hodnotami (čo zariadenie robilo, aké bolo zapojenie, ako dlho meranie trvalo).

Merač meria odber celej dosky pri napätí 5 V, teda nielen mikrokontroléra, ale aj stabilizátora napätia, WiFi čipu, LED diód a všetkých pripojených senzorov.

Task

Odmerajte odber zariadenia v prípadoch uvedených v tabuľke 1.

Zariadenie napájajte z USB nabíjačky cez USB multimeter. Namerané hodnoty budú slúžiť ako referenčné, s nimi budete porovnávať všetky ďalšie merania. Napätie, pri ktorom ste merali, si zapíšte pod tabuľku.

Tab. 1: Odber zariadenia v jednotlivých stavoch
Prípad Prúd (mA) Výkon (mW)
program, ktorý nič nerobí
stav Init
stav Measurement
stav ConnectNetwork
stav PublishData
stav DisconnectNetwork
stav Sleep

Niektoré stavy trvajú tak krátko, že ich odber z merača neodčítate. Preto odmerajte aj náboj a energiu, ktoré zariadenie spotrebuje za jeden celý cyklus od štartu až po zaspanie, a zapíšte ich do tabuľky 2.

Tab. 2: Spotreba zariadenia za jeden cyklus
Náboj (mAh) Energia (mWh) Čas (s)

Zníženie pracovnej frekvencie

Jedným zo spôsobov, ako znížiť spotrebu zariadenia, je spomaliť jeho prácu znížením pracovnej frekvencie mikrokontroléra. Ako zistiť a zmeniť pracovnú frekvenciu a na čo si pri tom dať pozor, sa dozviete v kapitole Zmena frekvencie zariadenia.

Task

Odmerajte odber zariadenia pri pracovných frekvenciách uvedených v tabuľke 3.

Merajte program, ktorý nič nerobí, rovnako ako v prvom riadku tabuľky 1. Meniť sa bude len pracovná frekvencia volaním funkcie machine.freq().

Tab. 3: Odber zariadenia pri rôznych pracovných frekvenciách
Frekvencia (MHz) Prúd (mA) Výkon (mW)
150
125
100
75
48

Uspanie zariadenia

Chytrý senzor bude merať teplotu a vlhkosť v pravidelných intervaloch. Medzi meraniami však nemá čo robiť, a preto ho v tomto čase uspíme. Stav Sleep zatiaľ činnosť zariadenia ukončí. Po novom zariadenie v tomto stave zaspí a po zobudení bude pokračovať ďalším meraním (pozri obrázok 2).

---
# spolocna konfiguracia stavovych diagramov THSensor; vklada sa ako prvy
# riadok bloku ```mermaid, za nim nasleduje "flowchart LR" a samotny diagram
config:
  flowchart:
    curve: basis
    nodeSpacing: 40
    rankSpacing: 60
  themeVariables:
    fontSize: 20px
  themeCSS: ".edgeLabel, .edgeLabel p, .labelBkg { background-color: var(--bs-body-bg) !important; }"
---

flowchart LR
    start@{ shape: f-circ } --> init("<div style='width:164px;height:48px;display:flex;align-items:center;justify-content:center;line-height:1.2'>Init</div>")
    init --> measurement("<div style='width:164px;height:48px;display:flex;align-items:center;justify-content:center;line-height:1.2'>Measurement</div>")
    init -- "<code>SVC_PIN</code><br>grounded" --> terminal("<div style='width:164px;height:48px;display:flex;align-items:center;justify-content:center;line-height:1.2'>Service<br>Terminal</div>")
    init -- "long button<br>press" --> reset("<div style='width:164px;height:48px;display:flex;align-items:center;justify-content:center;line-height:1.2'>Factory<br>Reset</div>")
    init -- "no/faulty<br><code>settings.json</code> /<br>short button press" --> configuration("<div style='width:164px;height:48px;display:flex;align-items:center;justify-content:center;line-height:1.2'>Configuration</div>")
    measurement --> connect("<div style='width:164px;height:48px;display:flex;align-items:center;justify-content:center;line-height:1.2'>Connect<br>Network</div>")
    connect -- "connected" --> publish("<div style='width:164px;height:48px;display:flex;align-items:center;justify-content:center;line-height:1.2'>Publish<br>Data</div>")
    connect -- "connection<br>failed" --> disconnect("<div style='width:164px;height:48px;display:flex;align-items:center;justify-content:center;line-height:1.2'>Disconnect<br>Network</div>")
    publish --> disconnect
    disconnect --> sleep("<div style='width:164px;height:48px;display:flex;align-items:center;justify-content:center;line-height:1.2'>Sleep</div>")
    sleep -- "wake up" --> measurement
    terminal --> terminalEnd@{ shape: fr-circ }
    reset --> resetEnd@{ shape: fr-circ }
    configuration --> commissioning("<div style='width:164px;height:48px;display:flex;align-items:center;justify-content:center;line-height:1.2'>Commissioning</div>")
    commissioning -- "verification<br>result" --> configuration
    configuration -- "restart" --> configurationEnd@{ shape: fr-circ }

    %% spolocne styly stavovych diagramov THSensor (farby podla
    %% images/thsensor-state.diagram.complete.png); vklada sa na koniec diagramu
    %% a stavy sa k nim priradia cez "class <stavy> <styl>"
    classDef state fill:#cfe2ff,stroke:#9aa3ad,stroke-width:3px,color:#343a40,font-weight:bold
    classDef service fill:#cbc3a3,stroke:#9aa3ad,stroke-width:3px,color:#343a40,font-weight:bold
    classDef reset fill:#ffd6f5,stroke:#9aa3ad,stroke-width:3px,color:#343a40,font-weight:bold
    classDef config fill:#fddba7,stroke:#9aa3ad,stroke-width:3px,color:#343a40,font-weight:bold
    classDef error fill:#ffd7d9,stroke:#9aa3ad,stroke-width:3px,color:#343a40,font-weight:bold
    classDef ota fill:#c3f5c8,stroke:#9aa3ad,stroke-width:3px,color:#343a40,font-weight:bold
    classDef initial fill:#000,stroke:#fff,stroke-width:2px
    classDef final fill:#fff,stroke:#000,stroke-width:2px

    class init,measurement,connect,publish,disconnect,sleep state
    class terminal service
    class reset reset
    class configuration,commissioning config
    class start initial
    class terminalEnd,resetEnd,configurationEnd final

Obr. 2: Stavový diagram zariadenia s opakovaným meraním

Na uspanie zariadenia použijeme ľahký spánok (pozri prednášku (Nízka) spotreba energie). Na mikrokontroléri RP2350 by nám hlboký spánok neušetril žiadnu energiu navyše a zariadenie by sa po zobudení reštartovalo.

Task

Pridajte do nastavení interval merania.

Nastavenia merania budú v samostatnom vnorenom modeli Measurement, podobne ako nastavenia WiFi siete alebo MQTT brokera. Zatiaľ bude obsahovať len položku interval, ktorá určuje interval merania v sekundách. Predvolená hodnota bude 900, teda 15 minút. V nastaveniach bude model dostupný pod názvom measurement, takže interval získate ako settings.measurement.interval.

Interval merania musí byť kladné celé číslo. Kontrolu môžete napísať ako znovupoužiteľnú funkciu do modulu models/validators.py.

Task

Doplňte do formulára s nastaveniami pole na zmenu intervalu merania.

Task

Uspite zariadenie v stave Sleep na interval merania a po zobudení pokračujte stavom Measurement.

Ľahký spánok zabezpečí funkcia lightsleep() z modulu machine, ktorej parametrom je čas spánku v milisekundách.

Task

Odmerajte odber zariadenia v stave Sleep a spotrebu za jeden cyklus a porovnajte ich s hodnotami v tabuľkách 1 a 2.

Okamžité prebudenie zariadenia z režimu spánku

Nie vždy je vhodné čakať, kým sa zariadenie zobudí automaticky po uplynutí nastaveného času. V niektorých situáciách potrebujeme možnosť prebudiť ho skôr – napríklad pri zásahu používateľa. Keďže naše zariadenie je vybavené tlačidlom, môžeme ho využiť práve na tento účel. Po stlačení tlačidla sa zariadenie prebudí a reštartuje, čím získame kontrolu nad jeho prebudením aj mimo plánovaného cyklu spánku.

V tomto kroku teda vytvoríte prerušenie na pine, ku ktorému je pripojené tlačidlo. Ak je zariadenie v režime spánku, vznik externého prerušenia spôsobí jeho okamžité prebudenie.

Funkcia, ktorá bude spracúvať vzniknuté prerušenie, môže byť prázdna – dôležité je, aby bola zavolaná. V opačnom prípade prerušenie nebude ošetrené a zariadenie sa neprebudí.

Externý časovač pomocou RTC modulu

Náš chytrý senzor nebude aktívny neustále – väčšinu času strávi v úspornom režime spánku, aby šetril energiu. Takéto správanie je typické pre zariadenia v rámci Internetu vecí, kde je dôležité, aby jednotlivé komponenty pracovali len vtedy, keď je to skutočne potrebné. Zo spánku sa môže zariadenie prebudiť dvoma spôsobmi: buď manuálne, stlačením tlačidla používateľom, alebo automaticky po uplynutí vopred nastaveného časového intervalu.

Ak budeme senzor uspávať vždy na konštantný čas, musíme počítať s tým, že jeho následné prebúdzanie sa bude postupne posúvať o dobu, počas ktorej senzor vykonáva meranie a spracovanie dát. Aj keď nejde o závažný problém, v niektorých prípadoch môže viesť k neželanej používateľskej skúsenosti.

Ak si napríklad používateľ nastaví, aby sa meranie vykonávalo vždy na celú hodinu, už po jednom dni môže byť začiatok merania posunutý o približne jednu minútu.

Na odstránenie tohto problému a zabezpečenie, aby sa merania vykonávali vždy v presne stanovených intervaloch, máme dve možnosti:

  1. Pred uspaním zariadenia vypočítať presnú dĺžku času, počas ktorého má zostať v spánku. Týmto spôsobom môžeme zabezpečiť, že sa prebudí práve v okamihu, keď sa má začať ďalšie meranie.

  2. Uspať zariadenie na neurčitý čas a prebudiť ho externým signálom v presne určenom okamihu. Na tento účel je možné použiť externý hodinový modul, ktorý dokáže generovať zobúdzací signál na svojom výstupnom pine. Tento signál môžeme pripojiť k vstupu mikrokontroléra, ktorý pri jeho aktivácii zariadenie zobudí podobne, ako v prípade stlačenia tlačidla. Takýmto modulom je napr. DS3231.

    Rozloženie pinov RTC modulu DS3231

Strážny pes

Počas prevádzky môže zariadenie niekedy „uviaznuť“ – dostať sa do stavu, z ktorého sa nedokáže zotaviť bez zásahu používateľa. Typickým príkladom je nekonečná slučka, v ktorej sa zariadenie pokúša pripojiť k neexistujúcej WiFi sieti, alebo neošetrená výnimka, ktorá spôsobí, že zariadenie zostane „visieť“.

Aby sa dokázalo automaticky zotaviť z takýchto situácií, používame špeciálny časovač s názvom Watchdog Timer. Ak zariadenie uviazne, Watchdog ho po uplynutí nastaveného času automaticky reštartuje.

V tomto kroku vo vhodnom okamihu zapnite a správne nakonfigurujte Watchdog Timer, aby sa predišlo zaseknutiu zariadenia a zabezpečila sa jeho stabilná prevádzka.

Správa napájania

Na nasledujúcom obrázku sa nachádza časť schémy zapojenia vývojovej dosky RPi Pico 2, ktorá súvisí s napájaním.

RPi Pico 2 W: Napájanie

Na základe tejto schémy je možné povedať nasledovné:

  • Pin VBUS je priamo pripojený k USB. Ak je doska napájaná z USB portu, je možné z pinu VBUS odoberať priamo napätie 5V.

  • Pomocou pinu WL_GPIO2 vieme jednoducho overiť, či je doska napájaná z USB portu. Ak sa na ňom nachádza hodnota 1, doska je napájaná z USB portu. Ak sa na ňom nachádza hodnota 0, doska nie je napájaná z USB portu.

    vbus = Pin('WL_GPIO2', Pin.IN, Pin.PULL_DOWN)
    
    if vbus.value() == True:
        print('Device is USB Powered.')
    else:
        print('Device is battery powered.')
  • Ak je doska napájaná z pinu VSYS, vďaka Schottkyho dióde sa toto napätie nedostane späť na USB port, čo by mohlo mať zlé následky.

Vstupné napätie je možné aj odmerať priamo pomocou komponentov dosky bez nutnosti zostavenia vlastného napäťového deliča. Tým pádom je možné monitorovať aj aktuálny stav napájania a v prípade potreby notifikovať nutnosť jeho výmeny. Na tento účel je možné použiť štvrtý kanál ADC (ADC3), ktorý je pripojený priamo k pinu GP29.

Na doskách s WiFi modulom to však nestačí. V oficiálnej dokumentácii v kapitole venovanej rozloženiu pinov, sa dočítame, že ak chceme zistiť hodnotu napätia na pine VSYS, musíme na pine GP25 nastaviť hodnotu 1. Po ukončení merania je zase potrebné vrátiť všetko do pôvodného stavu.

Pre odmeranie napätia na pine VSYS je možné použiť nasledujúcu funkciu:

def measure_vsys():
    # prepare pins
    Pin(25, Pin.OUT, value=1)
    Pin(29, Pin.IN, pull=None)

    # read and convert value
    value = ADC(3).read_u16() * 3 * 3.3 / 2**16

    # restore original state of pins
    Pin(29, Pin.ALT, pull=Pin.PULL_DOWN, alt=7)
    Pin(25, Pin.OUT, value=0, pull=Pin.PULL_DOWN)

    return value

Pred odchodom z cvičenia…

Ďalšie úlohy

  1. V prípade akýchkoľvek problémov nezabudnite prejsť do stavu Error a reprezentovať vzniknutú chybu potrebným blikaním.

Ďalšie zdroje

  1. Hackaday.io: Review 016: UM24 USB Meter

  2. MicroPython Chapters: Časovač Watchdog

  3. MicroPython: Quick reference for the RP2: General board control

  4. MicroPython Chapters: Zmena frekvencie zariadenia

  5. The DS3231 real time clock chip

  6. Last Minute Engineers: Interface DS3231 Precision RTC Module with Arduino

  7. Random Nerd Tutorials: Raspberry Pi Pico: DS3231 RTC (Real-Time Clock) – Get Time and Set Alarms (MicroPython)

  8. Workbench Wednesdays: Measuring the Raspberry Pi Pico W’s Power Consumption

  9. Power for the Raspberry Pi Pico - Guide to using VBUS, VSYS and 3V3 for external power circuits