time — tidsrelaterade funktioner

Modulen time tillhandahåller funktioner för att hämta aktuell tid och datum, mäta tidsintervall och för fördröjningar.

Tidsepok: De Alif- och i.MX RT-baserade OpenMV Cams använder POSIX-epoken 1970-01-01 00:00:00 UTC. De STM32-baserade OpenMV Cams använder en epok på 2000-01-01 00:00:00 UTC. Epokåret kan bestämmas vid körning med gmtime(0)[0].

Upprätthålla faktiskt kalenderdatum/-tid: Detta kräver en realtidsklocka (RTC). På OpenMV Cam tillhandahålls systemtiden av objektet machine.RTC. Den aktuella kalendertiden kan ställas in med machine.RTC().datetime(tuple) och upprätthålls av en av följande:

  • Ett backup-batteri (en valfri komponent på vissa OpenMV Cams).

  • Ett nätverksbaserat tidsprotokoll såsom ntptime (kräver en nätverksanslutning).

  • Manuell inställning vid varje uppstart. RTC:n bibehålls då vanligtvis över mjuka omstarter, men går förlorad vid strömavbrott om inte ett backup-batteri är monterat.

Om kalendertiden inte upprätthålls kommer funktionerna nedan som refererar till den aktuella absoluta tiden inte att bete sig som förväntat.

Funktioner

time.gmtime(secs: int | None = None) Tuple[int, int, int, int, int, int, int, int]
time.localtime(secs: int | None = None) Tuple[int, int, int, int, int, int, int, int]

Konverterar tiden secs, uttryckt i sekunder sedan epoken (se ovan), till en 8-tupel som innehåller: (year, month, mday, hour, minute, second, weekday, yearday) Om secs inte anges eller är None används den aktuella tiden från RTC:n.

Funktionen gmtime() returnerar en datum-tid-tupel i UTC, och localtime() returnerar en datum-tid-tupel i lokal tid.

Formatet på posterna i 8-tupeln är:

  • year inkluderar århundradet (till exempel 2014).

  • month är 1-12

  • mday är 1-31

  • hour är 0-23

  • minute är 0-59

  • second är 0-59

  • weekday är 0-6 för mån-sön

  • yearday är 1-366

time.mktime(date_time_tuple: Tuple[int, int, int, int, int, int, int, int]) int

Detta är inversfunktionen till localtime. Dess argument är en fullständig 8-tupel som uttrycker en tid enligt localtime. Den returnerar ett heltal som är antalet sekunder sedan tidsepoken.

time.sleep(seconds: float) None

Sover i det angivna antalet sekunder. seconds kan vara ett flyttal, för att sova ett bråkdelsantal sekunder. För finkornigare eller heltalsbaserade fördröjningar, använd funktionerna sleep_ms() och sleep_us().

Anrop av sleep(), inklusive sleep(0), garanteras anropa väntande återanropsfunktioner.

time.sleep_ms(ms: int) None

Fördröjer i det angivna antalet millisekunder, ska vara positivt eller 0.

Denna funktion fördröjer i minst det angivna antalet millisekunder, men kan ta längre tid om annan bearbetning måste ske, till exempel avbrottshanterare eller andra trådar. Att ange 0 för ms tillåter ändå att denna andra bearbetning sker. Använd sleep_us() för mer precisa fördröjningar.

Anrop av sleep_ms(), inklusive sleep_ms(0), garanteras anropa väntande återanropsfunktioner.

time.sleep_us(us: int) None

Fördröjer i det angivna antalet mikrosekunder, ska vara positivt eller 0.

Denna funktion försöker tillhandahålla en exakt fördröjning på minst us mikrosekunder, men det kan ta längre tid om systemet har annan bearbetning med högre prioritet att utföra.

time.ticks_ms() int

Returnerar en stigande millisekundsräknare med en godtycklig referenspunkt, som slår runt efter ett visst värde.

