Ratlos: Sketch nach Restart fehlerhaft

Hallo Gemeinde,
Ich bin noch relativer Einsteiger in diesem ganzen Bereich hier, habe meine UNO-Klons aber schon seit ein paar Monaten erfolgreich am laufen.

Nun schrieb ich einen Sketch mit folgender (grob zusammengefasster) Aufgabe:

Ein DHT11 wird alle 5 Sekunden ausgelesen und die entsprechenden Temperatur- und Feuchtigkeitswerte auf einem LCD angezeigt. Wenn die Temperatur einen Maximalwert überschreitet, fängt das Display im 0.5Sek Takt an zu blinken. Parallel dazu wurde eine Zeitschaltuhr per RTC3231 und einem Relais ebenfalls integriert.

Jetzt zur Problematik:
Wenn ich den Sketch auf das Board überspiele funktioniert (noch angeschlossen am Rechner) alles so, wie es soll. Wehe jedoch ich A) restarte das Board, oder B) Trenne die Stromversorgung und stelle diese wieder her

Dann passiert folgendes:
Der DHT11 wird nichtmehr alle 5, sondern schätzungsweise alle 0.01sek ausgelesen und das Display blinkt nicht im 0.5 Sekunden Intervall sondern (und jetzt wirds richtig komisch) immer doppelt so schnell als vor dem Restart. Also zuallererst 0.5 Sek Intervall -> restart -> 0.25Sek -> restart -> 0.125sek ->etc etc.

Ich frage mich, wie das sein kann, da meines Wissens beim Ausschalten/Restarten vom Arduino alle Variablen verloren gehen und somit im Speicher wieder exakt das selbe Zeug steht, als hätte ich den Sketch grade frisch aufgespielt.

Wie könnt ihr euch das erklären?

Viele Grüße

Der DHT11 ist bissel problematisch.
Das hab ich gestern auch erfahren: wenn man den zu schnell (oder zu oft, das weiss ich nicht) ausliest, baut irgendwie die ganze Lib Mist.
Bei mir äusserte sich das so:

-es wurde die RTC ausgelesen und auf Display geschrieben.
-dann wurde die Temperatur vom DHT11 geholt, die der RTC dazu, alles verwurstet und geschrieben
-dann wurde die Luftfeuchtigkeit vom DHT11 geholt und aufs Display geschrieben.

DABEI verrutschte mir immer wieder mal die Anzeige der Luftfeuchte !
Hab zwei Tage dran gegrübelt, woran das liegen könnte- erfolglos (ich mach sowas schon ne Weile...).
Dann habe ich mal die Reihenfolge getauscht:
-RTC
-Luftfeuchte
-Temperatur
Ergebnis: jetzt verrutscht die Temperaturanzeige!
Mit nem anständigen delay() zwischen den beiden Zugriffen auf den DHT11 lief es plötzlich....

Ich hab es nun quick&dirty so gelöst:

-RTC
-Temperatur
-RTC
-Luftfeuchtigkeit

Problem behoben!
Interessant ist, dass dieses "schnelle zugreifen" auch Probleme in ganz anderen Bereichen auslösen kann- daher ist das sehr schwer herauszufinden- meine Displayausgaben werden quasi in eigenen, völlig unabhängigen Tasks gemacht, da ist das auslesen der Werte längst Geschichte. :confused:

Also: bau mal, vor dem auslesen des DHT11 anständige delay() ein- ne Zentelsekunde oder so, und versuch es dann.

Erstmal vielen Dank für deine Antwort. Ich habe auch schon oft gehört, dass man den DHT11 nicht öfter als 1x pro 2Sek auslesen darf.

Ich habe mir in meinem Sketch Temperatur & Luftfeuchtigkeit immer alle 5 Sek gleichzeitig ausgelesen mit:

DHT.read11(dht_apin);

Und dann halt nur noch die Werte, die in der DHT-Struktur-Variablen gespeichert sind, benutzt.

Wüsste jetzt auch gar nicht, wie man nur die Temp oder nur die Luftfeuchte auslesen kann.

