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.