Värdet vid runtslagning exponeras inte explicit, men vi kommer att referera till det som TICKS_MAX för att förenkla diskussionen. Periodlängden för värdena är TICKS_PERIOD = TICKS_MAX + 1. TICKS_PERIOD garanteras vara en tvåpotens, men kan i övrigt skilja sig från port till port. Samma periodvärde används för alla funktionerna ticks_ms(), ticks_us() och ticks_cpu() (för enkelhets skull). Således returnerar dessa funktioner ett värde i intervallet [0 .. TICKS_MAX], inklusive ändpunkterna, totalt TICKS_PERIOD värden. Observera att endast icke-negativa värden används. För det mesta bör du behandla värdena som returneras av dessa funktioner som ogenomskinliga. De enda tillgängliga operationerna för dem är funktionerna ticks_diff() och ticks_add() som beskrivs nedan.

Obs: Att utföra vanliga matematiska operationer (+, -) eller relationsoperatorer (<, <=, >, >=) direkt på dessa värden leder till ogiltigt resultat. Att utföra matematiska operationer och sedan skicka deras resultat som argument till ticks_diff() eller ticks_add() leder också till ogiltiga resultat från de senare funktionerna.

time.ticks_us() int

Precis som ticks_ms() ovan, men i mikrosekunder.

time.ticks_cpu() int

Liknar ticks_ms() och ticks_us(), men med högsta möjliga upplösning i systemet. Detta är vanligtvis CPU-klockor, och det är därför funktionen heter så. Men det behöver inte vara en CPU-klocka; någon annan tidskälla som finns i ett system (t.ex. en högupplösningstimer) kan användas i stället. Den exakta tidsenheten (upplösningen) för denna funktion specificeras inte på time-modulnivå, men dokumentationen för en specifik port kan ge mer specifik information. Denna funktion är avsedd för mycket finkornig benchmarking eller mycket snäva realtidsloopar. Undvik att använda den i portabel kod. Den är tillgänglig på alla OpenMV Cams.

time.ticks_add(ticks: int, delta: int) int

Förskjuter ett ticks-värde med ett givet antal, som kan vara antingen positivt eller negativt. Givet ett ticks-värde låter denna funktion dig beräkna ett ticks-värde delta ticks före eller efter det, enligt den modulär-aritmetiska definitionen av tick-värden (se ticks_ms() ovan). Parametern ticks måste vara ett direkt resultat av ett anrop till funktionerna ticks_ms(), ticks_us() eller ticks_cpu() (eller från ett tidigare anrop till ticks_add()). Däremot kan delta vara ett godtyckligt heltal eller numeriskt uttryck. ticks_add() är användbar för att beräkna tidsfrister för händelser/uppgifter. (Obs: du måste använda funktionen ticks_diff() för att arbeta med tidsfrister.)

Exempel:

# Find out what ticks value there was 100ms ago
print(ticks_add(time.ticks_ms(), -100))

# Calculate deadline for operation and test for it
deadline = ticks_add(time.ticks_ms(), 200)
while ticks_diff(deadline, time.ticks_ms()) > 0:
    do_a_little_of_something()

# Find out TICKS_MAX used by this port
print(ticks_add(0, -1))
time.ticks_diff(ticks1: int, ticks2: int) int

Mäter ticks-skillnaden mellan värden returnerade från funktionerna ticks_ms(), ticks_us() eller ticks_cpu(), som ett tecknat värde som kan slå runt.

Argumentordningen är densamma som för subtraktionsoperatorn; ticks_diff(ticks1, ticks2) har samma betydelse som ticks1 - ticks2. Värden som returneras av funktionerna ticks_ms() osv. kan dock slå runt, så att direkt använda subtraktion på dem ger felaktigt resultat. Det är därför ticks_diff() behövs; den implementerar modulär (eller mer specifikt ring-) aritmetik för att ge korrekt resultat även för värden som slår runt (så länge de inte är alltför långt ifrån varandra, se nedan). Funktionen returnerar ett tecknat värde i intervallet [-TICKS_PERIOD/2 .. TICKS_PERIOD/2-1] (det är en typisk intervalldefinition för tecknade binära heltal i tvåkomplement). Om resultatet är negativt betyder det att ticks1 inträffade tidigare i tiden än ticks2. Annars betyder det att ticks1 inträffade efter ticks2. Detta gäller endast om ticks1 och ticks2 är åtskilda med högst TICKS_PERIOD/2-1 ticks. Om så inte är fallet returneras ett felaktigt resultat. Specifikt, om två tick-värden är åtskilda med TICKS_PERIOD/2-1 ticks returneras det värdet av funktionen. Men om TICKS_PERIOD/2 realtids-ticks har förflutit mellan dem returnerar funktionen i stället -TICKS_PERIOD/2, dvs. resultatvärdet slår runt till det negativa intervallet av möjliga värden.

Informell motivering av begränsningarna ovan: Anta att du är inlåst i ett rum utan möjlighet att övervaka tidens gång annat än med en vanlig 12-stegs klocka. Om du tittar på urtavlan nu och inte tittar igen på 13 timmar (t.ex. om du faller i en lång sömn), kan det när du till slut tittar igen verka som om bara 1 timme har gått. För att undvika detta misstag, titta bara på klockan regelbundet. Din applikation bör göra detsamma. Metaforen ”för lång sömn” mappar också direkt mot applikationsbeteende: låt inte din applikation köra någon enskild uppgift för länge. Kör uppgifter i steg och håll koll på tiden däremellan.

ticks_diff() är utformad för att rymma olika användningsmönster, bland dem:

  • Avläsning med tidsgräns (timeout). I detta fall är ordningen på händelserna känd, och du kommer endast att hantera positiva resultat från ticks_diff()

    # Wait for GPIO pin to be asserted, but at most 500us
    start = time.ticks_us()
    while pin.value() == 0:
        if time.ticks_diff(time.ticks_us(), start) > 500:
            raise TimeoutError
    
  • Schemaläggning av händelser. I detta fall kan resultatet från ticks_diff() vara negativt om en händelse är försenad:

    # This code snippet is not optimized
    now = time.ticks_ms()
    scheduled_time = task.scheduled_time()
    if ticks_diff(scheduled_time, now) > 0:
        print("Too early, let's nap")
        sleep_ms(ticks_diff(scheduled_time, now))
        task.run()
    elif ticks_diff(scheduled_time, now) == 0:
        print("Right at time!")
        task.run()
    elif ticks_diff(scheduled_time, now) < 0:
        print("Oops, running late, tell task to run faster!")
        task.run(run_faster=true)
    

Obs: Skicka inte time()-värden till ticks_diff(); du bör använda vanliga matematiska operationer på dem. Men observera att time() också kan (och kommer att) svämma över. Detta är känt som https://en.wikipedia.org/wiki/Year_2038_problem .

time.time() int

Returnerar antalet sekunder, som ett heltal, sedan epoken, förutsatt att den underliggande RTC:n är inställd och upprätthålls enligt beskrivningen ovan. Om en RTC inte är inställd returnerar denna funktion antalet sekunder sedan en portspecifik referenspunkt i tiden (för inbäddade kort utan batteribackad RTC vanligtvis sedan uppstart eller omstart). Om du vill utveckla en portabel MicroPython-applikation bör du inte förlita dig på att denna funktion ger högre precision än sekund. Om du behöver högre precision, använd absoluta tidsstämplar med time_ns(). Om relativa tider är acceptabla, använd funktionerna ticks_ms() och ticks_us(). Om du behöver kalendertid är gmtime() eller localtime() utan argument ett bättre val.

Skillnad mot CPython

I CPython returnerar denna funktion antalet sekunder sedan Unix-epoken (1970-01-01 00:00 UTC) som ett flyttal, vanligtvis med mikrosekundsprecision. På OpenMV Cam returnerar den ett heltal med ensekundsprecision – hårdvaran kan inte representera både ett långt tidsintervall och precision under en sekund i ett flyttal – och epoken skiljer sig åt mellan kort (se Tidsepok ovan). Utan en batteribackad RTC som har ställts in räknar den i stället sekunder sedan uppstart/omstart.

time.time_ns() int

Liknar time() men returnerar nanosekunder sedan epoken, som ett heltal (vanligtvis ett stort heltal, så det allokeras på heapen).

Konstruktorer

class time.clock

Returnerar ett klockobjekt.

Metoder

tick() None

Börjar spåra förfluten tid.

fps() float

Slutar spåra den förflutna tiden och returnerar aktuell FPS (bildrutor per sekund).

Anropa alltid tick först innan denna funktion anropas.

avg() float

Slutar spåra den förflutna tiden och returnerar den aktuella genomsnittliga förflutna tiden i millisekunder.

Anropa alltid tick först innan denna funktion anropas.

reset() None

Återställer klockobjektet.