time — zeitbezogene Funktionen

Das time-Modul stellt Funktionen bereit, um die aktuelle Uhrzeit und das Datum abzurufen, Zeitintervalle zu messen und Verzögerungen zu erzeugen.

Zeit-Epoche: Die Alif- und i.MX RT-basierten OpenMV Cams verwenden die POSIX-Epoche von 1970-01-01 00:00:00 UTC. Die STM32-basierten OpenMV Cams verwenden eine Epoche von 2000-01-01 00:00:00 UTC. Das Jahr der Epoche kann zur Laufzeit mit gmtime(0)[0] ermittelt werden.

Beibehalten des tatsächlichen Kalenderdatums/der Uhrzeit: Dies erfordert eine Echtzeituhr (RTC). Auf der OpenMV Cam wird die Systemzeit vom machine.RTC-Objekt bereitgestellt. Die aktuelle Kalenderzeit kann mit machine.RTC().datetime(tuple) gesetzt werden und wird durch eines der folgenden Mittel aufrechterhalten:

  • Eine Pufferbatterie (eine optionale Komponente bei einigen OpenMV Cams).

  • Ein vernetztes Zeitprotokoll wie ntptime (erfordert eine Netzwerkverbindung).

  • Manuelles Setzen bei jedem Einschalten. Die RTC wird dann typischerweise über Soft-Resets hinweg beibehalten, geht jedoch bei Stromausfall verloren, sofern keine Pufferbatterie eingebaut ist.

Wenn die Kalenderzeit nicht aufrechterhalten wird, verhalten sich die nachstehenden Funktionen, die auf die aktuelle absolute Zeit verweisen, nicht wie erwartet.

Funktionen

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]

Wandelt die in Sekunden seit der Epoche (siehe oben) ausgedrückte Zeit secs in ein 8-Tupel um, das Folgendes enthält: (year, month, mday, hour, minute, second, weekday, yearday) Wird secs nicht angegeben oder ist None, wird die aktuelle Zeit aus der RTC verwendet.

Die Funktion gmtime() gibt ein Datum-Zeit-Tupel in UTC zurück, und localtime() gibt ein Datum-Zeit-Tupel in Ortszeit zurück.

Das Format der Einträge im 8-Tupel ist:

  • year enthält das Jahrhundert (zum Beispiel 2014).

  • month ist 1-12

  • mday ist 1-31

  • hour ist 0-23

  • minute ist 0-59

  • second ist 0-59

  • weekday ist 0-6 für Mo-So

  • yearday ist 1-366

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

Dies ist die Umkehrfunktion von localtime. Ihr Argument ist ein vollständiges 8-Tupel, das eine Zeit wie bei localtime ausdrückt. Sie gibt eine Ganzzahl zurück, die die Anzahl der Sekunden seit der Zeit-Epoche ist.

time.sleep(seconds: float) None

Schläft für die angegebene Anzahl von Sekunden. seconds kann eine Gleitkommazahl sein, um für eine Bruchteilzahl von Sekunden zu schlafen. Für feinere oder rein ganzzahlige Verzögerungen verwenden Sie die Funktionen sleep_ms() und sleep_us().

Der Aufruf von sleep(), einschließlich sleep(0), ruft garantiert ausstehende Callback-Funktionen auf.

time.sleep_ms(ms: int) None

Verzögert um die angegebene Anzahl von Millisekunden, die positiv oder 0 sein sollte.

Diese Funktion verzögert um mindestens die angegebene Anzahl von Millisekunden, kann aber länger dauern, wenn andere Verarbeitung stattfinden muss, zum Beispiel Interrupt-Handler oder andere Threads. Die Übergabe von 0 für ms lässt diese andere Verarbeitung dennoch zu. Verwenden Sie sleep_us() für präzisere Verzögerungen.

Der Aufruf von sleep_ms(), einschließlich sleep_ms(0), ruft garantiert ausstehende Callback-Funktionen auf.

time.sleep_us(us: int) None

Verzögert um die angegebene Anzahl von Mikrosekunden, die positiv oder 0 sein sollte.

Diese Funktion versucht, eine genaue Verzögerung von mindestens us Mikrosekunden zu bieten, sie kann jedoch länger dauern, wenn das System andere Verarbeitung mit höherer Priorität durchführen muss.

time.ticks_ms() int

Gibt einen steigenden Millisekundenzähler mit einem beliebigen Bezugspunkt zurück, der nach einem bestimmten Wert wieder überläuft.

