Ein Countdown soll die verbleibende Wartezeit anzeigen

Hallo liebe community,

Es gibt ein Problem in meinem Sketch. Der Sketch soll ein kinetisches Spiel steuern, dass mit Druckluft aus einem Kompressor- Kessel betrieben wird. Der Ablauf des Spiels gliedert sich in drei Phasen:

1. Vorbereitungsphase
Ein Kompressor baut in seinem Kessel Luftdruck für das Spiel auf.

2. Spielphase
Das Spiel startet weil es mit Druckluft versorgt wird (geöffnetes Ventil).

3. Spielpause
Das Spiel endet, weil es nicht mehr mit Druckluft versorgt wird (geschlossenes Ventil). Jetzt kommt das Problem: Bis die Vorbereitungsphase wieder beginnt soll es eine 20- minütige Pause geben. Ein Countdown soll die verbleibende Wartezeit anzeigen.

Ich weiß, dass der Mikrocontroller während der 20- minütigen Pause, die ich mit delay im Sketch festgelegt habe, schläft, und den Countdown in dieser Zeit nicht parallel runterzählen kann. Ich weiß, dass sich das Problem mit der Funktion millis() irgendwie lösen lässt. Leider reichen meine Arduino- Kenntnisse noch nicht aus um das alleine auf die Reihe zu kriegen.

Ich würde mich riesig freuen wenn mir jemand mit dem Sketch helfen könnte!

Herzliche Grüße Leonardo

// LiquidCrystal Library

#include <LiquidCrystal.h>

int S = 00; // count seconds 
int M = 20; // count minutes
int H = 00; // count hours
//initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);


void setup() {

lcd.begin(16, 2);
pinMode (7, OUTPUT);                  //Ventil               
pinMode (2, OUTPUT);                  //Kompressor

}

void loop() {

// 1. Vorbereitungsphase: Kompressorkessel wird aufgefüllt. Das Kompressorventil ist geschlossen. Auf dem LCD wird während dieser Phase "WAIT" angezeigt.

lcd.setCursor(0, 0);
lcd.print("WAIT");                    //Beginn beim ersten Zeichen in der ersten Zeile mit dem Text „WAIT“
digitalWrite (7,LOW);                 // Ventil ist geschlossen  
digitalWrite (2,HIGH);                // Kompressor anschalten
delay ( 180000);                      // Kompressor läuft 3 Minuten, bis der Kessel gefüllt ist
lcd.clear();                          //Display löschen




// 2. Spielphase: Druckluft versorgt das Spiel. Während des Spiels wird auf dem LCD "PLAY" angezeigt.

lcd.setCursor(0, 0);
lcd.print("PLAY");                    //Beginn beim ersten Zeichen in der ersten Zeile mit dem Text „PLAY“
digitalWrite (2, LOW);                // Kompressor ausschalten
digitalWrite (7, HIGH);               // Ventil öffnen
delay (300000);                       // Das Ventil bleibt 5 Minuten offen
digitalWrite(7,LOW);                  // Das Ventil schließt und damit endet das Spiel
lcd.clear();                          //Display löschen


                  
// 3. Spielpause: Es gibt eine Pause von 20 Minuten. Der LCD soll anzeigen wie lange die Pause noch dauert.

delay(120000);                        // Spielpause von 20 Minuten
 lcd.setCursor(1,0);                  // Die verbleibende Wartezeit soll auf LCD angezeigt werden
 lcd.print ("Time to next Game");
 lcd.setCursor(6,1);                                       
 lcd.print(":");
 lcd.setCursor(9,1);
 lcd.print(":");
 
 S--;
 delay(1000);
  
 if(S<0)
 {
   M--;
   S=59;
 }
 if(M<0)
 {
   H--;
   M=59;
 }
 if(H<0) { H=23; M=59; S=59; } if(M>9)
 {
   lcd.setCursor(7,1);
   lcd.print(M);
 }
 else
 {
   lcd.setCursor(7,1);
   lcd.print("0"); 
   lcd.setCursor(8,1);
   lcd.print(M);
   lcd.setCursor(9,1);
   lcd.print(":");
 }
  
 if(S>9)
 {
   lcd.setCursor(10,1);
   lcd.print(S);
 }
 else
 {
   lcd.setCursor(10,1);
   lcd.print("0"); 
   lcd.setCursor(11,1);
   lcd.print(S);
   lcd.setCursor(12,1);
   lcd.print(" ");
 }
  
 if(H>9)
 {
   lcd.setCursor(4,1);
   lcd.print (H);
 }
 else
 {
   lcd.setCursor(4,1);
   lcd.print("0"); 
   lcd.setCursor(5,1);
   lcd.print(H);
   lcd.setCursor(6,1);
   lcd.print(":");
   }

}

