Steuern zeitkritischer Aufgaben oder Multitasking
Bisher wurde nur die delay()
Funktion, welche den Programmablauf für die angegebene Zeit unterbricht, zum Steuern zeitkritischer Aufgaben verwendet. Hierbei handelt es sich um eine blockierende Funktion, da der Mikrocontroller während der Programmverzögerung keine anderen Aufgaben ausführen kann.
millis()
Eine bessere Möglichkeit zur Steuerung von zeitlichen Abläufen ergibt sich mit der millis()
Methode, welche die (vergangene) Zeit seit dem Programmstart angibt.
Durch den Aufruf der folgenden Zeilen ist es möglich, die seit dem Start des Arduinos vergangene Zeit in Millisekunden zu bestimmen.
long aktuelleZeit; // Variable vom Typ long (32 bit)
aktuelleZeit = millis(); // seit dem Start vergangene Zeit in Millisekunden (ms)
Da die Rückgabewerte der millis()
-Funktion relativ schnell sehr groß werden können, sollten diese immer einer Variablen vom Typ long
oder besser vom Typ unsinged long
übergeben werden.
Blinken mit millis()
Im folgenden Programm wird nicht einfach nur bis zum Umschalten der LED mit der delay()
Methode gewartet, sondern in einer Schleife regelmäßig auf die Uhr geschaut und überprüft, ob die LED umgeschaltet werden muss. Da nicht nur gewartet wird, sondern das vergangene Zeitintervall immer wieder überprüft wird, können zwischen jedem neuen Überprüfen der Zeit auch andere Aktionen ausgeführt werden.
// Lässt eine LED mit Hilfe der millis() Funktion blinken.
#define LED 2 // Pin der LED
int zustandLED = LOW; // zu setzender LED-Zustand
unsigned long zeitLetztesUmschalten = 0; // Zeitpunkt LED-Änderung
unsigned long blinkZeit = 1000; // Blinkintervall in ms
void setup()
{
pinMode(LED, OUTPUT); // Pin als Output
}
void loop()
{
unsigned long aktuelleZeit = millis(); // Zeit seit Programmstart in ms
// Es wird die Zeit bestimmt, die seit dem letzten Umschalten der LED vergangen
// ist. Ist die vergangene Zeit größer gleich `blinkZeit`, so wird der Wert
// von `zustandLED` angepasst und anschließend der Pin auf den entsprechenden
// Zustand gesetzt.
if (aktuelleZeit - zeitLetztesUmschalten >= blinkZeit)
{
if (zustandLED == LOW){ // Überprüfen des LED Zustands
zustandLED = HIGH;
}
else{
zustandLED = LOW;
}
digitalWrite(LED, zustandLED); // Pin auf `zustandLED` setzen
zeitLetztesUmschalten = aktuelleZeit; // Zeit des Umschaltens speichern
}
}
Erläuterungen zum Programm
Mit der Zeile
unsigned long aktuelleZeit = millis(); // Zeit seit Programmstart in Millisekunden
wird der Variablen aktuelleZeit
die seit dem Programmstart vergangene Zeit in Millisekunden zugewiesen.
Da die LED ihren Zustand immer dann ändern soll, wenn die gegebene Zeitdifferenz blinkZeit
vergangen ist, wird in der if
-Verzweigung die seit dem letzten Umschalten vergangene Zeit bestimmt: aktuelleZeit - zeitLetztesUmschalten
.
if (aktuelleZeit - zeitLetztesUmschalten >= blinkZeit)
Ist seit dem letzten Umschalten mehr Zeit als in blinkZeit
angegeben vergangen, so wird als erstes der Zustand der LED überprüft:
if (zustandLED == LOW){ // Überprüfen des LED Zustands
zustandLED = HIGH;
}
else{
zustandLED = LOW;
}
Hierfür wurde global die Zustandsvariable zustandLED
definiert. Soll der Zustand der LED geändert werden (an oder aus), so wird der neue Zustand der LED in der Variable zustandLED
vermerkt und anschließend mit
digitalWrite(LED, zustandLED); // Pin auf `zustandLED` setzen
der LED übergeben. Erst durch den Befehl digitalWrite()
wird die LED umgeschaltet.
Anschließend muss der Zeitpunkt des Umschaltens gespeichert werden, damit später wieder die Zeit zum erneuten Umschalten bestimmt werden kann:
zeitLetztesUmschalten = aktuelleZeit; // Zeit des Umschaltens speichern
Mit der millis()
-Funktion kann auch ein einfaches Multitasking (also das scheinbar parallele Abarbeiten von unterschiedlichen Aufgaben) auf dem Arduino realisiert werden.
Aufgaben
Verwenden Sie zum Lösen der Aufgaben nicht die delay()
Funktion.
- Schreiben Sie ein Programm, welches eine LED mit verschiedene An- und Auszeiten blinken lässt. Nutzen Sie
millis()
. - Schließen Sie eine zweite LED an den Arduino an und lassen sie diese unabhängig von der ersten LED mit einem anderen Rhythmus blinken.
- Schreiben Sie ein Programm, welches eine LED nur dann langsam blinken lässt, wenn ein Taster gedrückt ist. Sobald der Taster losgelassen wurde, soll die LED aus gehen (nicht erst nach dem Beenden des Blink-Intervalls).
- Bei vielen Anwendungen soll das Hauptprogramm erst nach dem Betätigen eines Tasters gestartet werden. Schreiben sie Programm, welches die
setup()
Funktion erst nach dem Drücken eines Tasters beendet. Als Zeichen, dass auf eine Tastereingabe gewartet wird, soll zur selben Zeit eine LED blinken. Nachdem der Taster gedrückt wurde, erlicht die LED und auf dem seriellen Monitor wird der TextProgramm startet ...
ausgegeben. Hinweis: Verwenden Sie einewhile
-Schleife. - Schreiben Sie ein Programm, welches die Zeit misst, die ein Taster gedrückt ist. Das Ergebnis soll auf dem seriellen Monitor ausgegeben werden:Beim schnellen Drücken des Tasters werden die Messergebnisse vermutlich nicht Ihren Erwartungen entsprechen. Analysieren Sie das unerwartete Verhalten.
Zeit, die der Taster gedrückt war: x.xx Sekunden