Problem mit if- im Sketch

Hallo liebe communitiy,

Ich habe ein Problem mit einer if- Bedingung, das ich einfach nicht verstehe, es wäre so schön wenn mich jmd. erlösen könnte!

Es handelt sich um diese Intervallsteuerung:

unsigned long timestore;                            // Variabler Speicher für 15 Minuten und 15Sekunden
int PumpenStatus = LOW;                             // Pumpe is normally on
int Pumpe= 9;

void setup() {
  // put your setup code here, to run once:
  pinMode(Pumpe,OUTPUT);
  digitalWrite(Pumpe, LOW);
}

void loop() {
  // put your main code here, to run repeatedly:

  if (PumpenStatus == LOW) {                         // wenn die Pumpe aus ist
    if (millis() - timestore > 3000) {               // auf die Uhr sehen, ob die 15 Minuten schon rum sind, wenn ja
      digitalWrite(Pumpe, LOW);                      // Pumpe einschalten
      PumpenStatus = HIGH;                           // notieren, dass die Pumpe angeschaltet ist
      timestore = millis();
    }
  } else {                                           // wenn die Pumpe an ist
    if (millis() - timestore > 6000) {               // auf die Uhr sehen ob die 15 Minuten und 15 Sekunden schon rum sind, wenn ja
      digitalWrite (Pumpe, HIGH);                    // Pumpe ausschalten
      PumpenStatus = LOW;                            // notieren, dass die Pumpe ausgeschaltet ist
      timestore = millis();
    }
  }
}

Ich will diese Intervallsteuerung nur laufen lassen wenn ein Taster LOW ist. Also dachte ich mir ich muss den void- loop- Teil der Intervallsteuerung einfach in eine zusätzliche if- Bedingung einbinden. Das war der Versuch:

// Versuch mit zusätzlicher if- Bedingung

unsigned long timestore;                            // Variabler Speicher für 15 Minuten und 15Sekunden
int PumpenStatus = LOW;                             // Pumpe is normally on
int Pumpe= 9;
int Niveauschalterminimum = 2;

void setup() {
  // put your setup code here, to run once:
  pinMode(Pumpe,OUTPUT);
  digitalWrite(Pumpe, LOW);
  pinMode(Niveauschalterminimum, INPUT_PULLUP);
}

void loop() {

  if (Niveauschalterminimum == LOW){                 // wenn der Niveauschalterminimum LOW ist...
    if (PumpenStatus == LOW) {                       // wenn die Pumpe aus ist
  }
    if (millis() - timestore > 3000) {               // auf die Uhr sehen, ob die 15 Minuten schon rum sind, wenn ja
      digitalWrite(Pumpe, LOW);                      // Pumpe einschalten
      PumpenStatus = HIGH;                           // notieren, dass die Pumpe angeschaltet ist
      timestore = millis();
    }
  else {                                             // wenn die Pumpe an ist
    if (millis() - timestore > 6000) {               // auf die Uhr sehen ob die 15 Minuten und 15 Sekunden schon rum sind, wenn ja
      digitalWrite (Pumpe, HIGH);                    // Pumpe ausschalten
      PumpenStatus = LOW;                            // notieren, dass die Pumpe ausgeschaltet ist
      timestore = millis();
    }
  }
  }
  }

Kann mir bitte jmd. verraten was ich falsch gemacht habe?

LG Leonardo

Das Problem bei meinem Versuch ist, dass die Intervallsteuerung nicht läuft wenn der Taster LOW ist und so auch garnicht unterbrochen werden kann von einer nichterfüllten if- Bedingung;)

statte deinen Sketch mit entsprechenden Debug-Ausgaben (Serial.print) aus, damit du siehst wo dein Programm in ein If hineinspringt. Dann siehst du auch, wo du NICHT hinkommst.

