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ünetsmásodpercig. Lebegőpontos számot fogad, így atime.sleep(0.5)fél másodpercet vár.time.sleep_ms(ms)– szünetmsezredmásodpercig. Az argumentumnak egész számnak kell lennie.time.sleep_us(us)– szünetusmikromá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:
time.ticks_ms()– az aktuális tick-érték ezredmásodpercben.time.ticks_us()– ugyanaz mikromásodpercben.
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.
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.