Habe nun vor und nach das Auslesen mit DHT.read11(dht_apin); jeweils 1 Zehntel Sekunde gesetzt. Brachte leider auch keine Besserung.

Viele Grüße

ijustdontcare:
Habe nun vor und nach das Auslesen mit DHT.read11(dht_apin); jeweils 1 Zehntel Sekunde gesetzt. Brachte leider auch keine Besserung.

Dann zeige uns doch deinen Sketch, evtl. erkennen wir da ja das Problem.

Der Code ist im Vergleich zu seiner eigentlichen Funktion ziemlich komplex, weil ich einfach viel Optimierung durchgeführt habe, die für den Benutzer eben angenehmer ist. Darunter fällt das vermeiden von Doppelklicks an Knöpfen, dass das Display nach einem eventuellen Blinken wieder den vorher eingestellten AN oder AUS Zustand erreicht (und nicht halt einfach beim letzten Blinkzustand "stehenbleibt"), etc.

Ich habe so viel Kommentiert wie grade ging, vielleicht könnt ihr ja Teile davon nachvollziehen.. Ist etwas chaotisch, da ich kein routinierter Coder bin. Vorgegebenes Blinkintervall ist übrigens 1,0 Sek und nicht 0.5, wie ich weiter oben erwähnt habe.

#include <dht.h>
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include <ds3231.h>
#include <rtc_ds3231.h>

#define I2C_ADDR 0x27
#define Rs_pin 0
#define Rw_pin 1
#define En_pin 2
#define BACKLIGHT_PIN 3
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7
bool LCD_flag=1;

//Definitionen und Variablen zur Temperaturmessung
#define dht_apin A0 // Lege A0 als dht-Pin fest
dht DHT; //DHT struct Variable
int temp=0; 
int luft=0; 
int zaehler_f_check=1795; //Zahlvariable um eine schleife alle 1800sek (halbe stunde) aktivieren zu können
int zaehler_f_auslesen=5; //Zählvariable um eine schleife ale 5 Sek aktivieren zu können
int eingabe_min=10; //Fuer eingabe Mindesttemp
int eingabe_max=10; //Fuer eingabe Maximaltemp
bool eingabe_backlight=1;

//Variable zur Relaissteuerung
const int relaisPin1 = 3; // Zur Steuerung Temperaturabhängig (Wenn minimaltemp erreicht, dann schalte relais an)
const int relaisPin2 = 5; // Zur Steuerung Zeitabhängig (Wenn im Fenster der Zeitschaltuhr, dann schalte relais an)

//Zeitschaltuhr
bool zsu_ja=0;
int zsu_anfang=0;
int zsu_ende=0;

//LCD Funktion
LiquidCrystal_I2C lcd(I2C_ADDR, En_pin, Rw_pin, Rs_pin, D4_pin, D5_pin, D6_pin, D7_pin);

//Variablen für Knöpfe
int button1=13; // Knopf 1 ist am Pin 13 angebracht und wird dementsprechend in der Variablen so festgelegt
int button2=12; // Knopf 2 ist am Pin 12 angebracht und wird dementsprechend in der Variablen so festgelegt
int wert1=HIGH;
int wert2=HIGH;
int warten=0;
int timetemp=0;

void setup()
{
 lcd.begin (16,2);
 lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE); //Erlaube den Zugriff auf das EIN/AUS-Schalten der Hintergrundbeleuchtung
 lcd.setBacklight(HIGH); // LCD von anfang an beleuchtet
 pinMode(relaisPin1, OUTPUT); 
 pinMode(relaisPin2, OUTPUT); 
 digitalWrite(relaisPin1, HIGH); //Relais von anfang an aus
 digitalWrite(relaisPin2, HIGH); //Relais von anfang an aus
 digitalWrite(button1, HIGH); // Aktiviert pull up für knopf 1
 digitalWrite(button2, HIGH); // Aktiviert Pull up für Knopf 1
 DS3231_init(DS3231_INTCN);