Ersetze erst mal quote durch code, damit das lesbarer wird.

Gruß Tommy

Sorry;)

Die Funktio loop() heißt so, weil sie als permanente Schleife immer wieder dran kommt, und für jeden Durchlauf keine (kaum) Zeit braucht. Was das mit dem BlinkWithoutDelay Beispiel zu tun hat, zeigt dir die Nachtwächter-Erklärung hier im Forum.

Dass es kein Problem ist, in der Wartezeit jede Sekunde eine andere Zahl anzuzeigen, wenn man diese Wartezeit nicht mit delay (180000) realisiert, sollte klar werden.

Wieso benutzt Du das Pin 7 doppelt?
Zu millis()
schau dir das Beispiel "Blink without delay" der IDE an und lies Nachtwächtererklährung https://forum.arduino.cc/index.php?topic=423688.0

Grüße Uwe

Hi

Momentan besteht Dein 'Spiel' aus drei Wartezeiten - ok, wenn man dafür keinen hoch qualifizierten µC nehmen will, sondern 08/15 Elektronik, braucht man Davon gleich mehr.
Aber in diesem Sketch sehe ich absolut keine Notwendigkeit, DAS mit einem µC erschlagen zu wollen.

Kleiner, nicht ganz ernst gemeinter, Ansatz:
int wartezeit=60x20 //60 Sekunden mal 20 Minuten ... warum int? Weil Du ÜBERALL int benutzt
while (wartezeit>0){
Serial.println(wartezeit);
delay(1000);
wartezeit--;
}

Absichtlich nicht in Code-Tags und ohne schnieke Ausgabe.

MfG

PS: Deine ganzen int sind ebenfalls berichtigungsfähig - auch könnte man, bei Dingen, Die konstant sind, const verwenden.

Deine 3 Phasen

Vorbereitungsphase
Spielphase
Spielpause

sind 3 Stufen eine Statemachine.

Du musst dir nur überlegen, wodurch du von einem Status in den nächsten Status kommst.
In deinem Fall ist es wohl die Zeit.
Und damit bist du wieder bei “Blink Without Delay” bzw. millis()-previousMillis>intervall

Auf Wikipedia gibt es Theorie: Endlicher Automat – Wikipedia
Im Forum sind viele ähnliche Threads. z.B.: https://forum.arduino.cc/index.php?topic=620652.0

Suchbegriffe sind
state machine
endlicher Automat

Vielen Dank für Eure Antworten!

Ich hab meinen Sketch umgeschrieben. Jetzt erfolgt der Übergang von einer Phase in die nächste durch millis(). Ich habe mich dabei an der Nachtwächtererklärung orientiert. Danke für den Tipp!

Jetzt muss ich aber noch folgendes Problem lösen: In der Spielpause soll ein Countdown auf dem LCD angezeigt werden, der 20 Minuten runterzählt.

Meine Idee ist jetzt folgende:

Ein Countdown- Timer muss dauerhaft im Sketch laufen. Nach dem Schließen des Ventils ( Beginn der Spielpause) muss der Countdown resettet werden. Und dann muss dieser Countdown auf dem LCD abgebildet werden. Nach den 20 Minuten wird der Countdown nicht mehr auf dem LCD abgebildet.

Das Problem ist, dass in meinem Countdown- Timer kein delay () vorkommen darf. Ich weiß gerade nicht so recht wie ich das anstellen soll. Kann mir jemand bitte weiterhelfen? Ein Link zu einem ähnlichen Post oder ein kurzer Tipp als Sketch wären super!:slight_smile:

Herzliche Grüße Leonardo

// LiquidCrystal Library

#include <LiquidCrystal.h>

int S = 00; // count seconds 
int M = 20; // count minutes
int H = 00; // count hours

unsigned long timestore;              // Variable Speicher für Systemzeit.
int KompressorStatus = LOW;           //Kompressor is normally off
int KompressorPin = 1;
int VentilStatus = LOW;               //Ventil is normally closed
int VentilPin = 2;

//initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);


void setup() {

lcd.begin(16, 2);
pinMode (1, OUTPUT);                  //Kompressor
pinMode (2, OUTPUT);                  //Ventil               

}

void loop() {

// 1. Vorbereitungsphase: Kompressorkessel wird aufgefüllt. Das Kompressorventil ist geschlossen. Auf dem LCD wird während dieser Phase "WAIT" angezeigt.

if(KompressorStatus == LOW){                  // wenn der Kompressor aus ist
  if(millis()-timestore>1800000){             // auf die Uhr sehen, ob die 30 Minuten schon rum sind, wenn ja
  digitalWrite(KompressorPin, HIGH);          // Kompressor einschalten
  timestore = millis();                       // und Uhrzeit notieren
  KompressorStatus = HIGH;                    // notieren, dass der Kompressor angeschaltet ist
  }                                          
} else {                                      // wenn der Kompressor an ist
if(millis()-timestore>300000){                // auf die Uhr sehen ob die 5 Minuten schon rum sind, wenn ja
  digitalWrite (KompressorPin, LOW);          // Kompressor ausschalten
  KompressorStatus = LOW;                     // notieren, dass der Kompressor ausgeschaltet ist
  

// 2. Spielphase: Druckluft versorgt das Spiel. Während des Spiels wird auf dem LCD "PLAY" angezeigt.

  digitalWrite (VentilPin, HIGH);             // Ventil öffnen
  VentilStatus = HIGH;                        // notieren, dass das Ventil geöffnet ist                  
 }                                            // wenn die 5 Minuten noch nicht rum sind: weitergehen
} 

if(VentilStatus == HIGH){                      // wenn das Ventil geöffnet ist
  if(millis()-timestore> 600000){              // auf die Uhr sehen, 10 Minuten schon rum sind, wenn ja
  digitalWrite(VentilPin, LOW);                // Ventil öffnen
  VentilStatus = LOW;                          // notieren, dass das Ventil geschlossen ist
   }
 } 

// Spielpause: Jetzt soll der Countdown, der im Hintergrund abläuft resettet werden und dann auf dem lcd display erscheinen. So lange bis die Vorbereitungsphase wieder beginnt.
  
  
while(KompressorStatus == HIGH){             // während der Kompressor eingeschaltet ist wird "WAIT" auf dem LCD angezeigt
  lcd.setCursor(0, 0);                         // Beginn beim ersten Zeichen in der ersten Zeile 
  lcd.print("WAIT");                           // mit dem Text „WAIT“
}

while(KompressorStatus == HIGH){               // während das Ventil geöffnet ist wird "PLAY" auf dem LCD angezeigt
  lcd.setCursor(0, 0);                         // Beginn beim ersten Zeichen in der ersten Zeile 
  lcd.print("PLAY");                           // mit dem Text „PLAY“
}
lcd.setCursor(1,0); 
 lcd.print ("Tutorial45.com");
 lcd.setCursor(6,1);
 lcd.print(":");
 lcd.setCursor(9,1);
 lcd.print(":");
 
 S--;
 delay(1000);
  
 if(S<0)
 {
   M--;
   S=59;
 }
 if(M<0)
 {
   H--;
   M=59;
 }
 if(H<0) { H=23; M=59; S=59; } if(M>9)
 {
   lcd.setCursor(7,1);
   lcd.print(M);
 }
 else
 {
   lcd.setCursor(7,1);
   lcd.print("0"); 
   lcd.setCursor(8,1);
   lcd.print(M);
   lcd.setCursor(9,1);
   lcd.print(":");
 }
  
 if(S>9)
 {
   lcd.setCursor(10,1);
   lcd.print(S);
 }
 else
 {
   lcd.setCursor(10,1);
   lcd.print("0"); 
   lcd.setCursor(11,1);
   lcd.print(S);
   lcd.setCursor(12,1);
   lcd.print(" ");
 }
  
 if(H>9)
 {
   lcd.setCursor(4,1);
   lcd.print (H);
 }
 else
 {
   lcd.setCursor(4,1);
   lcd.print("0"); 
   lcd.setCursor(5,1);
   lcd.print(H);
   lcd.setCursor(6,1);
   lcd.print(":");
 }
}

Hier ist der Sketch nochmal ohne den Countdown- Timer- Teil, der wegen dem delay() sowieso nicht zu gebrauchen ist:

