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ă de s secunde. Acceptă un float, deci time.sleep(0.5) așteaptă o jumătate de secundă.

  • time.sleep_ms(ms) – pauză de ms milisecunde. Argumentul trebuie să fie un întreg.

  • time.sleep_us(us) – pauză de us microsecunde.

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ă:

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.

Axă numerică de la 0 la MAX cu un tic de start aproape de MAX și un tic de final aproape de 0; o săgeată întreruptă de reluare arată că, după MAX, contorul revine la 0.

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.