Managing Energy Consumption with Software
Motivation in the Beginning
Predstavte si, že pracujete na niečom veľmi dôležitom. Ste totálne sústredený, keď vtom sa náhle ozve váš žalúdok a dá vám rozličnými akusticko-citlivými možnosťami najavo, že máte hlad. Neváhate, však to predsa nie je prvýkrát, keď ste vyhladli, a vytočíte svoju obľúbenú pizzeriu, objednáte si svoju obľúbenú pizzu a spojovateľka vám oznámi, že vám vašu pizzu doručia až o 60 minút. Takže ešte 60 minút budete zápasiť s hladom.
Čo teraz? Do úvahy prichádza niekoľko možností:
- nebudem robiť ďalej, pokiaľ sa nenajem - takže nasledujúcich 60 minút strávim sledovaním hodiniek
- budem ďalej robiť hladný a popri tom budem pravidelne sledovať hodinky, či už neuplynulo tých 60 minút
- nastavím si budik, aby ma po uplynutí 60 minút upozornil a ja som teda nemusel sledovať neustále hodinky, ale môžem sa plne sústrediť na prácu
Aj napriek tomu, že tento príklad z reálneho života vyznieva vzhľadom na uvedené možnosti pomerne komicky, môžeme isté paralely nájsť v mnohých našich, ale aj v rozličných existujúcich IoT riešeniach. Takže - čo robíme zle?
Motion Detection
Na začiatku vytvoríme jednoduché IoT riešenie, kde použijeme PIR senzor a jeho výstup pripojíme k mikrokontroléru. Toto riešenie nás bude sprevádzať počas celej kapitoly a postupne na ňom aplikované rozličné spôsoby zníženia spotreby elektrickej energie.
O fungovaní PIR senzora sa nebudeme baviť podrobne. Zjednodušene poviem, že je to senzor pohybu, ktorý má 2 vstupy (napájanie 5V a zem) a 1 výstup (vráti logickú 1 (obyčajne na úrovni 3.3V), ak bol detekovaný pohyb, ináč vracia 0). Pre konkrétne hodnoty napájania a výstupu je však potrebné sa pozrieť do dokumentácie (datasheet).
[!NOTE]
PIR senzor by sme samozrejme vedeli použiť v zapojení aj bez mikrokontroléra. Nás však bude zaujímať práve to, ako budeme čítať jeho výstup, ktorý hovorí, či k pohybu došlo alebo nie.
Správanie navrhovaného IoT zariadenia je možné reprezentovať aj jednoduchým stavovým strojom, ktorého stavový diagram sa nachádza na obrázku XXX. Tento stroj sa bude vždy nachádzať v jednom z dvoch stavov:
IDLE
- nebol zaznamenaný žiadny pohybALARM
- pohyb bol zaznamenaný

V riešení sa bude nachádzať aj jedna externá LED dióda, ktorá sa bude používať na indikáciu toho, v akom stave sa systém nachádza. Miesto nej je možné zapojiť napr. reproduktor alebo akýkoľvek iný akčný člen, ktorý signál ďalej spracuje a nakoniec odošle napr. SMS správu.
Schéma zapojenia zariadenia sa nachádza na obrázku XXX.

Let's Code!
Kód funkcie setup()
sa nachádza vo výpise XXX. V tejto funkcii sa najprv inicializujú dva piny:
- pin 2 - tu bude pripojený výstup z PIR senzora, a
- pin 8 - tu bude pripojená notifikačná LED dióda.
Rovnako tak bude vo funkcii inicializovaná globálna premenná isMovement
na hodnotu false
(žiadny pohyb). Táto premenná bude reprezentovať stav zariadenia, resp. systému. Ak bude detekovaný pohyb, bude mať hodnotu true
a systém bude v stave ALARM
. V opačnom prípade bude mať hodnotu false
a systém bude v stave IDLE
.
Nakoniec tu bude inicializovaná aj sériová linka, ktorá bude použitá na jednoduché logovanie.
#include <Arduino.h>
#define PIN_LED 8
#define PIN_PIR 2
bool isMovement;
void setup(){
// setup serial
Serial.begin(9600);
while(!Serial);
// set pin modes
pinMode(PIN_LED, OUTPUT);
pinMode(PIN_PIR, INPUT);
// initial state
isMovement = false;
}
V implementácii funkcie loop()
dôjde na základe prečítanej hodnoty z výstupu PIR senzoru a na základe aktuálneho stavu systému k prechodu zo stavu IDLE
do stavu ALARM
alebo zo stavu ALARM
do stavu IDLE
.
void loop(){
int data = digitalRead(PIN_PIR);
// state ALARM
if(isMovement == false && data == HIGH){
Serial.println("> Alarm State");
isMovement = true;
digitalWrite(PIN_LED, HIGH);
}
// state IDLE
if(isMovement == true && data == LOW){
Serial.println("> Idle State");
isMovement = false;
digitalWrite(PIN_LED, LOW);
}
// have a break
delay(500);
}
Po preložení a nahratí kódu do Arduina sa LED dióda bude rozsvecovať a zhasínať na základe toho, či PIR senzor zaznamenal pohyb alebo nie.
Aby kód viac reflektoval stavový diagram, bude pre každý stav vytvorená funkcia s názvom stavu - alarm()
a idle()
. Každá z nich bude reprezentovať správanie systému/zariadenia v príslušnom stave. Vďaka tomuto prístupu sa bude dať v programe a jeho ďalších zmenách ľahšie orientovať.
Kód funkcie idle()
sa nachádza vo výpise XXX. Táto funkcia zhasne LED diódu, nastaví hodnotu stavovej premennej isMovement
na false
a bude čakať, kým sa na výstupe z PIR senzora objaví úroveň HIGH
.
void idle(){
Serial.println("> Idle State");
// update state
isMovement = false;
digitalWrite(PIN_LED, LOW);
// wait for change
while(digitalRead(PIN_PIR) == LOW){
delay(500);
}
}
Následne funkcia alarm()
rozsvieti LED diódu, nastaví hodnotu stavovej premennej isMovement
na true
a bude čakať, kým sa na výstupe z PIR senzora objaví úroveň LOW
. Jej kód sa nachádza vo výpise XXX.
void alarm(){
Serial.println("> Alarm State");
// update state
isMovement = true;
digitalWrite(PIN_LED, HIGH);
// wait for change
while(digitalRead(PIN_PIR) == HIGH){
delay(500);
}
}
Nakoniec zostáva upraviť podobu funkcie loop()
, v ktorej bude dochádzať len k prechodu z jedného stavu do druhého. Jej kód sa nachádza vo výpise XXX.
void loop(){
idle();
alarm();
}