// LiquidCrystal Library

#include <LiquidCrystal.h>

unsigned long timestore;              // Variable Speicher für Systemzeit.
int KompressorStatus = LOW;           //Kompressor is normally off
int KompressorPin = 1;
int VentilStatus = LOW;               //Ventil is normally closed
int VentilPin = 2;

//initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);


void setup() {

lcd.begin(16, 2);
pinMode (1, OUTPUT);                  //Kompressor
pinMode (2, OUTPUT);                  //Ventil               

}

void loop() {

// 1. Vorbereitungsphase: Kompressorkessel wird aufgefüllt. Das Kompressorventil ist geschlossen. Auf dem LCD wird während dieser Phase "WAIT" angezeigt.

if(KompressorStatus == LOW){                  // wenn der Kompressor aus ist
  if(millis()-timestore>1800000){             // auf die Uhr sehen, ob die 30 Minuten schon rum sind, wenn ja
  digitalWrite(KompressorPin, HIGH);          // Kompressor einschalten
  timestore = millis();                       // und Uhrzeit notieren
  KompressorStatus = HIGH;                    // notieren, dass der Kompressor angeschaltet ist
  }                                          
} else {                                      // wenn der Kompressor an ist
if(millis()-timestore>300000){                // auf die Uhr sehen ob die 5 Minuten schon rum sind, wenn ja
  digitalWrite (KompressorPin, LOW);          // Kompressor ausschalten
  KompressorStatus = LOW;                     // notieren, dass der Kompressor ausgeschaltet ist
  

// 2. Spielphase: Druckluft versorgt das Spiel. Während des Spiels wird auf dem LCD "PLAY" angezeigt.

  digitalWrite (VentilPin, HIGH);             // Ventil öffnen
  VentilStatus = HIGH;                        // notieren, dass das Ventil geöffnet ist                  
 }                                            // wenn die 5 Minuten noch nicht rum sind: weitergehen
} 

if(VentilStatus == HIGH){                      // wenn das Ventil geöffnet ist
  if(millis()-timestore> 600000){              // auf die Uhr sehen, 10 Minuten schon rum sind, wenn ja
  digitalWrite(VentilPin, LOW);                // Ventil öffnen
  VentilStatus = LOW;                          // notieren, dass das Ventil geschlossen ist
   }
 } 

// Spielpause: Jetzt soll der Countdown, der im Hintergrund abläuft resettet werden und dann auf dem lcd display erscheinen. So lange bis die Vorbereitungsphase wieder beginnt.
  
  
while(KompressorStatus == HIGH){             // während der Kompressor eingeschaltet ist wird "WAIT" auf dem LCD angezeigt
  lcd.setCursor(0, 0);                         // Beginn beim ersten Zeichen in der ersten Zeile 
  lcd.print("WAIT");                           // mit dem Text „WAIT“
}

while(KompressorStatus == HIGH){               // während das Ventil geöffnet ist wird "PLAY" auf dem LCD angezeigt
  lcd.setCursor(0, 0);                         // Beginn beim ersten Zeichen in der ersten Zeile 
  lcd.print("PLAY");                           // mit dem Text „PLAY“
}
}

Das kannst Du doch ebenfalls mit Millis machen. Du setzt den Zähler aiuf 20 und nach jeder Minute ziehst Du eins ab. (oder auf 1200 und nach jeder Sekunde abziehen).

Gruß Tommy

Hi

Man könnte, wenn man denn wöllte, meinen 'nicht ganz ernst gemeinten Ansatz' in #5 auch einfach per C&P in den eigenen Sketch einbringen und schauen, ob man damit nicht einen Schritt weiter kommt.
Das 'nicht ganz ernst gemeint' ist aber ernst gemeint - Das geht mit millis() und endlichem Automat wesentlich flüssiger.
Hier wohl nicht gebraucht, weil hier ausschließlich NUR gewartet werden soll - die letzte Warterei soll aber 20 Minuten lang wohl eine sekündlich angepasste Restwartezeit anzeigen - 20 x 60 Einzelwartereien von 1000ms, dazwischen eine Ausgabe der Rest-Wartezeit und weiter warten.

MfG

Danke für deine Antwort Tommy56,

