3.2. Mjerenje vremena¶
Modul time grupira funkcije za spavanje (pauziranje skripte na poznato trajanje) i za mjerenje koliko nešto traje. Na mikrokontroleru to nisu samo zgodni dodaci; to je način na koji skripta usklađuje interakcije s vanjskim svijetom – koliko dugo držati pin na visokoj razini, koliko dugo čekati između uzoraka, koliko je vremena prošlo otkad je gumb zadnji put pritisnut.
3.2.1. Spavanje¶
Tri funkcije spavanja blokiraju skriptu na traženo trajanje:
time.sleep(s)– pauza odssekundi. Prihvaća decimalni broj, patime.sleep(0.5)čeka pola sekunde.time.sleep_ms(ms)– pauza odmsmilisekundi. Argument mora biti cijeli broj.time.sleep_us(us)– pauza odusmikrosekundi.
import time
print("now")
time.sleep_ms(500)
print("half a second later")
Koristite time.sleep_ms() za uobičajene potrebe „pričekaj malo”, a time.sleep_us() samo kada vrijeme mora biti precizno. Obični time.sleep() također je u redu, ali varijante s cjelobrojnim argumentom izbjegavaju pretvorbu u pomični zarez i prirodnije se čitaju za kratke intervale.
Spavanje je blokirajući poziv. Dok skripta spava, ne radi ništa drugo – ne čita pin, ne poslužuje UART, ne ažurira LED-icu. Posegnite za sleep kada je blokiranje upravo ono što želite; koristite neblokirajući obrazac u nastavku kada nije.
3.2.2. Čitanje sata¶
Da biste izmjerili koliko traje neki dio koda, pročitajte sat prije i poslije:
time.ticks_ms()– trenutna vrijednost otkucaja u milisekundama.time.ticks_us()– isto u mikrosekundama.
import time
start = time.ticks_ms()
do_work()
elapsed = time.ticks_ms() - start
print("took", elapsed, "ms")
Ovo radi većinu vremena. Brojač otkucaja se prelijeva (vraća se na nulu) nakon velikog, ali konačnog broja otkucaja, a naivno oduzimanje preko tog prelijevanja daje potpuno pogrešan negativan ili pozitivan broj.
Brojač otkucaja vraća se na nulu kada dosegne cjelobrojnu granicu. Obično oduzimanje preko tog prelijevanja je pogrešno.¶
3.2.3. ticks_diff¶
Da biste ispravno dobili proteklo vrijeme otkucaja, čak i preko prelijevanja, koristite time.ticks_diff():
import time
start = time.ticks_ms()
do_work()
elapsed = time.ticks_diff(time.ticks_ms(), start)
print("took", elapsed, "ms")
Redoslijed argumenata je ticks_diff(later, earlier) – izraz se čita „koliko je later nakon earlier”. Rezultat je predznačeni cijeli broj; pozitivan znači da je later doista kasnije, negativan znači da je u prošlosti. Funkcija interno obrađuje prelijevanje.
Savjet
Uvijek uparite time.ticks_ms() / time.ticks_us() s time.ticks_diff(). Sirovo oduzimanje točno je većinu vremena; trenutak kada je pogrešno jest kada skripta radi već dugo – obično najgori trenutak za otklanjanje pogreške u vremenu.
3.2.4. Neblokirajuće mjerenje vremena¶
Skripta za mikrokontroler obično ima više od jedne stvari koju treba obaviti „u isto vrijeme”: čitati gumb, treptati LED-icom, prozirati senzor, posluživati UART. sleep za to nije dobar – dok jedan sleep traje, ostali zadaci su zaustavljeni.
Standardni obrazac je da se za svaki zadatak drži rok, te da se u svakoj petlji provjeri je li rok prošao. Odluka o djelovanju gradi se na time.ticks_diff(), nikada 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-ica se prebacuje svakih 500 ms, senzor se prozire svakih 100 ms, i nijedan zadatak ne blokira drugi. time.ticks_add() pomiče rok za poznati prirast bez upadanja u zamku prelijevanja.
Taj oblik – jedna petlja, nekoliko vremenski raspoređenih zadataka, bez sleep u tijelu – pojavljuje se posvuda gdje ide hardverski kod: softversko uklanjanje podrhtavanja sklopki, sekvenciranje motora, istek vremena čitanja UART-a. Ista tri funkcije (time.ticks_ms(), time.ticks_diff(), time.ticks_add()) pokrivaju svaki slučaj.