Der Überlaufwert wird nicht explizit offengelegt, aber wir werden ihn zur Vereinfachung der Diskussion als TICKS_MAX bezeichnen. Die Periode der Werte ist TICKS_PERIOD = TICKS_MAX + 1. TICKS_PERIOD ist garantiert eine Zweierpotenz, kann aber ansonsten von Port zu Port unterschiedlich sein. Derselbe Periodenwert wird für alle Funktionen ticks_ms(), ticks_us(), ticks_cpu() verwendet (zur Vereinfachung). Daher geben diese Funktionen einen Wert im Bereich [0 .. TICKS_MAX] zurück, einschließlich, insgesamt TICKS_PERIOD Werte. Beachten Sie, dass nur nicht-negative Werte verwendet werden. Größtenteils sollten Sie die von diesen Funktionen zurückgegebenen Werte als undurchsichtig behandeln. Die einzigen für sie verfügbaren Operationen sind die nachstehend beschriebenen Funktionen ticks_diff() und ticks_add().

Hinweis: Das Durchführen von standardmäßigen mathematischen Operationen (+, -) oder Vergleichsoperatoren (<, <=, >, >=) direkt auf diesen Werten führt zu einem ungültigen Ergebnis. Das Durchführen mathematischer Operationen und das anschließende Übergeben ihrer Ergebnisse als Argumente an ticks_diff() oder ticks_add() führt ebenfalls zu ungültigen Ergebnissen der letzteren Funktionen.

time.ticks_us() int

Genau wie ticks_ms() oben, aber in Mikrosekunden.

time.ticks_cpu() int

Ähnlich wie ticks_ms() und ticks_us(), aber mit der höchstmöglichen Auflösung im System. Dies sind in der Regel CPU-Takte, und deshalb ist die Funktion so benannt. Es muss jedoch kein CPU-Takt sein, stattdessen kann eine andere im System verfügbare Zeitquelle (z. B. ein hochauflösender Timer) verwendet werden. Die genaue Zeiteinheit (Auflösung) dieser Funktion ist auf Ebene des time-Moduls nicht festgelegt, aber die Dokumentation für einen bestimmten Port kann genauere Informationen liefern. Diese Funktion ist für sehr feines Benchmarking oder sehr enge Echtzeitschleifen gedacht. Vermeiden Sie ihre Verwendung in portablem Code. Sie ist auf allen OpenMV Cams verfügbar.

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

Verschiebt einen Ticks-Wert um eine angegebene Zahl, die entweder positiv oder negativ sein kann. Bei gegebenem ticks-Wert ermöglicht diese Funktion die Berechnung des Ticks-Werts delta Ticks davor oder danach, gemäß der modular-arithmetischen Definition von Tick-Werten (siehe ticks_ms() oben). Der Parameter ticks muss ein direktes Ergebnis eines Aufrufs der Funktionen ticks_ms(), ticks_us() oder ticks_cpu() sein (oder aus einem vorherigen Aufruf von ticks_add()). delta kann jedoch eine beliebige Ganzzahl oder ein numerischer Ausdruck sein. ticks_add() ist nützlich zur Berechnung von Deadlines für Ereignisse/Aufgaben. (Hinweis: Sie müssen die Funktion ticks_diff() verwenden, um mit Deadlines zu arbeiten.)

Beispiele:

# 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

Misst die Ticks-Differenz zwischen den von den Funktionen ticks_ms(), ticks_us() oder ticks_cpu() zurückgegebenen Werten als vorzeichenbehafteten Wert, der überlaufen kann.

Die Argumentreihenfolge ist dieselbe wie beim Subtraktionsoperator, ticks_diff(ticks1, ticks2) hat dieselbe Bedeutung wie ticks1 - ticks2. Allerdings können die von Funktionen wie ticks_ms() usw. zurückgegebenen Werte überlaufen, sodass die direkte Verwendung der Subtraktion auf ihnen ein falsches Ergebnis liefert. Deshalb wird ticks_diff() benötigt; es implementiert modulare (oder genauer gesagt Ring-)Arithmetik, um auch für überlaufende Werte ein korrektes Ergebnis zu erzeugen (sofern sie nicht zu weit voneinander entfernt sind, siehe unten). Die Funktion gibt einen vorzeichenbehafteten Wert im Bereich [-TICKS_PERIOD/2 .. TICKS_PERIOD/2-1] zurück (das ist eine typische Bereichsdefinition für Zweierkomplement-vorzeichenbehaftete Binärzahlen). Ist das Ergebnis negativ, bedeutet dies, dass ticks1 zeitlich früher auftrat als ticks2. Andernfalls bedeutet es, dass ticks1 nach ticks2 auftrat. Dies gilt nur, wenn ticks1 und ticks2 nicht mehr als TICKS_PERIOD/2-1 Ticks voneinander entfernt sind. Wenn dies nicht zutrifft, wird ein falsches Ergebnis zurückgegeben. Genauer gesagt, wenn zwei Tick-Werte TICKS_PERIOD/2-1 Ticks voneinander entfernt sind, wird dieser Wert von der Funktion zurückgegeben. Wenn jedoch TICKS_PERIOD/2 an Echtzeit-Ticks zwischen ihnen vergangen sind, gibt die Funktion stattdessen -TICKS_PERIOD/2 zurück, d. h. der Ergebniswert läuft in den negativen Bereich der möglichen Werte über.