// Der folgende Codeabschnitt ist lediglich für eine eingabe von Tempwert Max, Tempwert Min, Zeitschaltuhr aktiviert JA/Nein, und falls ZSU Ja -> Start-Zeit und Endzeit
// Um Eine saubere eingabe mit den Knöpfen zu ermöglichen habe ich code geschrieben, dass ein knopf nur alle 200ms nach dem letzten drücken wieder gedrückt werden kann, damit keine doppel/dreifachklicks durch einmaliges drücken entstehen
 bool freigabe_min=1;
 signed int freigabe_min_zeit=0;
 lcd.clear(); // Löche alles auf dem LCD
 lcd.setCursor (0,0); // Gehe im Display in die erste Zeile an den Anfang
 lcd.print("Temperatur Min?"); // Schreibe "Temperatur Min?" aufs Display
 lcd.setCursor(0,1);
 lcd.print(eingabe_min);
 while(digitalRead(button2)==HIGH)
 {
  lcd.setCursor(0,1);
  lcd.print(eingabe_min);
  if(digitalRead(button1)==LOW && freigabe_min==1){if(eingabe_min==59){eingabe_min=10; freigabe_min=0; freigabe_min_zeit=millis();}else{eingabe_min=eingabe_min+1; freigabe_min=0; freigabe_min_zeit=millis();}}else{;}
  lcd.print("C");
  if(millis() > (freigabe_min_zeit + 200)){freigabe_min=1;}
  delay(5);
 }
 bool freigabe_max=1;
 signed int freigabe_max_zeit=0;
 lcd.clear(); // Löche alles auf dem LCD
 eingabe_max=(eingabe_min+1);
 lcd.setCursor (0,0); // Gehe im Display in die erste Zeile an den Anfang
 lcd.print("Temperatur Max?"); // Schreibe "Temperatur Max?" aufs Display
 lcd.setCursor(0,1);
 lcd.print(eingabe_max);
 delay(300);
 while(digitalRead(button2)==HIGH)
 {
  lcd.setCursor(0,1);
  lcd.print(eingabe_max);
  if(digitalRead(button1)==LOW && freigabe_max==1){if(eingabe_max==60){eingabe_max=(eingabe_min+1); freigabe_max=0; freigabe_max_zeit=millis();}else{eingabe_max=eingabe_max+1; freigabe_max=0; freigabe_max_zeit=millis();}}else{;}
  lcd.print("C");
  if(millis() > (freigabe_max_zeit + 200)){freigabe_max=1;}
  delay(5);
 }
 
 lcd.clear(); // Löche alles auf dem LCD
 lcd.setCursor (0,0); // Gehe im Display in die erste Zeile an den Anfang
 lcd.print("Zeitschaltuhr?"); // Schreibe "Zeitschaltuhr?" aufs Display
 lcd.setCursor(0,1);
 lcd.print("JA/NEIN");
 delay(300);
 while((digitalRead(button1)==HIGH) && (digitalRead(button2)==HIGH))
 {delay(10);}
 if(digitalRead(button1)==LOW){zsu_ja=1;} else{zsu_ja=0;}

