3.2. Timing

De time-module groepeert functies voor slapen (het script voor een bekende duur pauzeren) en voor het meten hoe lang iets duurt. Op een microcontroller zijn deze geen leuke extra’s; ze zijn de manier waarop het script de interacties met de buitenwereld doseert – hoe lang een pin hoog te houden, hoe lang te wachten tussen monsters, hoe lang geleden een knop voor het laatst is ingedrukt.

3.2.1. Slapen

Drie slaapfuncties blokkeren het script voor de gevraagde duur:

  • time.sleep(s) – pauzeer s seconden. Accepteert een float, dus time.sleep(0.5) wacht een halve seconde.

  • time.sleep_ms(ms) – pauzeer ms milliseconden. Het argument moet een integer zijn.

  • time.sleep_us(us) – pauzeer us microseconden.

import time

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

Gebruik time.sleep_ms() voor de gebruikelijke “even wachten”-behoeften en time.sleep_us() alleen wanneer de timing strak moet zijn. Het gewone time.sleep() is ook prima, maar de varianten met integer-argument vermijden floating-pointconversie en lezen natuurlijker voor korte intervallen.

Slapen is een blokkerende aanroep. Terwijl het script slaapt, doet het niets anders – geen pin lezen, geen UART bedienen, geen led bijwerken. Grijp naar sleep wanneer blokkeren is wat je wilt; gebruik het niet-blokkerende patroon hieronder wanneer dat niet zo is.

3.2.2. De klok lezen

Om te meten hoe lang een stukje code duurt, lees je de klok ervoor en erna:

import time

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

Dit werkt meestal. De tickteller loopt over (springt terug naar nul) na een groot maar eindig aantal ticks, en een naïeve aftrekking over die overloop heen levert een volkomen verkeerd negatief of positief getal op.

Getallenlijn van 0 tot MAX met een starttick nabij MAX en een eindtick nabij 0; een gestippelde overloop-pijl toont dat de teller na MAX terugkeert naar 0.

De tickteller loopt terug naar nul wanneer hij de integerlimiet bereikt. Een gewone aftrekking over die overloop heen is verkeerd.

3.2.3. ticks_diff

Om de verstreken ticks correct te krijgen, zelfs over een overloop heen, gebruik je time.ticks_diff():

import time

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

De argumentvolgorde is ticks_diff(later, earlier) – de uitdrukking leest “hoe ver ligt later na earlier“. Het resultaat is een geheel getal met teken; positief betekent dat later daadwerkelijk later is, negatief betekent dat het in het verleden ligt. De functie handelt de overloop intern af.

Tip

Combineer time.ticks_ms() / time.ticks_us() altijd met time.ticks_diff(). De ruwe aftrekking klopt meestal; het moment waarop ze fout gaat is wanneer een script lange tijd heeft gedraaid – meestal het slechtste moment om een timingstoring te debuggen.

3.2.4. Niet-blokkerende timing

Een microcontrollerscript heeft doorgaans meer dan één ding “tegelijkertijd” te doen: een knop lezen, een led laten knipperen, een sensor pollen, een UART bedienen. sleep deugt daar niet voor – terwijl één sleep loopt, staan de andere taken stil.

Het standaardpatroon is om per taak een deadline bij te houden en elke lus te controleren of de deadline is verstreken. De beslissing om te handelen is gebouwd op time.ticks_diff(), nooit op 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)

De led wisselt elke 500 ms, de sensor wordt elke 100 ms gepollt, en geen van beide taken blokkeert de ander. time.ticks_add() schuift een deadline op met een bekende stap zonder in de val van de overloop te lopen.

Deze vorm – een enkele lus, meerdere getimede taken, geen sleep in de body – duikt overal op waar hardwarecode gaat: software-debouncing van schakelaars, motorsequencing, UART-leestimeouts. Dezelfde drie functies (time.ticks_ms(), time.ticks_diff(), time.ticks_add()) dekken elk geval.