Ich habe gerade versucht einen Sketch zu schreiben in dem ein Countdown mit millis() abläuft. Auf dem Display erscheint aber leider noch nicht das was ich will. Denn in der zweiten Zeile des LCD erscheint:" 0:-1 " und von einem Countdown fehlt jede Spur. Kann mir bitte jemand sagen was ich falsch gemacht habe?

Herzliche Grüße Leonardo

// LiquidCrystal Library

#include <LiquidCrystal.h> //LCD-Bibliothek laden

// Festlegen der Variablen

int s = 60;                                     // Wert für Variable s  = 60
int m = 30;                                     // Wert für Varaible m = 30
unsigned long timestore_Sekunden;               // Variabler Speicher für Systemzeit

//initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

void setup() {
  
  lcd.begin(16,2);                             //Im Setup wird angegeben, wie viele Zeichen und Zeilen verwendet werden. Hier: 16 Zeichen in 2 Zeilen.
}

void loop() {

if(millis()-timestore_Sekunden>1000){           // wenn eine Sekunde vergangen ist...
  s = s - 1;                                    // wird s um 1 dezimiert
  lcd.setCursor(0,0);                           // Startposition der Darstellung auf dem LCD festlegen. lcd.setCursor(0,0) bedeutet: Erstes Zeichen in der ersten Zeile.
  lcd.print("time to next game:");              // Dort soll der Text „time to next game: “ erscheinen. 
  lcd.setCursor(0,1);                           // Startposition der Darstellung auf dem LCD festlegen.
  lcd.print(m);                                 // Dort soll die Variable m erscheinen.
  lcd.print (":");                              // dann der Text ":"
  lcd.print(s);                                 // dann die Variable s
  timestore_Sekunden = millis();                // dann wird timestore_Sekunden = millis() gleichgesetzt
  }
  
if(s = 0){                                      // wenn s bei 0 angekommen ist
  s = 60;                                       // wird s wieder 60
  m = m - 1;                                    // gleichzeitig wird m um eins dezimiert
}

if ( m = 0){                                    // wenn m bei 0 angekommen ist
m = 30;                                         // wird m wieder 30
 }
}
// Das ist eine Zuweisung
if (s = 0) {};
// das ist ein Vergleich
if (s == 0) {};

Ich würde erst alle Berechnungen machen und dann die Ausgabe.

Gruß Tommy

Hi

In Deiner IF-Abfrage prüfst Du NICHT, ob S Null ist - Du weist s den Wert Null zu.
Ob Das nun TRUE oder FALSE ist müsste man Mal antesten ... aber nach der Zeile