if(zsu_ja==1)
{
 bool freigabe_start=1;
 signed int freigabe_start_zeit=0;
 lcd.clear(); // Löche alles auf dem LCD
 lcd.setCursor (0,0); // Gehe im Display in die erste Zeile an den Anfang
 lcd.print("Beginn Lampe?"); // Schreibe "Beginn Lampe?" aufs Display
 lcd.setCursor(0,1);
 lcd.print(zsu_anfang);
 delay(300);
 while(digitalRead(button2)==HIGH)
 {
  if(digitalRead(button1)==LOW && freigabe_start==1){lcd.setCursor(0,1); lcd.print("     "); if(zsu_anfang==24){zsu_anfang=0; freigabe_start=0; freigabe_start_zeit=millis();}else{zsu_anfang=zsu_anfang+1; freigabe_start=0; freigabe_start_zeit=millis();}}else{;}
  lcd.setCursor(0,1);
  lcd.print(zsu_anfang);
  lcd.print("Uhr");
  if(millis() > (freigabe_start_zeit + 200)){freigabe_start=1;}
  delay(5);
 }
 bool freigabe_ende=1;
 signed int freigabe_ende_zeit=0;
 lcd.clear(); // Löche alles auf dem LCD
 lcd.setCursor (0,0); // Gehe im Display in die erste Zeile an den Anfang
 lcd.print("Ende Lampe?"); // Schreibe "Ende?" aufs Display
 delay(300);
 lcd.setCursor(0,1);
 lcd.print(zsu_ende);
 while(digitalRead(button2)==HIGH)
 {
  if(digitalRead(button1)==LOW && freigabe_ende==1){lcd.setCursor(0,1); lcd.print("     ");if(zsu_ende==24){zsu_ende=0; freigabe_ende=0; freigabe_ende_zeit=millis();}else{zsu_ende=zsu_ende+1; freigabe_ende=0; freigabe_ende_zeit=millis();} if(zsu_ende==zsu_anfang){zsu_ende=zsu_ende+1;if(zsu_ende==25){zsu_ende=1;}}else{;}}else{;}
  lcd.setCursor(0,1);
  lcd.print(zsu_ende);
  lcd.print("Uhr");
  if(millis() > (freigabe_ende_zeit + 200)){freigabe_ende=1;}
  delay(5);
 }
}
else{;}
}
void loop()
{
  if(zaehler_f_auslesen==5) // Wenn Zähler den Wert 5 hat (Wenn der Zähler 5 erreicht hat, sind ca 5 Sekunden vergangen --> Einfach: Frage alle 5 Sekunden neue Temperaturwerte ab und zeige diese an)
 {
  delay(10);
  struct ts t;
  DS3231_get(&t);
  if((zsu_ja==1) && (zsu_ende>zsu_anfang)){if((t.hour>=zsu_anfang) && (t.hour<zsu_ende)){digitalWrite(relaisPin2, LOW);}else{digitalWrite(relaisPin2, HIGH);}}else{;} // Wenn Zeitschaltuhr gewollt und aktuelle Zeit im gewünschten Intervall, schalte Relais an (Bedingung 1)
  if((zsu_ja==1) && (zsu_ende<zsu_anfang)){if((t.hour>=zsu_anfang) || (t.hour<zsu_ende)){digitalWrite(relaisPin2, LOW);}else{digitalWrite(relaisPin2, HIGH);}}else{;} // Wenn Zeitschaltuhr gewollt und aktuelle Zeit im gewünschten Intervall, schalte Relais an (Bedingung 2)
  DHT.read11(dht_apin); // Lies den dht_apin -> aus. Oben definiert, dass der dht_apin der Analogpin A0 des Arduinos ist
  if((temp==DHT.temperature) && (luft==DHT.humidity)) {;} // Wenn die aktuellen Temperatur&Luftfeuchtigkeitswerte der vorherigen Messung entsprechend, dann mache nichts (schreibe sie nicht nochmal aufs display, weil das so ein "flackern" verursacht --> reiner Schönheitsaspekt)
  else //Wenn sich jedoch ein Wert im Vergleich zur letzten Messung geändert hat, dann schreibe die neuen Werte aufs display
  {
   lcd.clear(); 
   lcd.setCursor (0,0); 
   lcd.print("Temperatur:  "); 
   temp=DHT.temperature; // Temperatur, die in Form XX.X geliefert wird in die int-Variable temp. geschrieben damit Nachkommastelle abgeschnitten wird
   lcd.print(temp); 
   lcd.print("C");
   lcd.setCursor(0,1); 
   luft=DHT.humidity; // Luftfeuchtigkeit, die in Form XX.X geliefert wird in die int-Variable luft geschrieben damit Nachkommastelle abgeschnitten wird
   lcd.print("Luftfeuchte: ");
   lcd.print(luft);
   lcd.println("%");
  }
  zaehler_f_auslesen=0; //Setze Zähler wieder auf 0 zurück damit er wieder (ca.) pro sekunde um 1 erhöht wird und bei wert 5 wieder die if-schleife aktiviert
 }
 else{;} //Anderenfalls (Also wenn Zähler 1,2,3,4 ist) dann mache gar nichts
 zaehler_f_auslesen=zaehler_f_auslesen+1; // 1. Variable Zähler wird um 1 erhöht (ca. jede sekunde)
 zaehler_f_check=zaehler_f_check+1; // 2. Variable Zähler wird um 1 erhöht (ca. jede sekunde)
 
 if(zaehler_f_check==1800) // Wenn Zähler den Wert 1800 hat, ist ca eine halbe Stunde vergangen --> Einfach: Führe jede halbe Std einen Check der Temperaturen hinsichtlich des Relais 1 durch)
 {
  if(temp < eingabe_min) 
  {
    digitalWrite(relaisPin1, LOW); 
  }
  else{;} 
  
  if(temp > eingabe_min) 
  {
    digitalWrite(relaisPin1, HIGH); 
  }
  else{;} 
  
  zaehler_f_check=0; // Der Zähler wird auf 0 zurückgesetzt. Somit braucht es wieder ca eine halbe Std, bis er erneut 1800 erreicht
 }

 if(temp>eingabe_max) // Wenn aktueller Temperaturwert über der Max-Temperatur liegt, die angegeben wurde, soll das relais 1 auf jeden fall aus und das display alle 0.5 sek blinken
 {
  digitalWrite(relaisPin1, HIGH); // ..... dann schalte Relais 1 auf jeden fall aus (überhitzungsschutz jede sekunde)
  if(eingabe_backlight==1) // Wenn der nutzer das Display vom benutzer definiert eingeschaltet hat, Blinke mit jedem durchgang (ca 1x pro sek).
  {
   if(LCD_flag==0)
   {
     lcd.setBacklight(HIGH); .
     LCD_flag=1; 
   } 
   else // Andernfalls 
   {
     lcd.setBacklight(LOW);
     LCD_flag=0; 
   }
  }
  else{;} // Wenn der nutzer das Display ausgeschalten hat, Blinke nicht
 }
 else // Anderenfalls (also wenn keine Temperatur_Max überschreitung mehr auftritt, dann schalte das display wieder ein wenn der benutzer es vor dem blinken auch ein hatte, oder aus wenn er es davor auch aus hatte)
 {
  if((LCD_flag==0) && (eingabe_backlight==1))
  {
   lcd.setBacklight(HIGH);
   LCD_flag=1;
  }
  else{;}
 }
 
if(warten==1){warten=0;} // Benötigte Variablenrechnung um später versehentliche Doppelklicks zu vermeiden
if(warten==2){warten=1;} // Benötigte Variablenrechnung um später versehentliche Doppelklicks zu vermeiden

for(int i;i<101;i++) //100x schlaufe mit je 10ms = 1 sek durchlaufzeit mit ständiger Bereitschaft das signal vom knopf zu empfangen mit dem man das Display jederzeit manuell aus schalten kann (bzw an, aber dann wird es bei >maxtemp auch blinken)
{
 
 wert1 = digitalRead(button1);
 if((warten==2) && (timetemp<51) && (i==(timetemp+50))){warten=0;}
 if((warten==1) && (i==(timetemp-50))){warten=0;}
 if((wert1==LOW) && (warten==0))
 {
  timetemp=i;
  warten=2;
  if(eingabe_backlight==1)
  {
   lcd.setBacklight(LOW);
   eingabe_backlight=0;
  }
  else
  {
   lcd.setBacklight(HIGH);
   eingabe_backlight=1;
  }
 }
 delay(10);
}
}

