3.2. Temporizare¶
Modulul time grupează funcții pentru pauze (oprirea scriptului pentru o durată cunoscută) și pentru măsurarea cât durează ceva. Pe un microcontroler acestea nu sunt facilități opționale; ele sunt modul în care scriptul ritmează interacțiunile cu lumea exterioară – cât timp să mențină un pin la nivel ridicat, cât să aștepte între eșantioane, cât timp a trecut de la ultima apăsare a unui buton.
3.2.1. Pauze¶
Trei funcții de pauză blochează scriptul pentru durata solicitată:
time.sleep(s)– pauză dessecunde. Acceptă un float, decitime.sleep(0.5)așteaptă o jumătate de secundă.time.sleep_ms(ms)– pauză demsmilisecunde. Argumentul trebuie să fie un întreg.time.sleep_us(us)– pauză deusmicrosecunde.
import time
print("now")
time.sleep_ms(500)
print("half a second later")
Folosiți time.sleep_ms() pentru nevoile tipice de „așteaptă puțin” și time.sleep_us() doar când temporizarea trebuie să fie strânsă. Simplul time.sleep() este, de asemenea, în regulă, dar variantele cu argument întreg evită conversia în virgulă mobilă și se citesc mai natural pentru intervale scurte.
Pauza (sleep) este un apel blocant. Cât timp scriptul este în pauză, nu face nimic altceva – nu citește un pin, nu deservește un UART, nu actualizează un LED. Recurgeți la sleep atunci când blocarea este ceea ce doriți; folosiți modelul neblocant de mai jos atunci când nu este.
3.2.2. Citirea ceasului¶
Pentru a măsura cât durează o bucată de cod, citiți ceasul înainte și după:
time.ticks_ms()– valoarea curentă a ticurilor în milisecunde.time.ticks_us()– la fel, în microsecunde.
import time
start = time.ticks_ms()
do_work()
elapsed = time.ticks_ms() - start
print("took", elapsed, "ms")
Acest lucru funcționează de cele mai multe ori. Contorul de ticuri se resetează (revine la zero) după un număr mare, dar finit, de ticuri, iar scăderea naivă peste această resetare produce un număr negativ sau pozitiv complet greșit.
Contorul de ticuri revine la zero când atinge limita de întreg. O simplă scădere peste această resetare este greșită.¶
3.2.3. ticks_diff¶
Pentru a obține corect ticurile scurse, chiar și peste o resetare, folosiți time.ticks_diff():
import time
start = time.ticks_ms()
do_work()
elapsed = time.ticks_diff(time.ticks_ms(), start)
print("took", elapsed, "ms")
Ordinea argumentelor este ticks_diff(later, earlier) – expresia se citește „cât de departe este later după earlier„. Rezultatul este un întreg cu semn; pozitiv înseamnă că later este într-adevăr mai târziu, negativ înseamnă că este în trecut. Funcția gestionează resetarea intern.
Sfat
Asociați întotdeauna time.ticks_ms() / time.ticks_us() cu time.ticks_diff(). Scăderea brută este corectă de cele mai multe ori; momentul în care este greșită este atunci când un script rulează de mult timp – de obicei cel mai prost moment pentru a depana o anomalie de temporizare.
3.2.4. Temporizare neblocantă¶
Un script pentru microcontroler are de obicei mai mult de un lucru de făcut „în același timp”: citește un buton, clipește un LED, interoghează un senzor, deservește un UART. sleep nu este bun pentru asta – cât timp un sleep rulează, celelalte sarcini sunt blocate.
Modelul standard este de a păstra un termen limită pentru fiecare sarcină și de a verifica la fiecare buclă dacă termenul limită a trecut. Decizia de a acționa se construiește pe time.ticks_diff(), niciodată pe 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-ul comută la fiecare 500 ms, senzorul este interogat la fiecare 100 ms și niciuna dintre sarcini nu o blochează pe cealaltă. time.ticks_add() avansează un termen limită cu un increment cunoscut fără a fi afectat de resetare.
Această formă – o singură buclă, mai multe sarcini temporizate, fără sleep în corp – apare peste tot unde merge codul hardware: debouncing software al comutatoarelor, secvențierea motoarelor, expirări la citirea UART. Aceleași trei funcții (time.ticks_ms(), time.ticks_diff(), time.ticks_add()) acoperă fiecare caz.