if (s=0){...

ist s auf Null gesetzt.
Einen Durchlauf später wird s zu -1 und auf de mDisplay ausgegeben.

Du möchtest in der ID auf Gleichheit prüfen - Das geht mit == (zwei Mal Gleich).
Gleiches mit m=0.

MfG

Den (noch fehlerhaften) Countdown habe ich dann in meinen vorherigen Sketch integriert.

Beim Kompilieren des Sketches wird an diesem Punkt eine Fehlermeldung angezeigt:

if (KompressorStatus == LOW)&& (VentilStatus == LOW){  // Wenn KompressorStatus und Ventilstatus == LOW...

Kann mir jemand sagen wo der Fehler liegt?

Ich will den im Hintergrund ablaufenden Countdown nur dann auf dem LCD abbilden lassen, wenn KompressorStatus und VentilStatus == LOW sind. Das ist die Zeit, in denen die Spielpause ist.

Hier ist der gesamte Sketch:

// LiquidCrystal Library

#include <LiquidCrystal.h>

int s = 60;                                     // Wert für Variable s  = 60
int m = 30;                                     // Wert für Varaible m = 30
unsigned long timestore_Sekunden;               // Variabler Speicher für Systemzeit

unsigned long timestore;                        // Variabler Speicher für Systemzeit
int KompressorStatus = LOW;                     //Kompressor is normally off
int KompressorPin = 1;
int VentilStatus = LOW;                         //Ventil is normally closed
int VentilPin = 2;

//initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);


void setup() {

lcd.begin(16, 2);
pinMode (1, OUTPUT);                            //Kompressor
pinMode (2, OUTPUT);                            //Ventil               

}

void loop() {

// 1. Vorbereitungsphase: Kompressorkessel wird aufgefüllt. Das Kompressorventil ist geschlossen. Auf dem LCD wird während dieser Phase "WAIT" angezeigt.

if(KompressorStatus == LOW){                    // wenn der Kompressor aus ist
  if(millis()-timestore>1800000){               // auf die Uhr sehen, ob die 30 Minuten schon rum sind, wenn ja
  digitalWrite(KompressorPin, HIGH);            // Kompressor einschalten
  timestore = millis();                         // und Uhrzeit notieren
  KompressorStatus = HIGH;                      // notieren, dass der Kompressor angeschaltet ist
  }                                          
} else {                                        // wenn der Kompressor an ist
if(millis()-timestore>300000){                  // auf die Uhr sehen ob die 5 Minuten schon rum sind, wenn ja
  digitalWrite (KompressorPin, LOW);            // Kompressor ausschalten
  KompressorStatus = LOW;                       // notieren, dass der Kompressor ausgeschaltet ist
  

// 2. Spielphase: Das Ventil ist geöffnet, dadurch wird das Spiel mit Druckluft versorgt. Während des Spiels wird auf dem LCD "PLAY" angezeigt.

  digitalWrite (VentilPin, HIGH);               // Ventil öffnen
  VentilStatus = HIGH;                          // notieren, dass das Ventil geöffnet ist                  
 }                                              // wenn die 5 Minuten noch nicht rum sind: weitergehen
} 

if(VentilStatus == HIGH){                       // wenn das Ventil geöffnet ist
  if(millis()-timestore> 600000){               // auf die Uhr sehen, 10 Minuten schon rum sind, wenn ja
  digitalWrite(VentilPin, LOW);                 // Ventil öffnen
  VentilStatus = LOW;                           // notieren, dass das Ventil geschlossen ist
   }
 } 



// Spielpause: Jetzt soll der Countdown, der im Hintergrund abläuft auf dem LCD erscheinen. Ich habe den Countdown an eine if- Bedingung geknüpft, dass dieser nur auf dem LCD erscheint, wenn KompressorStatus und VentilStatus == LOW sind.
  
if(millis()-timestore_Sekunden>1000){           // wenn eine Sekunde vergangen ist...
  s = s - 1;                                    // wird s um 1 dezimiert
  timestore_Sekunden = millis();                // dann wird timestore_Sekunden = millis()
  }
  
if(s = 0){                                      // wenn s bei 0 angekommen ist
  s = 60;                                       // wird s wieder 60
  m = m - 1;                                    // gleichzeitig wird m um eins dezimiert
}

if ( m = 0){                                    // wenn m bei 0 angekommen ist
m = 30;                                         // wird m wieder 30
}

if(KompressorStatus == HIGH){                   // während der Kompressor eingeschaltet ist wird "WAIT" auf dem LCD angezeigt
  lcd.setCursor(0,0);                           // Beginn beim ersten Zeichen in der ersten Zeile 
  lcd.print("WAIT");                            // mit dem Text „WAIT“
}
  if(VentilStatus == HIGH){                     // während das Ventil geöffnet ist wird "PLAY" auf dem LCD angezeigt
  lcd.setCursor(0,0);                           // Beginn beim ersten Zeichen in der ersten Zeile 
  lcd.print("PLAY");                            // mit dem Text „PLAY“
}

if (KompressorStatus == LOW)&& (VentilStatus == LOW){ // Wenn KopmressorStatus und Ventilstatus == LOW...
  lcd.setCursor(0,0);                                 // Startposition der Darstellung auf dem LCD festlegen. lcd.setCursor(0,0) bedeutet: Erstes Zeichen in der ersten Zeile.
  lcd.print("time to next game:");                    // Dort soll der Text „time to next game: “ erscheinen. 
  lcd.setCursor(0,1);                                 // Startposition der Darstellung auf dem LCD festlegen.
  lcd.print(m);                                       // Dort soll die variable m erscheinen.
  lcd.print (":");                                    // dann der Text ":"
  lcd.print(s);                                       // dann s
} 
}

Danke vielmals für Eure Antworten! Der Countdown funktioniert jetzt, aber das Einbetten in meinen vorherigen Sketch leider noch nicht. Kann mir da jemand weiterhelfen?

Hi

Zeile 84 - entferne die beiden inneren Klammern.
Durch die schließende Klammer ist die IF-bedingung beendet - die nächste öffnende Klammer, mit Deiner 2.ten Bedingung passt nicht zur Syntax einer IF-Abfrage.

Wenn die beiden inneren Klammern weg sind, hast Du zwei Prüfungen auf Gleichheit und in der Mitte ein &&, wodurch Beide gültig sein müssen, um die IF auszuführen.

Trotzdem sehe ich eine wesentliche Vereinfachung, wenn Du den Kram in eine State-Maschine/endlichen Automaten/Schrittkette umbaust.
Man könnte auch ganz stur die Sekunden hoch zählen und eben

  • 0...1'800'000 ... nix, Wartezeit, bis Kompressor an geht
  • 1'800'000 ... 2'100'000 Wartezeit, bis Kompressor wieder aus geht
  • 2'100'000 ... 2'700'000 Wartezeit, bis das Ventil geöffnet wird
    (sollte der Kompressor nicht am Schluss 'warten'? ... Bin verwirrt ...)

MfG

PS: Funktioniert nicht ist ... nicht so toll - wa?
Etwas genauer solltest Du das Problem schon umschreiben ...

LeonardoFiando:
Beim Kompilieren des Sketches wird an diesem Punkt eine Fehlermeldung angezeigt:

Die Fehlermeldung mit posten.
Es ist ein Klammerfehler.

Gruß Tommy

Ich poste das nächste Mal die Fehlermeldung mit!:slight_smile:

Jetzt funktioniert es. Danke!

Lieber postmaster-ino,

Ja Du hast Recht, ich will dass der Kompressor am Anfang läuft und am Ende wartet. Ich hatte einen Knoten im Gehirn:D. Ich habe den Sketch glaube ich jetzt erfolgreich verändert.

So soll es ablaufen:

5 Minuten lang Kompressor an…
5 Minuten lang Ventil auf…
20 Minuten lang Countdown runterzählen

Mir ist eben aufgefallen, dass die Schrift auf dem LCD, nach dem Übergang von “WAIT” zu “PLAY” komisch aussah. Ich habe den Befehl lcd.clear(); nach dem Ausschalten des Kompressors

if(millis()-timestore>300000){                  // auf die Uhr sehen ob die 5 Minuten schon rum sind, wenn ja
  digitalWrite (KompressorPin, LOW);            // Kompressor ausschalten
  KompressorStatus = LOW;                       // notieren, dass der Kompressor ausgeschaltet ist
  lcd.clear();

und nach dem Schließen des Ventils

if(VentilStatus == HIGH){                       // wenn das Ventil geöffnet ist
  if(millis()-timestore> 600000){               // auf die Uhr sehen, 10 Minuten schon rum sind, wenn ja
  digitalWrite(VentilPin, LOW);                 // Ventil öffnen
  VentilStatus = LOW;                           // notieren, dass das Ventil geschlossen ist
  lcd.clear();
   }

eingebaut, aber das hat es nicht so richtig gebracht. Könnt Ihr mir sagen was ich falsch mache?

Hier der ganze Sketch:

// LiquidCrystal Library

#include <LiquidCrystal.h>

int s = 60;                                     // Wert für Variable s  = 60
int m = 29;                                     // Wert für Varaible m = 30
unsigned long timestore_Sekunden;               // Variabler Speicher für Systemzeit

unsigned long timestore;                        // Variabler Speicher für Systemzeit
int KompressorStatus = LOW;                     //Kompressor is normally off
int KompressorPin = 1;
int VentilStatus = LOW;                         //Ventil is normally closed
int VentilPin = 2;

//initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);


void setup() {

lcd.begin(16, 2);
pinMode (1, OUTPUT);                            //Kompressor
pinMode (2, OUTPUT);                            //Ventil               

}

void loop() {

if(millis()-timestore>1800000){
  timestore = millis();
  }
  
// 1. Vorbereitungsphase: Kompressorkessel wird aufgefüllt. Das Kompressorventil ist geschlossen. Auf dem LCD wird während dieser Phase "WAIT" angezeigt.

if(KompressorStatus == LOW){                    // wenn der Kompressor aus ist
  if(millis()-timestore>0){               // auf die Uhr sehen, ob die 0 Minuten schon rum sind, wenn ja
  digitalWrite(KompressorPin, HIGH);            // Kompressor einschalten
  KompressorStatus = HIGH;                      // notieren, dass der Kompressor angeschaltet ist
  }                                          
} else {                                        // wenn der Kompressor an ist
if(millis()-timestore>300000){                  // auf die Uhr sehen ob die 5 Minuten schon rum sind, wenn ja
  digitalWrite (KompressorPin, LOW);            // Kompressor ausschalten
  KompressorStatus = LOW;                       // notieren, dass der Kompressor ausgeschaltet ist
  lcd.clear();
  

// 2. Spielphase: Das Ventil ist geöffnet, dadurch wird das Spiel mit Druckluft versorgt. Während des Spiels wird auf dem LCD "PLAY" angezeigt.

  digitalWrite (VentilPin, HIGH);               // Ventil öffnen
  VentilStatus = HIGH;                          // notieren, dass das Ventil geöffnet ist                  
 }                                              // wenn die 5 Minuten noch nicht rum sind: weitergehen
} 

if(VentilStatus == HIGH){                       // wenn das Ventil geöffnet ist
  if(millis()-timestore> 600000){               // auf die Uhr sehen, 10 Minuten schon rum sind, wenn ja
  digitalWrite(VentilPin, LOW);                 // Ventil öffnen
  VentilStatus = LOW;                           // notieren, dass das Ventil geschlossen ist
  lcd.clear();
   }
 } 



// Spielpause: Jetzt soll der Countdown, der im Hintergrund abläuft auf dem LCD erscheinen. Ich habe den Countdown an eine if- Bedingung geknüpft, dass dieser nur auf dem LCD erscheint, wenn KompressorStatus und VentilStatus == LOW sind.
  
if(millis()-timestore_Sekunden>1000){           // wenn eine Sekunde vergangen ist...
  s = s - 1;                                    // wird s um 1 dezimiert
  timestore_Sekunden = millis();                // dann wird timestore_Sekunden = millis()
  }
  
if(s == 0){                                      // wenn s bei 0 angekommen ist
  s = 60;                                       // wird s wieder 60
  m = m - 1;                                    // gleichzeitig wird m um eins dezimiert
}

if ( m == 0){                                    // wenn m bei 0 angekommen ist
m = 30;                                         // wird m wieder 30
}

if(KompressorStatus == HIGH){                   // während der Kompressor eingeschaltet ist wird "WAIT" auf dem LCD angezeigt
  lcd.setCursor(0,0);                           // Beginn beim ersten Zeichen in der ersten Zeile 
  lcd.print("WAIT");                            // mit dem Text „WAIT“
}
  if(VentilStatus == HIGH){                     // während das Ventil geöffnet ist wird "PLAY" auf dem LCD angezeigt
  lcd.setCursor(0,0);                           // Beginn beim ersten Zeichen in der ersten Zeile 
  lcd.print("PLAY");                            // mit dem Text „PLAY“
}

if (millis()-timestore_Sekunden>600000 && millis()-timestore_Sekunden<1800000 ){ // Wenn die 10 Minuten vergangen sind (in denen der Kompressor Druck aufgebaut hat (5 Minuten) und das Ventil geöffnet war (5 Minuten), dann...
  lcd.setCursor(0,0);                                 // Startposition der Darstellung auf dem LCD festlegen. lcd.setCursor(0,0) bedeutet: Erstes Zeichen in der ersten Zeile.
  lcd.print("time to next game:");                    // Dort soll der Text „time to next game: “ erscheinen. 
  lcd.setCursor(0,1);                                 // Startposition der Darstellung auf dem LCD festlegen.
  lcd.print(m);                                       // Dort soll die variable m erscheinen.
  lcd.print (":");                                    // dann der Text ":"
  lcd.print(s);                                       // dann s
} 
}

Du könntest mal Deine Einrückung verbessern. +T in der IDE hilft Dir dabei. Das steigert für Dich und für uns die Lesbarkeit.
Das halte ich für eine schlechte Idee:

pinMode (1, OUTPUT);  //Kompressor

Die Pins 0 und 1 werden für die Kommunikation mit dem PC gebraucht und sollten nicht mit etwas anderem belegt werden.

LCD haben einen festen Zeichensatz. Was sollen wir uns unter “sieht komisch aus” vorstellen?

Gruß Tommy

Lieber postmaster-ino,

ich habe mir heute schonmal überlegt, wie ich das Problem mit 08/15 Elektronik lösen könnte;) Das wäre auch eine Maßnahme gewesen:

Aber ich denke ich bin jetzt auf einem ganz guten Weg es auch mit µC hinzukriegen.

Herzliche Grüße Leonardo