Es gibt eine wichtige Sache, an die Sie denken müssen, wenn Sie mit der Zeit an einem Arudino jeglicher Form arbeiten:
- Jede Operation braucht Zeit.
Ihre Funktion foo () wird einige Zeit in Anspruch nehmen. Was diese Zeit ist, können wir nicht sagen.
Der zuverlässigste Weg, mit der Zeit umzugehen, besteht darin, sich nur auf die Zeit für das Auslösen zu verlassen und nicht darauf, wann die nächste Auslösung erfolgen sollte.
Nehmen Sie zum Beispiel Folgendes:
if (millis() - last > interval) {
doSomething();
last = millis();
}
Die Variable last
ist die Zeit, die die Routine ausgelöst hat * plus die Zeit, doSomething
die zum Ausführen benötigt wurde. Angenommen, es interval
ist 100, und doSomething
die Ausführung dauert 10 ms. Sie erhalten Auslösungen bei 101 ms, 212 ms, 323 ms usw. Nicht die erwarteten 100 ms.
Eine Sache, die Sie tun können, ist, immer dieselbe Zeit zu verwenden, unabhängig davon, indem Sie sich an einen bestimmten Punkt erinnern (wie Juraj vorschlägt):
uint32_t time = millis();
if (time - last > interval) {
doSomething();
last = time;
}
Jetzt hat die Zeit, die doSomething()
benötigt wird, keine Auswirkung auf irgendetwas. Sie erhalten also Auslösungen bei 101 ms, 202 ms, 303 ms usw. Immer noch nicht ganz die 100 ms, die Sie wollten - weil Sie nach mehr als 100 ms suchen, die vergangen sind - und das bedeutet 101 ms oder mehr. Stattdessen sollten Sie verwenden >=
:
uint32_t time = millis();
if (time - last >= interval) {
doSomething();
last = time;
}
Angenommen, in Ihrer Schleife passiert nichts anderes, erhalten Sie Auslösungen bei 100 ms, 200 ms, 300 ms usw. Beachten Sie jedoch das Bit: "Solange in Ihrer Schleife nichts anderes passiert" ...
Was passiert, wenn eine Operation, die 5 ms dauert, bei 99 ms stattfindet ...? Ihre nächste Auslösung wird auf 104 ms verzögert. Das ist ein Drift. Aber es ist leicht zu bekämpfen. Anstatt zu sagen "Die aufgezeichnete Zeit ist jetzt", sagen Sie "Die aufgezeichnete Zeit ist 100 ms später als sie war". Das bedeutet, dass unabhängig von den Verzögerungen, die Sie in Ihrem Code erhalten, Ihre Auslösung immer in Intervallen von 100 ms erfolgt oder innerhalb eines Ticks von 100 ms driftet.
if (millis() - last >= interval) {
doSomething();
last += interval;
}
Jetzt erhalten Sie Auslösungen bei 100 ms, 200 ms, 300 ms usw. Oder wenn es Verzögerungen bei anderen Codebits gibt, erhalten Sie möglicherweise 100 ms, 204 ms, 300 ms, 408 ms, 503 ms, 600 ms usw. Es wird immer versucht, sie so nahe wie möglich auszuführen das Intervall wie möglich unabhängig von Verzögerungen. Und wenn Sie Verzögerungen haben, die größer als das Intervall sind, wird Ihre Routine automatisch so oft ausgeführt, dass Sie die aktuelle Zeit einholen können.
Bevor du driftest . Jetzt hast du Jitter .