Erklärung nicht-blockierendes Timing am Alltagsbeispiel Tiefkühl-Pizza backen ( millis() statt delay() ) Blink without delay BWD

Ich habe diese Erklärung vor längerer Zeit noch ausführlicher und mit Demo-Codes hier auf englisch geschrieben.

Jetzt habe ich mir mal Zeit genommen das wichtigste auf deutsch zu erklären.
Ich bin der Meinung wenn man es von einem Alltagsbeispiel aus kommend erklärt dann wird es sehr viel leichter verständlich.

Ich erkläre nicht-blockierendes Timing gerne mit "eine Tiefkühl-Pizza backen".

Wie macht man eine Tiefkühlpizza backen?
Ofen einschalten und ein paar Minuten aufheizen lassen.

Auf der Verpackung steht 10 Minuten backen.

Wenn der Ofen heiß ist Pizza hineinschieben.
Man schaut auf die Uhr es ist 13:05 Uhr.
Das bedeutet bei 10 Minuten Backzeit ist die Pizza um 13:15 Uhr fertig.

Das heißt bis die Pizza fertig ist könnte man noch ein paar andere Sachen machen.
Arduino-Forum lesen / posten
endlich mal wie man dieses Forum benutzt lesen
Teller und Besteck auf den Tisch
WhatsApp-Nachrichten checken.
Aus dem Keller was zu Trinken holen
Ne runde am Handy spielen
usw.
Dabei wird man immer wieder auf die Uhr schauen ob schon 10 Minuten vorbei sind.

Beispiel:

