Problem While-Schleife

Hallo Forum,
ich bin noch ein ziemlicher Neuling und bitte darum, dass ihr mir vielleicht ein paar Tipps geben könnte.
Ich habe eine Bewässerung gebastelt und programmiert, die im Grunde so funktioniert, wie ich es möchte.

Was jetzt noch dazu kam, war eine Sicherung des Wasserstandes im Behälter, damit die Pumpen nicht leer laufen. Dafür habe ich einen Schwimmschalter und eine LED, die anzeigen soll, wenn der Behälter leer ist.
Gedacht war, das bei geschlossenem Schwimmschalter die LED leuchtet und das Programm nicht zur Prüfung der Messwerte übergeht, bzw. die Relais abfallen, solange der Schwimmschalter geschlossen bleibt.

Beim momentanen Code ziehen bei geschlossenem Schwimmschalter, alle drei Relais (die Pumpen laufen) und die LED leuchtet so lange, wie der Schalter geschlossen ist. Ist der Schalter offen, erlischt die LED und die Relais fallen ab.

Was mache ich falsch? :-/

#define SENSORA 0
#define SENSORB 1
#define SENSORC 2

#define RELAISA 2
#define RELAISB 3
#define RELAISC 4

#define SWIM 6
#define LED 7

#define WERTH 370
#define WERTL 360

boolean RelaiszustandA = true;
boolean RelaiszustandB = true;
boolean RelaiszustandC = true;

void setup() {
  pinMode(RELAISA, OUTPUT);
  pinMode(RELAISB, OUTPUT);
  pinMode(RELAISC, OUTPUT);
  
  pinMode(SWIM, INPUT_PULLUP);
  pinMode(LED, OUTPUT);
  
  Serial.begin(9600);
}

void loop() {

  while(digitalRead(SWIM) == 0)
    {
    digitalWrite(LED, HIGH);
    } 
    digitalWrite(LED, LOW);
 { 
  //Pflanze1
    if((analogRead(SENSORA) < WERTL)&&(RelaiszustandA==LOW)) //Sensor wird abgefragt und wenn der Wert unter 370 ist UND das Relais gezogen ist, fällt es ab
      RelaiszustandA = true;      //Pumpe aus
    
    if((analogRead(SENSORA) > WERTH)&&(RelaiszustandA==HIGH)) //Sensor wird abgefragt und wenn der Wert über 450 ist UND das Relais nicht gezogen ist, zieht es an
      RelaiszustandA = false;   //Pumpe an

    digitalWrite(RELAISA, RelaiszustandA);  //Ausgang wird angesteuert
    Serial.print(" Sensor 1: ");
    Serial.println(analogRead(SENSORA));

 
  //Pflanze2
    if((analogRead(SENSORB) < WERTL)&&(RelaiszustandB==LOW))
      RelaiszustandB = true;      //Relais aus
    
    if((analogRead(SENSORB) > WERTH)&&(RelaiszustandB==HIGH))
      RelaiszustandB = false;   

    digitalWrite(RELAISB, RelaiszustandB);
    Serial.print(" Sensor 2: ");
    Serial.println(analogRead(SENSORB));


  //Pflanze3
    if((analogRead(SENSORC) < WERTL)&&(RelaiszustandC==LOW))
      RelaiszustandC = true;      //Relais aus
    
    if((analogRead(SENSORC) > WERTH)&&(RelaiszustandC==HIGH))
      RelaiszustandC = false;   

    digitalWrite(RELAISC, RelaiszustandC);
    Serial.print(" Sensor 3: ");
    Serial.println(analogRead(SENSORC));


    Serial.println();

  //Wenn eines der Relais gezogen ist, wird jede Sekunde die Messung wiederholt. Wenn keines gezogen ist, wird alle 30 Min gemessen
    if((RelaiszustandA==LOW)||(RelaiszustandB==LOW)||(RelaiszustandC==LOW))
    { 
      delay(1000);
    } else {
      delay(1800000);
    }
  } 
    }

Hi

Vorab: Welcher Arduino?
Bei UNO und NANO sind die Pins 0 und 1 pfui - hier hängt schon die USB-Schnittstelle dran!