Das schaut auf alle Fälle eingenartig aus, das Pumpenstatus == LOW tut vermutlich nicht viel, da fehlt der Anweisungsblock:

  if (Niveauschalterminimum == LOW){                 // wenn der Niveauschalterminimum LOW ist...
    if (PumpenStatus == LOW) {                       // wenn die Pumpe aus ist
  }

auch könntest mal STRG-T in der IDE drücken. Das hilft, die ganzen Einrückungen sichtbar zu machen. Vieleicht siehst du es dann auch schon.

Wo liest Du den Taster ein?

Hallo,

wenn

int Niveauschalterminimum = 2
die Pinnummer vom Taster sein soll, dann fehlt dir digitalRead zum einleses des Signals. :wink:

mit
if (Niveauschalterminimum == LOW)
fragst du nur ab ob 2 == LOW ist, was ja nie der Fall sein kann.

Hallo
und nicht vergessen die Pumpe abzuschalten, wenn die Bedingung

if (digitalRead(Niveauschalterminimum) == LOW)

nicht erfüllt ist.
Dein Sketch birgt eine Menge von Optimierungpotential.

@noiasca:
Kannst Du mir erklären oder ein Beispiel geben wie ich meinen Sketch mit serial.print austatte um zu gucke wo mein Programm in ein if einsprint? Was muss ich dafür mit Serial.print auslesen?

Der Tipp mit STRG + T war gut, habe jetzt auch nochmal ein paar {} Klammern dazugetan, jetzt sehen die Verzeigungen zumindest sinnvoller aus:D.

@Doc_Arduino: Oh ja ich hatte ein digitalRead zum Einlesen des Signals vergessen, habe es hinzugefügt.

So sieht der Sketch jetzt aus:

// Versuch mit zusätzlicher if- Bedingung

unsigned long timestore;                            // Variabler Speicher für 15 Minuten und 15Sekunden
int PumpenStatus = LOW;                             // Pumpe is normally on
int Pumpe = 9;
int Niveauschalterminimum = 2;

void setup() {
  // put your setup code here, to run once:
  pinMode(Pumpe, OUTPUT);
  digitalWrite(Pumpe, LOW);
  pinMode(Niveauschalterminimum, INPUT_PULLUP);
}

void loop() {

  if (digitalRead(Niveauschalterminimum) == LOW) {                // wenn der Niveauschalterminimum LOW ist...
  { if (PumpenStatus == LOW) {                       // wenn die Pumpe aus ist
      }
      if (millis() - timestore > 3000) {               // auf die Uhr sehen, ob die 15 Minuten schon rum sind, wenn ja
        digitalWrite(Pumpe, LOW);                      // Pumpe einschalten
        PumpenStatus = HIGH;                           // notieren, dass die Pumpe angeschaltet ist
        timestore = millis();
      }
      else                                            // wenn die Pumpe an ist
        if (millis() - timestore > 6000) {               // auf die Uhr sehen ob die 15 Minuten und 15 Sekunden schon rum sind, wenn ja
          digitalWrite (Pumpe, HIGH);                    // Pumpe ausschalten
          PumpenStatus = LOW;                            // notieren, dass die Pumpe ausgeschaltet ist
          timestore = millis();
        }

    }
  }
}

Es funktioniert leider noch nicht, bitte noch mehr Tipps:)

Hallo,

if (PumpenStatus == LOW) {                       // wenn die Pumpe aus ist
      } // diese Klammer muss woanders hin

in dem if Block steht ja nichts drin, eigendlich willst Du doch den gesamten Block zum einschalten da drin haben.

if (digitalRead(Niveauschalterminimum) == LOW){        // wenn der Niveauschalterminimum LOW ist...
  
 if (PumpenStatus == LOW) {                       // wenn die Pumpe aus ist
      
      if (millis() - timestore > 3000) {            // auf die Uhr sehen, ob die 15 Minuten schon rum sind, wenn ja
        digitalWrite(Pumpe, LOW);                      // Pumpe einschalten
        PumpenStatus = HIGH;                           // notieren, dass die Pumpe angeschaltet ist
        timestore = millis();
      }
   }
}

Heinz

Nachtrag. Allerdings klappt das Ausschalten mit dem Taster dann immer noch nicht.

Hallo,

die Klammersetzung ist komplett daneben. Schreibe für den Anfang erstmal die geschweiften Klammern ausführlich hin. Also keine öffnende Klammer am Ende der Zeile sondern auf nächste Zeile alleine. Dann nochmal Auto Formatierung. Dann sollte dir etwas auffallen.

Kannst Du mir erklären oder ein Beispiel geben wie ich meinen Sketch mit serial.print austatte um zu gucke wo mein Programm in ein if einsprint? Was muss ich dafür mit Serial.print auslesen?

hm, du sollst dir ja nur marker setzen damit du siehst was das Programm macht. So in etwa:

// Debugausgaben für Serial ergänzt
// STRG-T gedrückt
unsigned long timestore;                            // Variabler Speicher für 15 Minuten und 15Sekunden
int PumpenStatus = LOW;                             // Pumpe is normally on
int Pumpe = 9;
int Niveauschalterminimum = 2;

