arduino
Zeiteinteilung
Suche…
Syntax
unsignierte lange Millis ()
unsignierte lange micros ()
Leere Verzögerung (unsignierte lange Millisekunden)
void delayMicroseconds (unsignierte lange Mikrosekunden)
Konstruktoren und Operatoren dieser Klasse finden Sie im elapsedMillis-Header . Zusamenfassend:
- elapsedMillis elapsedMillisObject; erstellt ein Objekt, um die Zeit nach der Erstellung oder seit einem anderen explizit festgelegten Zeitpunkt zu verfolgen
- elapsedMillisObject = 0; setzt die vom Objekt verfolgte Zeit auf "seit jetzt" zurück
- unsigned long deltaT = elapsedMillisObject; Lasst uns die verfolgte Zeit betrachten
- elapsedMillisObject + = und - = diese funktionieren wie erwartet
Bemerkungen
Blockierung vs. nicht blockierender Code
Für sehr einfache Skizzen kann das Schreiben von Blockierungscode mit delay()
und delayMicroseconds()
sinnvoll sein. Wenn die Dinge komplexer werden, kann die Verwendung dieser Funktionen einige Nachteile haben. Einige davon sind:
- Verschwenden von CPU-Zeit: Komplexere Skizzen benötigen möglicherweise die CPU für etwas anderes, während auf das Blinken einer LED gewartet wird.
- Unerwartete Verzögerungen: Wenn
delay()
in Subroutinen aufgerufen wird, die nicht offensichtlich aufgerufen werden, z. B. in von Ihnen eingeschlossenen Bibliotheken. - Fehlende Ereignisse, die während der Verzögerung auftreten und nicht von einem Interrupt-Handler behandelt werden, z. B. das Abfragen von abgefragten Knöpfen: Eine Taste wird möglicherweise für 100 ms gedrückt, dies kann jedoch durch eine
delay(500)
abgeschattet werden.
Implementierungsdetails
millis()
normalerweise auf einem Hardware-Timer, der mit einer Geschwindigkeit von weit über 1 kHz läuft. Wenn millis()
aufgerufen wird, gibt die Implementierung einen Wert zurück, aber Sie wissen nicht, wie alt dieser tatsächlich ist. Es ist möglich, dass die "aktuelle" Millisekunde gerade begonnen hat oder direkt nach dem Funktionsaufruf endet. Das bedeutet, dass Sie bei der Berechnung der Differenz zwischen zwei Ergebnissen von millis()
um fast null bis fast eine Millisekunde millis()
können. Verwenden Sie micros()
wenn eine höhere Genauigkeit erforderlich ist.
Ein Blick in den Quellcode von elapsedMillis
zeigt, dass millis()
intern verwendet wird, um zwei Zeitpunkte zu vergleichen, so dass auch dieser Effekt darunter leidet. Wieder gibt es die Alternative elapsedMicros
für höhere Präzision aus derselben Bibliothek.
Blinky mit Verzögerung blockieren ()
Eine der einfachsten Methoden, um eine LED zum Blinken zu bringen, besteht darin, sie einzuschalten, etwas zu warten, auszuschalten, erneut zu warten und endlos zu wiederholen:
// set constants for blinking the built-in LED at 1 Hz
#define OUTPIN LED_BUILTIN
#define PERIOD 500
void setup()
{
pinMode(OUTPIN, OUTPUT); // sets the digital pin as output
}
void loop()
{
digitalWrite(OUTPIN, HIGH); // sets the pin on
delayMicroseconds(PERIOD); // pauses for 500 miliseconds
digitalWrite(OUTPIN, LOW); // sets the pin off
delayMicroseconds(PERIOD); // pauses for 500 milliseconds
// doing other time-consuming stuff here will skew the blinking
}
Durch das Warten wie im obigen Beispiel werden jedoch CPU-Zyklen verschwendet, da es nur in einer Schleife sitzt und auf einen bestimmten Zeitpunkt wartet, um vorbeizugehen. Das ist es, was die nicht blockierenden Methoden mit millis()
oder elapsedMillis
besser machen - in dem Sinne, dass sie nicht so viel von den Fähigkeiten der Hardware brennen.
Nicht blockierendes Blinky mit der elapsedMillis-Bibliothek (und Klasse)
Die Bibliothek elapsedMillis stellt eine Klasse mit demselben Namen zur Verfügung, die die Zeit seit ihrer Erstellung oder einen bestimmten Wert verfolgt:
#include <elapsedMillis.h>
#define OUTPIN LED_BUILTIN
#define PERIOD 500
elapsedMillis ledTime;
bool ledState = false;
void setup()
{
// initialize the digital pin as an output.
pinMode(OUTPIN, OUTPUT);
}
void loop()
{
if (ledTime >= PERIOD)
{
ledState = !ledState;
digitalWrite(OUTPIN, ledState);
ledTime = 0;
}
// do other stuff here
}
Sie können im Beispiel sehen, dass das ledTime
Objekt null ist, wenn der LED-Pin umgeschaltet wurde. Das mag auf den ersten Blick nicht überraschend sein, wirkt sich jedoch aus, wenn zeitaufwendigere Dinge passieren:
ledTime
Sie sich eine Situation vor, in der der Vergleich zwischen ledTime
und PERIOD
nach 750 Millisekunden erfolgt. ledTime
auf Null setzen, bedeutet dies, dass alle folgenden Umschaltoperationen 250 ms "verspätet" sind. Wenn dagegen PERIOD
von ledTime
abgezogen wurde, würde die LED eine kurze Zeit sehen und dann weiter blinken, als ob nichts passiert wäre.
Nicht blockierendes Blinzeln mit Millis ()
Dies ist sehr nahe an einem Beispiel aus den Arduino-Dokumenten :
// set constants for blinking the built-in LED at 1 Hz
#define OUTPIN LED_BUILTIN
#define PERIOD 500 // this is in milliseconds
int ledState = LOW;
// millis() returns an unsigned long so we'll use that to keep track of time
unsigned long lastTime = 0;
void setup() {
// set the digital pin as output:
pinMode(OUTPIN, OUTPUT);
}
void loop() {
unsigned long now = millis();
if (now - lastTime >= PERIOD) // this will be true every PERIOD milliseconds
{
lastTime = now;
if (ledState == LOW)
{
ledState = HIGH;
}
else
{
ledState = LOW;
}
digitalWrite(OUTPIN, ledState);
}
// now there's lots of time to do other stuff here
}
Die Verwendung von millis()
auf diese Weise - um millis()
auf eine nicht blockierende Weise elapsedMillis
- ist ziemlich häufig erforderlich. elapsedMillis
die elapsedMillis
Bibliothek in Betracht elapsedMillis
.
Messen Sie, wie lange etwas gedauert hat, mit elapsedMillis und elapsedMicros
#include <elapsedMillis.h>
void setup() {
Serial.begin(115200);
elapsedMillis msTimer;
elapsedMicros usTimer;
long int dt = 500;
delay(dt);
long int us = usTimer;
long int ms = msTimer;
Serial.print("delay(");Serial.print(dt);Serial.println(") took");
Serial.print(us);Serial.println(" us, or");
Serial.print(ms);Serial.println(" ms");
}
void loop() {
}
In diesem Beispiel werden ein elapsedMillis
Objekt und ein elapsedMicros
Objekt verwendet, um zu messen, wie lange etwas elapsedMicros
hat, indem es erstellt wird, bevor der gewünschte Ausdruck ausgeführt wird, und danach die entsprechenden Werte abgerufen werden. Sie werden etwas andere Ergebnisse zeigen, aber das Millisekundenergebnis wird nicht länger als eine Millisekunde sein.
Mehr als 1 Aufgabe ohne Verzögerung ()
Wenn Sie mehr als eine Aufgabe haben, die wiederholt in unterschiedlichen Intervallen ausgeführt werden soll, verwenden Sie dieses Beispiel als Ausgangspunkt:
unsigned long intervals[] = {250,2000}; //this defines the interval for each task in milliseconds
unsigned long last[] = {0,0}; //this records the last executed time for each task
void setup() {
pinMode(LED_BUILTIN, OUTPUT); //set the built-it led pin as output
Serial.begin(115200); //initialize serial
}
void loop() {
unsigned long now = millis();
if(now-last[0]>=intervals[0]){ last[0]=now; firstTask(); }
if(now-last[1]>=intervals[1]){ last[1]=now; secondTask(); }
//do other things here
}
void firstTask(){
//let's toggle the built-in led
digitalWrite(LED_BUILTIN, digitalRead(LED_BUILTIN)?0:1);
}
void secondTask(){
//say hello
Serial.println("hello from secondTask()");
}
Um eine weitere Aufgabe hinzufügen alle 15 Sekunden ausgeführt werden , erweitern die Variablen intervals
und last
:
unsigned long intervals[] = {250,2000,15000};
unsigned long last[] = {0,0,0};
Fügen Sie dann eine if
Anweisung hinzu, um die neue Aufgabe auszuführen. In diesem Beispiel habe ich thirdTask
.
if(now-last[2]>=intervals[2]){ last[2]=now; thirdTask(); }
Zum Schluss deklarieren Sie die Funktion:
void thirdTask(){
//your code here
}