3.2. Časování¶
Modul time sdružuje funkce pro spánek (pozastavení skriptu na známou dobu) a pro měření, jak dlouho něco trvá. Na mikrokontroléru to nejsou nepovinné vymoženosti; jsou způsobem, jakým skript řídí tempo interakcí s okolním světem – jak dlouho držet pin ve vysoké úrovni, jak dlouho čekat mezi vzorky, jak dlouho uplynulo od posledního stisku tlačítka.
3.2.1. Spánek¶
Tři funkce spánku blokují skript po požadovanou dobu:
time.sleep(s)– pozastaví nassekund. Přijímá float, takžetime.sleep(0.5)čeká půl sekundy.time.sleep_ms(ms)– pozastaví namsmilisekund. Argument musí být celé číslo.time.sleep_us(us)– pozastaví nausmikrosekund.
import time
print("now")
time.sleep_ms(500)
print("half a second later")
Pro typické potřeby „chvíli počkat“ použijte time.sleep_ms() a time.sleep_us() jen tehdy, když časování musí být přesné. Obyčejná funkce time.sleep() je také v pořádku, ale varianty s celočíselným argumentem se vyhýbají převodu na pohyblivou řádovou čárku a pro krátké intervaly se čtou přirozeněji.
Spánek je blokující volání. Zatímco skript spí, nedělá nic jiného – nečte pin, neobsluhuje UART, neaktualizuje LED. Sáhněte po sleep, když je blokování to, co chcete; pokud ne, použijte neblokující vzorec níže.
3.2.2. Čtení hodin¶
Chcete-li změřit, jak dlouho trvá nějaký úsek kódu, přečtěte hodiny před ním a po něm:
time.ticks_ms()– aktuální hodnota tiků v milisekundách.time.ticks_us()– totéž v mikrosekundách.
import time
start = time.ticks_ms()
do_work()
elapsed = time.ticks_ms() - start
print("took", elapsed, "ms")
Toto funguje většinu času. Čítač tiků přeteče (vrátí se zpět na nulu) po velkém, ale konečném počtu tiků a naivní odečtení přes tento přechod produkuje divoce nesprávné záporné nebo kladné číslo.
Čítač tiků se po dosažení celočíselného limitu vrátí zpět na nulu. Obyčejné odečtení přes tento přechod je nesprávné.¶
3.2.3. ticks_diff¶
Pro správné získání uplynulých tiků, i přes přetečení, použijte time.ticks_diff():
import time
start = time.ticks_ms()
do_work()
elapsed = time.ticks_diff(time.ticks_ms(), start)
print("took", elapsed, "ms")
Pořadí argumentů je ticks_diff(later, earlier) – výraz se čte jako „jak daleko je later po earlier“. Výsledkem je celé číslo se znaménkem; kladné znamená, že later je skutečně později, záporné znamená, že je v minulosti. Funkce přetečení zpracovává interně.
Tip
time.ticks_ms() / time.ticks_us() vždy párujte s time.ticks_diff(). Surové odečtení je správné většinu času; kdy je nesprávné, je tehdy, když skript běží dlouhou dobu – obvykle ve chvíli, kdy je ladění chyby časování nejhorší.
3.2.4. Neblokující časování¶
Skript pro mikrokontrolér obvykle musí dělat více než jednu věc „současně“: číst tlačítko, blikat LED, dotazovat senzor, obsluhovat UART. sleep k tomu není dobrý – zatímco běží jeden sleep, ostatní úlohy jsou zastavené.
Standardním vzorcem je udržovat termín (deadline) pro každou úlohu a v každé smyčce kontrolovat, zda termín uplynul. Rozhodnutí jednat je postaveno na time.ticks_diff(), nikdy na sleep:
import time
next_blink = time.ticks_ms()
next_poll = time.ticks_ms()
state = False
while True:
now = time.ticks_ms()
if time.ticks_diff(now, next_blink) >= 0:
state = not state
# update LED here
next_blink = time.ticks_add(next_blink, 500)
if time.ticks_diff(now, next_poll) >= 0:
# read sensor here
next_poll = time.ticks_add(next_poll, 100)
LED se přepíná každých 500 ms, senzor se dotazuje každých 100 ms a žádná úloha neblokuje druhou. time.ticks_add() posune termín o známý přírůstek, aniž by narazila na problém s přetečením.
Tento tvar – jediná smyčka, několik časovaných úloh, žádný sleep v těle – se objevuje všude, kde se vyskytuje hardwarový kód: softwarové potlačení zákmitů spínačů (debouncing), sekvencování motorů, časové limity čtení z UART. Stejné tři funkce (time.ticks_ms(), time.ticks_diff(), time.ticks_add()) pokrývají každý případ.