13:07 - 13:05 = 2 Minuten (Weniger als 10 Minuten => weiterbacken lassen
13:08 - 13:05 = 3 Minuten (Weniger als 10 Minuten => weiterbacken lassen
13:09 - 13:05 = 4 Minuten (Weniger als 10 Minuten => weiterbacken lassen
13:10 - 13:05 = 5 Minuten (Weniger als 10 Minuten => weiterbacken lassen
13:11 - 13:05 = 6 Minuten (Weniger als 10 Minuten => weiterbacken lassen
13:12 - 13:05 = 7 Minuten (Weniger als 10 Minuten => weiterbacken lassen
13:13 - 13:05 = 8 Minuten (Weniger als 10 Minuten => weiterbacken lassen
13:14 - 13:05 = 9 Minuten (Weniger als 10 Minuten => weiterbacken lassen
13:15 - 13:05 = 10 Minuten Hurra 10 Minuten vorbei Pizza ist fertig.

Was läuft da im Prinzip ab
man merkt sich die Startzeit 13:05
Das entspricht

    Led_BlinkTimer = millis(); // Timer auf aktuelle Zeit setzen
    Buzzer_Timer   = millis();

Dann überprüft man immer wieder wie viel Zeit ist schon vergangen indem man aktuelle Zeit minus Startzeit berechnet
Das ist das was in der function TimePeriodIsOver gemacht wird

  // prüfe ob LED-Blinkzeit vorbei ist
  if ( TimePeriodIsOver(Led_BlinkTimer, LedBlinkInterval) ) {

Im Detail

       aktuelle Zeit -  StartZeit         ist die größer gleich Intervall
  if ( currentMillis - startOfPeriod >= TimePeriod ) {

          13:07      -  13:05                ergibt  2  
  if ( currentMillis - startOfPeriod >= TimePeriod ) {

die Aussage 13:07      -  13:05    >=  10      ist FALSCH    false 
.
.
.
       aktuelle Zeit -  StartZeit         ist das größer/gleich Intervall
  if ( currentMillis - startOfPeriod >= TimePeriod ) {

          13:15      -  13:05                ergibt  10  
  if ( currentMillis - startOfPeriod >= TimePeriod ) {

die Aussage 13:15      -  13:05    >=  10      ist WAHR    true 

Wenn es 13:07 ist liefert

TimePeriodIsOver(13:05, 10 Minuten) ) 

false

um 13:07 ist die Bedingung

if ( TimePeriodIsOver(13:05, 10 Minuten)  ) {  

nicht erfüllt

um 13:15 ist die Bedingung

if ( TimePeriodIsOver(13:05, 10 Minuten)  ) {  

erfüllt. Also führe den Code in der If-Bedingung aus

13:15 Uhr

if ( TimePeriodIsOver(13:05, 10 Minuten)  ) {  
  Pizza_aus_dem_ofen_holen();

Man merkt sich die jeweilige Anfangszeit und vergleicht dann
ständig zig-tausendmal pro Sekunde
Aktuelle Zeit - Anfangszeit => ZeitIntervall

Aktuelle Zeit - Anfangszeit => 20 Sekunden nur wenn true => LED und Sirene neu einschalten

  // prüfe ob ein 20-Sekunden-Intervall vorbei ist
  if ( TimePeriodIsOver(Timer20Sec, MainInterval) ) {
    // wenn WIRKLICH 20 Sekunden vorbei sind
    Led_BlinkTimer = millis(); // Timer auf aktuelle Zeit setzen
    Buzzer_Timer   = millis();
    blink_LED = true; // LED blinken einschalten
    buzzerOn  = true; // Sirene einschalten
  }

Aktuelle Zeit - Anfangszeit => 10 Sekunden nur wenn true=> LED-Blinken ausschalten
Aktuelle Zeit - Anfangszeit => 5 Sekunden nur wenn true=> Sirene ausschalten
Aktuelle Zeit - Anfangszeit => 0,5 Sekunden nur wenn true=> LED an/aus
Aktuelle Zeit - Anfangszeit => 1,0 Sekunden nur wenn true=> Sirene An/aus

Diese Vergleiche werden zig-tausend mal pro Sekunde wiederholt.
Aber nur wenn die if-Bedingung true wird
wird der Code in der If-Bedingung ausgeführt.

Zusammengefasst:
Man merkt sich die jeweilige Anfangszeit und vergleicht dann
ständig zig-tausendmal pro Sekunde
ob eine bestimmte Zeitspanne schon vorbei ist oder nicht.

Dieser Vergleich ist in 0,1 Millisekunden abgearbeitet = nicht blockierend

Und nur wenn die Zeitspanne WIRKLICH vorbei ist
dann werde aktiv.

Wenn folgende Bedingung erfüllt ist Innerhalb von loop() gibt es wirklich nirgendwo ein delay().

Das Auswerten der If-Bedingung selbst dauert weniger als eine Millisekunde
Wenn die Auswertung der If-Bedingung false ergibt wird der Code-Block der If-Bedingung nicht ausgeführt.

Das bedeutet, dass das Abarbeiten der If-Bedingung ganz schnell erledigt ist.

Wenn der ganze Code innerhalb von loop() keine (länger dauernden ) For-Schleifen, keine While-Schleifen und auch sonst keine viel Ausführungszeit in Anspruch nehmenden function-calls enthält, wird loop() zig-tausende mal pro Sekunde durchlaufen.

Und das nennt man dann nicht-blockierendes Programmieren.

vgs

P.S. An bestimmten Stellen macht zum Verstehen des Grundprinzips Reduzierung auf das notwendigste Sinn. (Didaktische Reduzierung)
Wenn man es wissenschaftlich möglichst exakt und eindeutig und auch noch alle Sonderfälle einschließend beschreiben will dann landet man zwar bei wissenschaftlicher Exaktheit. Es ist dann aber eben auch schwer verständlich.

Es steht ja jedem frei seine eigene Erklärvariante zu posten.

Zweites Posting für Ergänzungen

drittes Posting für Ergänzungen

Danke, aber als "Referenz" wird hier doch immer das Nachwächter-Beispiel gebracht.

Naja, haben wir zwei. Der Nachtwächter muss ja auch mal was essen :wink:

Und was ist am Tag ? :wink:

Da wartet er bis das Bier in Kühlschrank kalt ist (1h) und geht nebenbei alle 20 min ein Eis essen (passend zum Wetter) :sweat_smile:

Da wird es aber schwer, in 100 Mikrosekunden wieder oben zu sein um den Ofen auszuschalten.

Der Nachtwächter macht sich jedenfalls weniger Streß.
:wink:

Dann will ich auch mal:

Die Schlußfolgerung ist falsch.

Erklären und besser machen

Ersetze Durch mit Während und passe das gramatikalisch an.

So Absatz neu formuliert und diesen Absatz als P.S. hinzugefügt

P.S. An bestimmten Stellen macht zum Verstehen des Grundprinzips Reduzierung auf das notwendigste Sinn. (Didaktische Reduzierung)
Wenn man es wissenschaftlich möglichst exakt und eindeutig und auch noch alle Sonderfälle einschließend beschreiben will dann landet man zwar bei wissenschaftlicher Exaktheit. Es ist dann aber eben auch schwer verständlich.

Es steht ja jedem frei seine eigene Erklärvariante zu posten.

Wenn Du meinst mit abgesicherter Ungenauigkeit verständlicher zu sein, dann wundere Dich nicht, warum Fragesteller diese Ungenaugigkeiten ebenso für sich in Anspruch nehmen.

Es ist ganz einfach: ständig ist etwas anderes als regelmäßig und durch ist etwas anderes als während. Und das ist gesichert. Ohne philosophisches Studium. Ich glaub das ist irgendwo zwischen Jahrgang 4 und 9 in der Schule gewesen.

Achja. Nu werde richtig produktiv und schreibe deine eigene Erklärung.

Es war und ist noch immer Dein Anspruch, eine Erklärung für nicht blockierenden Code, abseits der Nachtwächtererklärung, zu liefern.
Diese hat mir vollkommen ausgereicht. Daher ist mein Anspruch erfüllt.

Bei Dir war es nicht so. Aber bitte reflektiere Deinen Anspruch nicht auf mich.
Sprachliche Fehler sind kein Beinbruch und stehen jedem zu.
Die Annahme gut gemeinter Hilfe kann jeder verweigern.
Auch Du.