Zum Hauptinhalt springen

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.

  1. Schreiben Sie ein Programm, welches eine LED mit verschiedene An- und Auszeiten blinken lässt. Nutzen Sie millis().
  2. 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.
  3. 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).
  4. 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 Text Programm startet ... ausgegeben. Hinweis: Verwenden Sie eine while-Schleife.
  5. Schreiben Sie ein Programm, welches die Zeit misst, die ein Taster gedrückt ist. Das Ergebnis soll auf dem seriellen Monitor ausgegeben werden:
    Zeit, die der Taster gedrückt war: x.xx Sekunden
    Beim schnellen Drücken des Tasters werden die Messergebnisse vermutlich nicht Ihren Erwartungen entsprechen. Analysieren Sie das unerwartete Verhalten.