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:

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:

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.

Brojevni pravac od 0 do MAX s početnim otkucajem blizu MAX i završnim otkucajem blizu 0; isprekidana strelica prelijevanja pokazuje da se nakon MAX brojač vraća na 0.

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.