Ohne mir den Sketch bisher weiter anzusehen, die Frage:

Warum verwendest du 2 Libraries für das Display und 2 Libraries für die RTC.

Das LCD.h kannst du sicher entfernen, bei dem für die RTC musst du selbst ermitteln, welches das richtige ist.

Hier kann auch schon der Fehler versteckt sein.

Du hast absolut recht. Ist mir gar nicht aufgefallen. Ist wohl ein Relikt aus der Versuchs/Probierphase mit dem Sketch.

Hab jetzt nur noch folgendes verwendet:

#include <dht.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <ds3231.h>

Eine Besserung bezogen auf das eigentliche Problem brachte dies leider nicht.

Ok, dann müssen wir den Sketch mal durchschauen.

Es fehlt für die Tastereingänge der "pinMode":

pinMode(button1, INPUT);
pinMode(button2, INPUT);

Und wenn duschreibst:

pinMode(button1, INPUT_PULLUP);
pinMode(button2, INPUT_PULLUP);

Dann sparst du das "HIGH-setzen".

Und das mit deinen "while"-Schleifen im Setup ist gefährlich.
Da kann sich das System festsetzen.

Setze da lieber if-Anweisungen ein.

@HotSystems
erstmal Danke, dass du dir meinen langen Codesalat vornimmst.

