3.2. Időzítés

A time modul olyan függvényeket csoportosít, amelyek az alvást (a szkript ismert időtartamra történő szüneteltetését) és valaminek az időtartamát mérik. Egy mikrovezérlőn ezek nem csupán kellemes kiegészítők; ezekkel ütemezi a szkript a külvilággal való kapcsolatait – meddig tartson egy lábat magasan, mennyit várjon a mintavételek között, mennyi idő telt el egy gomb utolsó megnyomása óta.

3.2.1. Alvás

Három alvásfüggvény blokkolja a szkriptet a kért időtartamra:

  • time.sleep(s) – szünet s másodpercig. Lebegőpontos számot fogad, így a time.sleep(0.5) fél másodpercet vár.

  • time.sleep_ms(ms) – szünet ms ezredmásodpercig. Az argumentumnak egész számnak kell lennie.

  • time.sleep_us(us) – szünet us mikromásodpercig.

import time

print("now")
time.sleep_ms(500)
print("half a second later")

Használd a time.sleep_ms() függvényt a tipikus „várj egy kicsit” igényekhez, és a time.sleep_us() függvényt csak akkor, amikor az időzítésnek szorosnak kell lennie. A sima time.sleep() is megfelelő, de az egész szám argumentumú változatok elkerülik a lebegőpontos átalakítást, és természetesebben olvashatók rövid időközöknél.

Az alvás blokkoló hívás. Amíg a szkript alszik, semmi mást nem csinál – nem olvas lábat, nem szolgál ki UART-ot, nem frissít LED-et. Nyúlj a sleep hívásához, amikor a blokkolás éppen az, amit szeretnél; használd az alábbi nem blokkoló mintát, amikor nem ez a cél.

3.2.2. Az óra beolvasása

Annak méréséhez, hogy egy kóddarab mennyi ideig tart, olvasd be az órát előtte és utána:

import time

start = time.ticks_ms()
do_work()
elapsed = time.ticks_ms() - start
print("took", elapsed, "ms")

Ez az idő nagy részében működik. A tick-számláló átfordul (visszaugrik nullára) egy nagy, de véges számú tick után, és az ezen az átforduláson átnyúló naiv kivonás vadul hibás negatív vagy pozitív számot eredményez.

Számegyenes 0-tól MAX-ig, egy kezdő tickkel MAX közelében és egy záró tickkel 0 közelében; egy szaggatott átfordulási nyíl mutatja, hogy MAX után a számláló visszatér 0-ra.

A tick-számláló visszaugrik nullára, amikor eléri az egész szám korlátját. Az ezen az átforduláson átnyúló sima kivonás hibás.

3.2.3. ticks_diff

Az eltelt tickek helyes kiszámításához, még átforduláson keresztül is, használd a time.ticks_diff() függvényt:

import time

start = time.ticks_ms()
do_work()
elapsed = time.ticks_diff(time.ticks_ms(), start)
print("took", elapsed, "ms")

Az argumentumok sorrendje ticks_diff(later, earlier) – a kifejezés úgy olvasandó: „mennyivel van a later az earlier után”. Az eredmény előjeles egész szám; a pozitív azt jelenti, hogy a later valóban később van, a negatív pedig, hogy a múltban van. A függvény belsőleg kezeli az átfordulást.

Javaslat

Mindig párosítsd a time.ticks_ms() / time.ticks_us() függvényt a time.ticks_diff() függvénnyel. A nyers kivonás az idő nagy részében helyes; akkor hibás, amikor egy szkript már régóta fut – ami általában a legrosszabb időpont egy időzítési hiba felderítésére.

3.2.4. Nem blokkoló időzítés

Egy mikrovezérlő-szkriptnek általában egynél több dolga van „egyszerre”: gombot olvasni, LED-et villogtatni, érzékelőt lekérdezni, UART-ot kiszolgálni. A sleep erre nem jó – amíg egy sleep fut, a többi feladat megreked.

A szokásos minta az, hogy feladatonként egy határidőt tartunk fenn, és minden ciklusban ellenőrizzük, hogy a határidő letelt-e. A cselekvésről szóló döntés a time.ticks_diff() függvényre épül, sosem a sleep hívásra:

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)

A LED 500 ezredmásodpercenként vált állapotot, az érzékelőt 100 ezredmásodpercenként kérdezzük le, és egyik feladat sem blokkolja a másikat. A time.ticks_add() egy ismert lépéssel előrébb tolja a határidőt anélkül, hogy beleütközne az átfordulásba.

Ez a felépítés – egyetlen ciklus, több időzített feladat, sleep nélkül a törzsben – mindenütt felbukkan, ahol hardveres kód jelenik meg: kapcsolók szoftveres pergésmentesítése, motorok ütemezése, UART-olvasási időtúllépések. Ugyanaz a három függvény (time.ticks_ms(), time.ticks_diff(), time.ticks_add()) minden esetet lefed.