Kommentare fehlen komplett in Deinem Sketch - so können wir nicht Mal erkennen, WAS Du Dir dabei DACHTEST - und sehen nur, was Du gemacht hast.

delay() ist ... blöd

Relaiszustand setzt Du Mal auf true/false, dann fragst Du auf HIGH/LOW ab - WAS bezweckst Du, WANN sind die Relais gezogen?
Selber definiere ich mir eine Hilfs-Variable:
const bool _AN=LOW; //Ausgangspegel für Relais AKTIV
const bool _AUS=!_AN;

So SEHE ich im Code, was das Relais machen soll und muß nicht immer über Kreuz denken, weil das Groh der Relais-Karten eben LOW-Aktiv ist.

MfG

Edit
Da die Sensoren am ANALOGIN hängen, geht hier auch 0 und 1 - schöner wäre A0 und A1 gewesen - hier vertuscht die Arduino-IDE Das etwas, weil Diese die 0 beim analogRead intern auf A0 'umbiegt'.
Wenn A0 geschrieben wird, greifen sowohl digitalRead wie analogRead auf den gleichen Pin zu.
Sorry für die folgende Verwirrung in #3

Hallo,

hab ich das richtig verstanden ? Der Schwimmerschalter ist eine leer-Meldung ? Bei leer soll die LED angehen , aber der Motor aus ?

wenn die LED rchtig leuchtete , musst Du für den Motor die Abfrage negieren. Abfrage ist if ()

while(digitalRead(SWIM) == 0)
    {
    digitalWrite(LED, HIGH);
    }
    digitalWrite(LED, LOW);
 {

wozu soll das denn sein ? warum eine while schleife .

weiter unten arbeitest Du mit if , warum machst Du das bei der LED anders?

dann solltest Du das delay () rausnehmen, da hängt das Ding stundenlang in einer Wartepause und lann auf nichts mehr reagieren. Such mal nach dem Nachtwächter und schau dir BlinkWithoutDelay an und verwende anstelle von delay() milllis()

Heinz

Danke für die ersten Meldungen,

im Anhang nochmal der Code besser kommentiert.
Ich habe meinen Sketch aus Versatzstücken anderer Sketche zusammengesetzt und bissl probiert, bis es so gelaufen ist, wie ich es gerne hätte. Ich bin jetzt leider nicht so der Programmierer.

Hier handelt es sich um einen Arduino Mega. Ich habe den Sketch aber auch auf einem UNO laufen (noch nicht richtig aufgebaut). Gibt es beim UNO Probleme bei den analogen Eingängen 0 und 1 (wg Bemerkung USB-Schnittstelle)?

Der Sketch fragt alle 30min die Sensoren ab. Übersteigt der Wert 370, dann zieht das zum Sensor zugehörige Relais an und nun werde alle 1000ms die Sensoren erneut abgefragt. Fällt der Wert des Sensors unter 360, so fällt das Relais ab und es werde erst wieder in 30min erneut die Sensoren abgefragt (wenn alle Relais abgefallen sind).

Ich möchte den Schwimmschalter als elegante Sicherung, damit die Relais alle abfallen, solange nicht genug Wasser im Behälter ist. So jedenfalls meine Gedanken.

#define SENSORA 0 //analog Pins 
#define SENSORB 1
#define SENSORC 2

#define RELAISA 2 //digital Pins
#define RELAISB 3
#define RELAISC 4
#define SWIM 6  
#define LED 7

#define WERTH 370 //wird dieser Messwert überschritten, zieht das jeweilige Relais an
#define WERTL 360 //wird dieser Messwert unterschritten, fällt das jeweilige Relais ab

boolean RelaiszustandA = true;  //diese Angaben habe ich aus einem anderen Sketch übernommen, was sie genau machen, weiss ich nicht, hat bisher halt funktioniert
boolean RelaiszustandB = true;
boolean RelaiszustandC = true;

void setup() {
  pinMode(RELAISA, OUTPUT);
  pinMode(RELAISB, OUTPUT);
  pinMode(RELAISC, OUTPUT);
  
  pinMode(SWIM, INPUT_PULLUP);
  pinMode(LED, OUTPUT);
  
  Serial.begin(9600);
}

void loop() {

  while(digitalRead(SWIM) == 0) //wenn der Schwimmschalter geschlossen ist, soll die LED leuchten und alle Relais abfallen, solange der Schalter geschlossen ist. Wenn der Schalter wieder offen ist, soll das Programm normal weiterlaufen und die LED erlöschen.
    {
    digitalWrite(LED, HIGH);
    } 
    digitalWrite(LED, LOW);
 { 
  //Pflanze1
    if((analogRead(SENSORA) < WERTL)&&(RelaiszustandA==LOW)) //Sensor wird abgefragt und wenn der Wert unter 360 ist UND das Relais gezogen ist, fällt es ab
      RelaiszustandA = true;      //Pumpe aus
    
    if((analogRead(SENSORA) > WERTH)&&(RelaiszustandA==HIGH)) //Sensor wird abgefragt und wenn der Wert über 370 ist UND das Relais nicht gezogen ist, zieht es an
      RelaiszustandA = false;   //Pumpe an

    digitalWrite(RELAISA, RelaiszustandA);  //Ausgang wird angesteuert
    Serial.print(" Sensor 1: ");
    Serial.println(analogRead(SENSORA));

 
  //Pflanze2
    if((analogRead(SENSORB) < WERTL)&&(RelaiszustandB==LOW))
      RelaiszustandB = true;      //Relais aus
    
    if((analogRead(SENSORB) > WERTH)&&(RelaiszustandB==HIGH))
      RelaiszustandB = false;   

    digitalWrite(RELAISB, RelaiszustandB);
    Serial.print(" Sensor 2: ");
    Serial.println(analogRead(SENSORB));


  //Pflanze3
    if((analogRead(SENSORC) < WERTL)&&(RelaiszustandC==LOW))
      RelaiszustandC = true;      //Relais aus
    
    if((analogRead(SENSORC) > WERTH)&&(RelaiszustandC==HIGH))
      RelaiszustandC = false;   

    digitalWrite(RELAISC, RelaiszustandC);
    Serial.print(" Sensor 3: ");
    Serial.println(analogRead(SENSORC));


    Serial.println();

  //Wenn eines der Relais gezogen ist, wird jede Sekunde die Messung wiederholt. Wenn keines gezogen ist, wird alle 30 Min gemessen
    if((RelaiszustandA==LOW)||(RelaiszustandB==LOW)||(RelaiszustandC==LOW))
    { 
      delay(1000);
    } else {
      delay(1800000);
    }
  } 
    }

Tomcat1969:
...
Was mache ich falsch? :-/
...

    }

}
   }

Zunächst machst Du den Fehler, sehr schlecht lesbaren Code zu schreiben. Da bekomme ich nicht die geringste Lust, mir das näher anzusehen. Gerade bei der Fehlersuche ist leicht lesbarer Code Gold wert. Wenn ich z. B. Klammerungen wie die zitierte sehe, vergeht's mir.

Wenn Du möchtest, dass mehrere Sachen gleichzeitig ablaufen sollen, machst Du das am besten mit einem „endlichen Automat“. Guck z. B. hier.

Gruß

Gregor

PS: Ach ja: Mein Getexte zu „schönem“ Code

Hallo,

das hab ich mir schon gedacht mit dem delay , dennoch warum ein while für den Schwimmrschalter. er sollte logisch verknüpft sein mit dem Feuchtewert. Warum schaltest Du die Pumpe nur aus wenn sie ein ist. völlig unnötig.

if((analogRead(SENSORA) > WERTL)&&(schwimmerschalter_ok) ///Pumpe ein

if((analogRead(SENSORA) < WERTL)|| (!schwimmershalter_ok)// Pumpe aus

so was in der Art

Heinz

Hallo Heinz,

das ist eine gute Idee (die ich auch verstehe :wink: ). Das werd ich mal versuchen umzusetzen.

Danke!
Thomas

Lieber Heinz,
danke für Deine Idee, es hat - soweit ich das bisher sehe - geklappt :slight_smile: