Arduino millis() verzus micros()
Pri používaní knižnice Arduino máte dva jednoduché spôsoby, ako získať aktuálny čas od spustenia dosky Arduino: funkcie
To sú veľmi užitočné funkcie, ktoré potrebujete takmer vo všetkých svojich programoch. Umožnia vám napríklad veľmi jednoducho písať multitaskové programy a vyhnúť sa tak používaniu funkcie delay().
Tu je príklad typického programu, ktorý používa millis() micros() :
unsigned long previousTime = micros(); // alebo millis()
long timeInterval = 800;
void setup() { }
void loop() {
unsigned long currentTime = micros(); // alebo millis()
// len ak uplynulo 800 micros alebo millis (interval)
if (currentTime - previousTime > timeInterval) {
// vykonať
previousTime = currentTime;
}
}
Možno vás zaujíma, aké sú spoločné body a rozdiely medzi millis() a micros(). Okrem zjavného časového rozdielu, je niečo, čo by ste mali vedieť?
Časové rozlíšenie
Rozlíšenie pre micros() je 4 mikrosekundy na všetkých 16MHz Arduino doskách:
Uno, Mega, Nano atď. Napríklad, ak prečítate čas pomocou micros() a dostanete 10 000, potom ďalšia hodnota, ktorú získate, je 10 004 a potom že 10008 a tak ďalej. Nebudete môcť klesnúť na násobky 1, 2 alebo 3 mikrosekúnd. Ale to naozaj nie je problém. 4 mikrosekundy sú už dobré rozlíšenie, najmä ak vezmete do úvahy, že používate Arduino, nie mikrokontrolér určený na posielanie rakiet do vesmíru.
Takže za jednu sekundu získate 1 000 hodnôt pomocou millis() a získate 250 000 hodnôt pomocou micros(), čo zodpovedá 1 000 000/4. Všimnite si, že presnosť aktuálneho času pre millis() a micros() je rovnaká. Vždy by ste mali dostať rovnaký čas daný 2 funkciami, len s iným rozlíšením.
Pretečenie millis() vs micros().
Na 16-bitovom Arduine (Uno, Mega atď.) je unsigned long uložený na 4 bajtoch alebo 32 bitoch. Hodnoty premennej sa pohybujú od 0 do 4 294 967 295 (2^32 – 1). Je dôležité to vedieť. prečo?
Pretože ak budete premennú neustále inkrementovať, nakoniec dosiahne maximálnu možnú hodnotu. Po tejto hodnote sa premenná vráti na 0. Tomu hovoríme pretečenie.
Prakticky povedané:
Pomocou millis() bude pretekanie trvať približne 49,7 dňa. Ako to vypočítať:
(Maximálna hodnota pre unsigned long) delené (počet milisekúnd za jednu sekundu) delené (počet sekúnd v jednej hodine) delené (počet hodín v jednom dni). 2^32/1000/3600/24 = 49,7 dní. Pre micros() použijeme: (Maximálna hodnota pre dĺžku bez znamienka) vydelená (počet mikrosekúnd za jednu sekundu) vydelená (počet sekúnd za minútu). 2^32 / 1 000 000 / 60 = 71,6 minúty. čo to znamená?
Po 71,6 minútach hodnota, ktorú získate z micros(), pretečie (resetuje sa na nulu) a bude sa zvyšovať, kým nedosiahne maximálnu hodnotu znova a znova.
To je len o niečo viac ako jedna hodina. K pretečeniu micros() teda veľmi pravdepodobne dôjde pri spustení vašich programov a mali by ste si toho byť vedomí.
Pre millis() to bude trvať viac ako 49 dní, ale stále to nemôžete ignorovať.
Vaša doska Arduino môže potenciálne bežať navždy (povedzme navždy = 15 rokov pred poškodením hardvéru). Ak plánujete používať Arduino pre pripojenú domácu aplikáciu, vaša doska bude dlho zapnutá a millis() tiež pravdepodobne pretečie.
Ako vyriešiť problém s pretečením ?
Zdá sa teda, že váš program by sa mohol pokaziť 100 rôznymi spôsobmi, keď premenná pre millis() alebo micros() pretečie. Na to ale existuje jednoduché riešenie.
Najprv predpokladajme, že na porovnanie trvania použijete millis() a micros(). Vypočítate rozdiel medzi aktuálnym časom a posledným časom vykonania akcie, ktorý vám poskytne trvanie. Ak je trvanie vyššie ako daný prah, akciu vykonáte znova. Použitie millis() a micros() bude väčšinou len pre tento prípad použitia.
Aj tak ich nemôžete použiť na získanie skutočného aktuálneho času
(pamätajte, že monitorujú čas od spustenia Arduina, nie od epochy).
Pri použití millis() a micros() na porovnanie ako v programe nižšie budú veci fungovať, aj keď hodnota času pretečie.
// predchádzajúci čas bol v programe deklarovaný predtým (ako unsigned long)
unsigned long currentTime = millis(); // alebo micros()
if (currentTime - previousTime > timeInterval) {
// vykonať akciu
previousTime = currentTime;
}
Je to celkom jednoduché: porovnáte aktuálny čas s časom, kedy ste naposledy uložili hodnotu. Ak je vyšší ako určitá prahová hodnota, vykonáte akciu a zapíšete aktuálny čas do premennej posledného času.
Teraz si predstavte, že hodnota millis() micros() pretečie. Keď nabudúce porovnáte aktuálny čas s predchádzajúcim časom, získate obrovský pozitívny rozdiel, ktorý bude vyšší ako prahová hodnota. Potom aktualizujete posledný čas aktuálnym časom (ktorý bude tesne nad nulou) a to je všetko. Problém vyriešený.
millis() a micros() vo vnútri prerušení
Povedzme, že ste pripojili prerušenie na digitálny vstupný kolík. Toto prerušenie sa spustí vždy, keď niekto stlačí tlačidlo pripojené k kolíku. V rámci prerušenia nefungujú všetky funkcie súvisiace s časom. Stále môžete použiť millis() a micros() na získanie času, ale ak chcete počkať určitý čas porovnaním 2 rôznych časov, nebude to fungovať.
Navyše, ak zostanete pri prerušení príliš dlho, môžete zmeškať dôležité mikro prerušenia a vaše micros() už nebude načas! V každom prípade to majte na pamäti:
pri používaní prerušení udržujte kód veľmi krátky a rýchly.
Upravte iba niektoré premenné, ktoré spracujete neskôr v hlavnom vlákne Arduino. Nikdy nepoužívajte delay() a snažte sa nikdy nepoužívať ani millis() a micros().
Kedy použiť Arduino millis() a kedy micros() ?
Funkčnosť je rovnaká: millis() aj micros() udržiavajú čas od spustenia programu Arduino. Ak váš program vyžaduje vykonávanie akcií s rozlíšením vyšším ako jedna milisekunda, použite micros(). Ak nie, stačí použiť millis(). Nevýhodou pri použití micros() je, že premenná času preteká oveľa rýchlejšie ako premenná millis() (asi 71 minút namiesto 49 dní).
Môže to byť problém, pokiaľ nepoužívate časové funkcie iba na porovnanie predchádzajúceho a aktuálneho času, ako sme to urobili vyššie v tomto príspevku. Celkovo vzaté, 2 veci, ktoré treba mať na pamäti, sú časové rozlíšenie a trvanie pred pretečením. Keď to viete, nemali by ste mať žiadne problémy pri písaní programu Arduino pomocou časových funkcií!
Pridaj komentár