Informelle Begründung der obigen Einschränkungen: Angenommen, Sie sind in einem Raum eingesperrt, ohne eine Möglichkeit, das Vergehen der Zeit zu überwachen, außer einer standardmäßigen Uhr mit 12 Kerben. Wenn Sie nun jetzt auf das Zifferblatt schauen und dann weitere 13 Stunden lang nicht erneut hinschauen (z. B. wenn Sie in einen langen Schlaf fallen), kann es Ihnen, wenn Sie schließlich wieder hinschauen, so vorkommen, als sei nur 1 Stunde vergangen. Um diesen Fehler zu vermeiden, schauen Sie einfach regelmäßig auf die Uhr. Ihre Anwendung sollte dasselbe tun. Die Metapher des „zu langen Schlafs“ überträgt sich auch direkt auf das Anwendungsverhalten: Lassen Sie Ihre Anwendung keine einzelne Aufgabe zu lange ausführen. Führen Sie Aufgaben in Schritten aus und nehmen Sie dazwischen Zeitmessungen vor.

ticks_diff() ist darauf ausgelegt, verschiedene Nutzungsmuster zu unterstützen, darunter:

  • Polling mit Timeout. In diesem Fall ist die Reihenfolge der Ereignisse bekannt, und Sie haben es nur mit positiven Ergebnissen von ticks_diff() zu tun:

    # 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
    
  • Planen von Ereignissen. In diesem Fall kann das Ergebnis von ticks_diff() negativ sein, wenn ein Ereignis überfällig ist:

    # 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)
    

Hinweis: Übergeben Sie keine time()-Werte an ticks_diff(), Sie sollten normale mathematische Operationen auf ihnen verwenden. Beachten Sie aber, dass time() ebenfalls überlaufen kann (und wird). Dies ist als https://en.wikipedia.org/wiki/Year_2038_problem bekannt.

time.time() int

Gibt die Anzahl der Sekunden seit der Epoche als Ganzzahl zurück, vorausgesetzt, die zugrunde liegende RTC ist wie oben beschrieben gesetzt und wird aufrechterhalten. Wenn keine RTC gesetzt ist, gibt diese Funktion die Anzahl der Sekunden seit einem port-spezifischen Bezugszeitpunkt zurück (bei eingebetteten Boards ohne batteriegepufferte RTC üblicherweise seit dem Einschalten oder Zurücksetzen). Wenn Sie eine portable MicroPython-Anwendung entwickeln möchten, sollten Sie sich nicht darauf verlassen, dass diese Funktion eine höhere als sekundengenaue Präzision bietet. Wenn Sie höhere Präzision und absolute Zeitstempel benötigen, verwenden Sie time_ns(). Sind relative Zeiten akzeptabel, verwenden Sie die Funktionen ticks_ms() und ticks_us(). Wenn Sie Kalenderzeit benötigen, ist gmtime() oder localtime() ohne Argument die bessere Wahl.

Unterschied zu CPython

In CPython gibt diese Funktion die Anzahl der Sekunden seit der Unix-Epoche (1970-01-01 00:00 UTC) als Gleitkommawert zurück, üblicherweise mit Mikrosekundenpräzision. Auf der OpenMV Cam gibt sie eine Ganzzahl mit Sekundenpräzision zurück – die Hardware kann nicht gleichzeitig einen langen Zeitbereich und Subsekundenpräzision in einem Float darstellen – und die Epoche unterscheidet sich je nach Board (siehe Zeit-Epoche oben). Ohne eine gesetzte batteriegepufferte RTC zählt sie stattdessen die Sekunden seit dem Einschalten/Zurücksetzen.

time.time_ns() int

Ähnlich wie time(), gibt aber Nanosekunden seit der Epoche als Ganzzahl zurück (üblicherweise eine große Ganzzahl, allokiert also auf dem Heap).

Konstruktoren

class time.clock

Gibt ein Clock-Objekt zurück.

Methoden

tick() None

Beginnt mit der Verfolgung der verstrichenen Zeit.

fps() float

Stoppt die Verfolgung der verstrichenen Zeit und gibt die aktuelle FPS (Bilder pro Sekunde) zurück.

Rufen Sie immer zuerst tick auf, bevor Sie diese Funktion aufrufen.

avg() float

Stoppt die Verfolgung der verstrichenen Zeit und gibt die aktuelle durchschnittliche verstrichene Zeit in Millisekunden zurück.

Rufen Sie immer zuerst tick auf, bevor Sie diese Funktion aufrufen.

reset() None

Setzt das Clock-Objekt zurück.