void setup() {
  Serial.begin(115200);  // Serial Ausgabe beginnen
  // put your setup code here, to run once:
  pinMode(Pumpe, OUTPUT);
  digitalWrite(Pumpe, LOW);
  pinMode(Niveauschalterminimum, INPUT_PULLUP);
  Serial.println(F("D14 Ende Setup"));
}

void loop() {

  if (Niveauschalterminimum == LOW) {                // wenn der Niveauschalterminimum LOW ist...
    Serial.println(F("D20 Niveauschalterminimum LOW"));
    if (PumpenStatus == LOW) {                       // wenn die Pumpe aus ist
    }
    if (millis() - timestore > 3000) {               // auf die Uhr sehen, ob die 15 Minuten schon rum sind, wenn ja
      Serial.println(F("D24 Timestore > 3000"));
      digitalWrite(Pumpe, LOW);                      // Pumpe einschalten
      PumpenStatus = HIGH;                           // notieren, dass die Pumpe angeschaltet ist
      timestore = millis();
    }
    else {                                             // wenn die Pumpe an ist
      if (millis() - timestore > 6000) {               // auf die Uhr sehen ob die 15 Minuten und 15 Sekunden schon rum sind, wenn ja
        Serial.println(F("D31 Timestore > 6000"));
        digitalWrite (Pumpe, HIGH);                    // Pumpe ausschalten
        PumpenStatus = LOW;                            // notieren, dass die Pumpe ausgeschaltet ist
        timestore = millis();
      }
    }
  }
}

Die Zeilennummer ist nicht so genau, es geht nur darum, dass du dann auf Grund der Ausgabe im Serial-Monitor weist, woher die Meldung gekommen ist.
Das Program ist natürlich gleich "falsch" wie vorher - analysieren musst du selber.

Hallo,

nach Formatierung sieht man, dass die erste millis Abfrage > 3000 immer gewinnt. Die Zweite kommt nie zum Zug.
Und wenn der Niveauschalter High liest, wird die Pumpe nie ausgeschalten, weil ja dann nichts mehr ausgeführt wird. Das heißt komplette Logik für den Ablauf überdenken. Male es vorher am besten auf.

unsigned long timestore;                            // Variabler Speicher für 15 Minuten und 15Sekunden
bool PumpenStatus = LOW;                             // Pumpe is normally on
const byte Pumpe = 9;
const byte Niveauschalterminimum = 2;

void setup()
{
  pinMode(Pumpe, OUTPUT);
  digitalWrite(Pumpe, LOW);
  pinMode(Niveauschalterminimum, INPUT_PULLUP);
}

void loop()
{
  if (digitalRead(Niveauschalterminimum) == LOW)      // wenn der Niveauschalterminimum LOW ist...
  {
    if (PumpenStatus == LOW)                          // wenn die Pumpe aus ist
    {
      if (millis() - timestore > 3000)                // auf die Uhr sehen, ob die 15 Minuten schon rum sind, wenn ja
      {
        digitalWrite(Pumpe, LOW);                      // Pumpe einschalten
        PumpenStatus = HIGH;                           // notieren, dass die Pumpe angeschaltet ist
        timestore = millis();
      }
      else                                                // wenn die Pumpe an ist
      {
        if (millis() - timestore > 6000)                 // auf die Uhr sehen ob die 15 Minuten und 15 Sekunden schon rum sind, wenn ja
        {
          digitalWrite (Pumpe, HIGH);                    // Pumpe ausschalten
          PumpenStatus = LOW;                            // notieren, dass die Pumpe ausgeschaltet ist
          timestore = millis();
        }
      }
    }
  }
}

Hi Doc,

Doc_Arduino:
Male es vorher am besten auf.

Sowas hat er ja in der Vergangenheit probiert.
Und darauf keine Antwort bekommen.

Gut, ich gebe zu da auch irgendwie etwas übersehen zu haben.

Hallo,

das sind doch noch mehr Zustände - ich kriege gleich Zustände ... :slight_smile: :slight_smile: :slight_smile:

Schreit nach einem Zustandsautomat - switch case und enums sind dein Freund.
Ich habe das mal versucht umzusetzen.

