Ich wurden gebeten, die Erklärung des BlinkWithoutDelay hier nochmal reinzustellen.
Am Beispiel eines Wachmanns, der seine Runden dreht, wird in einfacher und eingängiger Weise erklärt, wie man ohne delay() zeitliche Abfolgen programmieren kann.
(an die Profis: es geht auch einfacher, es sind syntaktische Unsauberkeiten drin. Mein Augenmerk lag auf einer möglichst einfachen Darstellung für Menschen, die noch niemals im Leben was mit Programmiersprachen zu tun hatten)
Also: Wie funktioniert Blink Without Delay?
So kompliziert ist das gar nicht.
Gehen wir vom Blinken mal einen Schritt weg zu was ganz praktischem: Wir haben einen Nachtwächter / Wachmann, der immer seine Runden um ein Haus geht (das entspricht unserer Loop).
Zusätzlich erhält er die Aufgabe, jede Stunde für 15min eine Lampe einzuschalten. Die Lampe selbst sieht er nicht, aber es gibt einen Schalter am Haus.
Was macht er also:
Er schaltet das Licht ein, merkt sich die Zeit und dass die Lampe ein ist und macht weiter seine Runden. Bei jeder Runde schaut er auf die Uhr, ob die 15min schon um sind. Sind sie noch nicht um, geht er einfach weiter, wenn die um sind, schaltet er die Lampe aus und merkt sich, dass sie jetzt aus ist.
Nun schaut er bei jeder Runde auf die Uhr, um zu prüfen, ob die Stunde seit Einschalten schon um ist.
Ist sie um, schaltet er wieder ein, notiert sich Status der Lampe und Uhrzeit, und nimmt seine Runden wieder auf.
Genau so macht es der Arduino.
wenn wir die Schritte des Wachmanns in Arduinosprache übersetzen, schaut das in etwas so aus:
wenn sich der Wachmann die Zeiten auf dem Zettel notiert, schreibt der Arduino einen Wert in eine Variable. millis() ist die Systemuhr des Arduino. Sie zählt einfach die vergangenen millisekunden seit Start des Arduino.
der zugehörige Code schaut dann so aus:
unsigned long LED_timestore; // Variable Speicher für Systemzeit.
int LedStatus = LOW;
int LedPin = 13;
void setup() {
pinMode(LedPin, OUTPUT); // teilt dem Arduino mit, dass das ein Ausgang ist.
}
void loop() {
if (LedStatus == LOW) {
if (millis() - LED_timestore> 1000 ) {
digitalWrite(LedPin, HIGH);
LED_timestore = millis();
LedStatus = HIGH;
}
} else {
if (millis() - LED_timestore> 300) {
digitalWrite(LedPin, LOW);
LedStatus = LOW;
}
}
}
Wenn der Wachmann / Arduino mehrere Lampen schalten soll, braucht er einfach noch mehr Zettel / Variable und Schalter / Pins.
Geben wir Ihm doch noch eine Aufgabe dazu:
Erweiterung:
Ausserdem soll er alle 3h die Bewässerung für 10min einschalten.
Dann könnte das so aussehen:
In dieser Weise kann man (fast) beliebig viele Aktionen unabhängig voneinander ausführen lassen.
Man kann es übersichtlicher gestalten, in dem man die einzelnen Aktionen in Funktionen packt, oder flexibler, in dem man die Zeiten in Arrays steckt. Und, und, und...
Im Anhang Tabellen als Word-Datei (Excel geht leider nicht)
blink_without_delay_wachmann.doc (64 KB)