Den pinMode für die Knöpfe habe ich hinzugefügt.

Nun weiß ich nicht so recht, wie ich das mit den IF-Schleifen umsetzen soll. Ich möchte ja innerhalb einer Schleife so lange warten (in der Zeit kann der User so oft er will mit dem einen Button die entsprechenden Werte verändern), bis die Eingabe mit dem anderen Knopf bestätigt wird.

Sprich: "Solange nicht der Bestätigungsknopf gedrückt wurde, wiederhole die Eingabeabfrage für den Wert XYZ immer weiter".

Wie kann ich das mit einer IF-Schleife realisieren? Denn die läuft ja nach meinem Kentnissstand genau 1x durch und dann ist fertig.

ijustdontcare:
Wie kann ich das mit einer IF-Schleife realisieren?

Überhaupt nicht.

Es gibt keine IF-Schleifen.

Whandall:
Es gibt keine IF-Schleifen.

Hier hat Whandall recht, das sind if-Anweisungen.

Dann versteh ich aber nicht, wieso die while-Schleifen im Setup sind.
Wenn du damit Einstellungen verändern möchtest, gehört das in die Loop.

Dann funktioniert es auch, weil er ja immer wieder diese Anweisung auswertet.

Whandall:
Es gibt keine IF-Schleifen.

:confused: You got me.

Wobei ich jetzt nicht weiß, ob das ausschließlich dem Ausdruck gelten sollte, und/oder ob es auch technisch nicht möglich ist.

Dann die Frage etwas genereller: Kann ich die While-Schleifen in diesem Fall umgehen?

HotSystems:
Hier hat Whandall recht, das sind if-Anweisungen.

Dann versteh ich aber nicht, wieso die while-Schleifen im Setup sind.
Wenn du damit Einstellungen verändern möchtest, gehört das in die Loop.

Dann funktioniert es auch, weil er ja immer wieder diese Anweisung auswertet.

Mein Gedanke:
Im Setup möchte ich nur zu Beginn des Programmstarts den Nutzer die Parameter festlegen lassen.

Anschließend läuft dann der Loop, der Sekunde für Sekunde die gemessenen Werte mit den eingegebenen Werten vergleicht und daraufhin Aktionen durchführt oder eben nicht.

Würde ich jetzt die Eingabe-Schleifen in den Loop mit reinpacken, müsste ich als Nutzer jeden Loop (in diesem Fall: jede Sekunde) meine Parameter neu eingeben müssen. Oder übersehe ich da etwas?

Du müsstest eine Art Menü einbauen, indem diese Werte festgelegt werden.

Bei einem Neustart springst du automatisch ins Menü.

Mit einer Taste springst du ins Menü, mit der zweiten änderst du den Wert und springst mit der anderen wieder raus. Als Komfort speicherst du die Werte evtl. noch im EEProm.

Wenn alles in der Loop läuft, kannst du wunderbar mit einer if-Anweisung arbeiten.

Ich vermute auch, hier liegt das Problem.
Die While-Schleifen sind meist "ein Krampf".

HotSystems:
Du müsstest eine Art Menü einbauen, indem diese Werte festgelegt werden.

Bei einem Neustart springst du automatisch ins Menü.

Mit einer Taste springst du ins Menü, mit der zweiten änderst du den Wert und springst mit der anderen wieder raus. Als Komfort speicherst du die Werte evtl. noch im EEProm.

Wenn alles in der Loop läuft, kannst du wunderbar mit einer if-Anweisung arbeiten.

Ich vermute auch, hier liegt das Problem.
Die While-Schleifen sind meist "ein Krampf".

Ich glaube, wir reden gerade etwas aneinander vorbei. Deinen Gedanken verstehe ich, auch wenn ich noch den Punkt noch nicht nachvollziehen konnte, was der Vorteil davon ist, dieses Menü in die Loop-Funktion zu packen anstatt in die Setup-Funktion. In meinem Falle ist es nämlich nur wichtig, bei einem Neustart des Arduinos die Werte einmalig eingeben zu können. Die Werte müssen während des Programmablaufs nicht geändert werden.

Zu den While-Schleifen:
Sagen wir du befindest dich im Menüpunkt 1: Auf dem Display Steht: "Bitte Minimaltemperatur eingeben".

Du hast nun 2 Knöpfe. Zu beginn steht 10°C da. Mit dem linken Knopf erhöht sich der angezeigte Wert immer um 1 pro Knopfdruck (bei 60°C springt der Wert wieder auf 10°C zurück, falls du mal versehentlich "zu weit" geklickt haben solltest). Mit dem rechten Knopf bestätigst du deine Eingabe und springst zum nächsten Menüpunkt.

Nur das habe ich in der while-Schleife realisieren wollen. "Warte so lange bis der rechte Knopf gedrückt wird und übernehme den 'ausgewählten' Wert in eine Variable".

Für diese reine Eingabe-While-Schleife fällt mir keine gleichwertige Lösung per IF-Anweisung ein.

ijustdontcare:
..."Warte so lange bis der rechte Knopf gedrückt wird und übernehme den 'ausgewählten' Wert in eine Variable"....
Für diese reine Eingabe-While-Schleife fällt mir keine gleichwertige Lösung per IF-Anweisung ein.

Da das in der Loop passiert, geht es genau so.

HotSystems:
Da das in der Loop passiert, geht es genau so.

Aber die Loop-Funktion wiederholt doch den kompletten Programmablauf und spult innerhalb des Ablaufs ja auch nur Punkt für Punkt ohne innere Wiederholungen ab. Und das will ich ja nicht. Ich will innerhalb des Programmablaufs bestimmte Bereiche loopen.

Oder stehe ich gerade auf dem Schlauch, und man kann innerhalb der Haupt-Loop-Funktion auch beliebig viele innere Loopfunktionen erstellen? Und wenn ja, wie kommt man aus einer Loopfunktion wieder heraus?

ijustdontcare:
Aber die Loop-Funktion wiederholt doch den kompletten Programmablauf und spult innerhalb des Ablaufs ja auch nur Punkt für Punkt ohne innere Wiederholungen ab. Und das will ich ja nicht. Ich will innerhalb des Programmablaufs bestimmte Bereiche loopen.

Und das machst du mit einer if-Anweisung.

Oder stehe ich gerade auf dem Schlauch, und man kann innerhalb der Haupt-Loop-Funktion auch beliebig viele innere Loopfunktionen erstellen? Und wenn ja, wie kommt man aus einer Loopfunktion wieder heraus?

Du kommst mit deinen Bezeichnungen etwas durcheinander.

Es gibt nur eine Loop. Du kannst innerhalb der Loop per Anweisung in verschiedene Funktionen springen.

Ich möchte dich aber nicht auf eine falsch Spur bringen.

Ich vermute nur, das Problem liegt im Setup, welches durch die while-Schleifen nicht problemlos sind.

Kannst du nicht das Setup durch feste Werte ersetzen, um testweise von den while-Schleifen weg zu kommen.

Dafür gibt es Status-Variablen, so dass man innerhalb von loop() nur bestimmte Dinge tut je nachdem wo man gerade im Programm-Ablauf ist.

Normal macht man sowas:

void loop()
{
   eingabe();
   verarbeitung();
   ...
}

Jede Funktion nicht-blockierend, so dass sie sich nicht behindern. eingabe() fragt z.B. nur ab ob was gedrückt (oder was auf Serial ankam) wurde und kehrt sofort wieder zurück wenn nicht.