Wenn die Einstiegsbedingungen einmal erfüllt sind, werden die cases konsequent abgearbeitet, bis die Pumpe wieder aus ist. Vorteil, keine if else Verschachtelungen wo man nicht mehr raus kommt bzw. durchblickt.
Die Signallogik kann ich nicht prüfen.

struct Pumpe
{
  unsigned long lastMillis;            // Variabler Speicher für 15 Minuten und 15Sekunden
  bool status = LOW;                   // Pumpe is normally on
  const byte pin = 9;
  const byte pinNiveau = 2;
};

Pumpe pump;

enum class state : byte {IDLE, WAITON, WAITOFF};
state mode = state::IDLE;

void setup()
{
  Serial.begin(9600);
  pinMode(pump.pin, OUTPUT);
  digitalWrite(pump.pin, LOW);
  pinMode(pump.pinNiveau, INPUT_PULLUP);
}

void loop()
{
  switch (mode)
  {
    case state::IDLE:
      if (!digitalRead(pump.pinNiveau) && (!pump.status) )    // wenn Niveauschalter LOW und Pumpe aus ist ...
      {
        pump.lastMillis = millis();                           // aktuelle Zeit merken für den Vergleich im Nächsten case
        mode = state::WAITON;
        Serial.println("WAIT ON");
      }
      break;

    case state::WAITON:
      if (millis() - pump.lastMillis > 3000)              // auf die Uhr sehen, ob die 15 Minuten schon rum sind, wenn ja
      {
        digitalWrite(pump.pin, LOW);                      // Pumpe einschalten
        pump.status = HIGH;                               // notieren, dass die Pumpe angeschaltet ist
        pump.lastMillis = millis();                       // aktuelle Zeit merken für den Vergleich im Nächsten case
        mode = state::WAITOFF;
        Serial.println("WAIT OFF");
      }
      break;

    case state::WAITOFF: 
        if (millis() - pump.lastMillis > 6000)              // auf die Uhr sehen ob die 15 Minuten und 15 Sekunden schon rum sind, wenn ja
        {
          digitalWrite (pump.pin, HIGH);                    // Pumpe ausschalten
          pump.status = LOW;                                // notieren, dass die Pumpe ausgeschaltet ist
          mode = state::IDLE;
          Serial.println("IDLE");
        }
        break;
  }

}

LeonardoFiando:
Ich habe ein Problem mit einer if- Bedingung, das ich einfach nicht verstehe, es wäre so schön wenn mich jmd. erlösen könnte!

Ich würde mich freuen, wenn Du in Deinem Ursprungsthread bleiben würdest.
Dann wäre es nicht so schwer sich damit auseinandersetzen zu müssen. Nicht alle wissen, wo die Reise hingeht.

Es handelt sich um diese Intervallsteuerung:
Kann mir bitte jmd. verraten was ich falsch gemacht habe?

Also ich fange noch einmal an und biete Dir folgende Zeilen, die ich aus Deinem ersten Code rausgekürzt habe.
Bitte überlege, was Du für Kommentare reingeschrieben hast.

// Forumsketch - kompiliert / ungetestet
unsigned long timestore;  // Variabler Speicher für 15 Minuten und 15Sekunden
int Pumpe = 9;

void setup() {
  pinMode(Pumpe, OUTPUT);
  digitalWrite(Pumpe, LOW);
}

void loop() {
  if (digitalRead(Pumpe) && (millis() - timestore > 3000)) // - Neu: Wenn PumpenPin gesetzt UND Zeit abgelaufen
  {
    digitalWrite(Pumpe, LOW);
    timestore = millis();
  }

  if (!digitalRead(Pumpe) && (millis() - timestore > 6000)) // Wenn PumpenPin gesetzt UND Zeit abgelaufen
  {
    digitalWrite (Pumpe, HIGH);
    timestore = millis();
  }
}

Du brauchst keine zusäzliche Variable für den Status.

Das soll das Intervall machen.
Wenn Du vermeiden willst, das das Intervall läuft, wenn Du einen Schalter umlegst, das musst Du dann drum(!) mit einer Abfrage des Schalters legen!

// PSEUDOCODE / kompiliert
// die boolche Variable ist zu ersetzen durch den Schalterzustand
unsigned long timestore;  // Variabler Speicher für 15 Minuten und 15Sekunden
int Pumpe = 9;
bool Schalter_umgelegt=false;

void setup() {
  pinMode(Pumpe, OUTPUT);
  digitalWrite(Pumpe, LOW);
}
void loop() {
  if (Schalter_umgelegt )
  {
    if (digitalRead(Pumpe) && (millis() - timestore > 3000)) // - Neu: Wenn PumpenPin gesetzt UND Zeit abgelaufen
    {
      digitalWrite(Pumpe, LOW);
      timestore = millis();
    }
    if (!digitalRead(Pumpe) && (millis() - timestore > 6000)) // Wenn PumpenPin gesetzt UND Zeit abgelaufen
    {
      digitalWrite (Pumpe, HIGH);
      timestore = millis();
    }
  }
}

Mach was draus und bring das in Dein Ursprungsprojekt ein.

Doc_Arduino:
das sind doch noch mehr Zustände - ich kriege gleich Zustände ... :slight_smile: :slight_smile: :slight_smile:

Die Signallogik kann ich nicht prüfen.

Ja na geil... :slight_smile: :slight_smile:

Den Ansatz mit toggeln gab es auch schon mal....
Ok, ich freu mich, wenn es nicht nur mir so geht, das ganz langsam aufzubauen....

BG

Hallo
und das Interval als ARRAY :slight_smile:

Ich hätte nochmal eine Verständnisfrage zu diesem Sketch:

unsigned long timestore;                            // Variabler Speicher für 15 Minuten und 15Sekunden
int PumpenStatus = LOW;                             // Pumpe is normally on
int Pumpe = 9;
int Niveauschalterminimum = 2;

void setup() {
  // put your setup code here, to run once:
  pinMode(Pumpe, OUTPUT);
  digitalWrite(Pumpe, LOW);
  pinMode(Niveauschalterminimum, INPUT_PULLUP);
}

void loop()
{
  if (digitalRead(Niveauschalterminimum == LOW)) {     // wenn der Niveauschaltermimum geschlossen ist
    if (PumpenStatus == LOW) {                         // wenn der Pumpenstatus aus ist                                       // Doc_Arduino: Die erste millis Abfrage gewinnt immer!!! aber warum läuft das Programm weiter wenn die Bedingung garnicht erfüllt ist?
      if (millis() - timestore > 3000) {               // auf die Uhr sehen, ob die 15 Minuten schon rum sind, wenn ja
        digitalWrite(Pumpe, LOW);                      // Pumpe einschalten
        PumpenStatus = HIGH;                           // notieren, dass die Pumpe angeschaltet ist
        timestore = millis();
      }
    } else {                                           // wenn die Pumpe an ist
      if (millis() - timestore > 6000) {               // auf die Uhr sehen ob die 15 Minuten und 15 Sekunden schon rum sind, wenn ja
        digitalWrite (Pumpe, HIGH);                    // Pumpe ausschalten
        PumpenStatus = LOW;                            // notieren, der Pumpenstatus an ist
        timestore = millis();
      }
    }
  } else digitalWrite(Pumpe, HIGH);                   //Pumpe ausschalten
}

Ich verstehe einfach nicht warum die Intervallsteuerung weiterläuft wenn die Bedingung if (digitalRead(Niveauschalterminimum == LOW)) nicht erfüllt ist, dann müsste die Pumpe doch einfach ausgeschaltet sein/ werden?

} else digitalWrite(Pumpe, HIGH);                   //Pumpe ausschalten
?

LeonardoFiando:
Ich verstehe einfach nicht warum die Intervallsteuerung weiterläuft wenn die Bedingung if (digitalRead(Niveauschalterminimum == LOW)) nicht erfüllt ist, dann müsste die Pumpe doch einfach ausgeschaltet sein/ werden?

Weil es if (digitalRead(Niveauschalterminimum) == LOW) heissen muss.
Den Rest habe ich mir nicht angeschaut, genau wie Du die Beispiele in der IDE :frowning:

LeonardoFiando:
Ich verstehe einfach nicht warum die Intervallsteuerung weiterläuft wenn die Bedingung if (digitalRead(Niveauschalterminimum == LOW)) nicht erfüllt ist, dann müsste die Pumpe doch einfach ausgeschaltet sein/ werden?

Die Bedingung ist erfüllt.
Du verstehst nicht die Klammersetzung!
Kurzform:
if (!digitalRead(Niveauschalterminimum)) { // Wenn LowPegel auf PIN machwas
}
Langform:
if (digitalRead(Niveauschalterminimum)==LOW) { // Wenn LowPegel auf PIN machwas
}

Hinweis:
Ich hatte Dir das schon einmal gezeigt: