Pflanzenwächter (mit Pumpenanschluss)

Hallo und noch einen guten Rutsch miteinander…

ich bin so ziemlich blutiger Anfänger was das Programmieren von und mit allem was Arduino betrifft.
Begeistert bin ich aber dennoch und versuche bestehende Programme zu verstehen und eventuell so ab zu ändern dass diese hoffentlich auch richtig funktionieren.
Nun habe ich mir den Sketch von dieser az-delivery Seite mit dem Pflanzenwächter geschnappt und soweit abgeändert, dass im Endeffekt eigentlich eine angeschlossene Pumpe die Pflanzen gießen soll wenn ein gewisser Wert unterschritten ist.
Ich bin mir aber meiner Sache nicht so sicher ob ich alles auch richtig gemacht habe und frage nur mal ob sich jemand den abgeänderten Sketch mal ansieht und mir eventuell Fehler aufzeigt und mir hilft diese zu beheben…

Grüße

Jörg

Pflanzenwaechter_Teil5.ino (42.8 KB)

Hi

Nicht, daß ich mich nicht gerne auf 42k unbekannten Code stürze ...
Aber: WAS hast Du angepasst?
Wir dürfen ja wohl hoffentlich davon ausgehen, daß der zu Grunde liegende Sketch 'halbwegs sauber läuft'.
Deshalb wäre Es, meiner Meinung, nur nötig, die Anpassungen anzuschauen.
... auch, weil mir echt die Lust fehlt, das Tutorial dort drüben nachzuvollziehen - die fehlende Hardware noch außer Acht gelassen.

MfG

Tut mir leid dass ich das Thema so ungünstig begonnen habe.
Ich habe mehr oder weniger nach

// Main Loop
void loop()

Folgende Zeilen noch eingefügt:

//
//   Pumpenanschluss 1:
//
  {                                                               // Sensorausgang 0 für den Pumpenanschluss einrichten......
    if ((MMeasure.DataValid[0]))
    {                                                             // Bemerkung zu den Sensorwerte im seriellen Monitor:
      if ( MMeasure.Percent[0] <= 30)                             // Wenn der Wert unter 30% liegt.....
      {
        digitalWrite(Pumpe_1, LOW);                               // Setze den Anschluss auf LOW (eingeschaltet)
        if (Pumpe_1 = LOW)                                        // Wenn der Anschluss auf LOW liegt
          delay(50);                                              // warte erst einmal 50 Millisekunden
        Serial.println("Pflanze wird gegossen");                  // und schreibe im seriellen Monitor: Pumpe 1 an
      }
      else                                                        // Ansonsten.....
      {
        digitalWrite(Pumpe_1, HIGH);                               // Den Anschluss auf "LOW" setzen (anschalten)
        Serial.println("Pflanze wird nicht gegossen");                  // schreibe im seriellen Monitor: Pflanze wird gegossen
        delay(2000);                                              // 2 Sekunden lang an lassen.
        digitalWrite(Pumpe_1, HIGH);                              // danach wieder auf "HIGH" setzen (ausschalten)
        delay(2000);                                              // und wieder 2 Sekunden warten
      }
      delay(5000);                                                // Den Anschluss alle 5 Sekunden überprüfen
    }
  }

Der Code ist beim Kompilieren auch Fehlerfrei durchgelaufen. Aber wie schon geschrieben…
Ich bin mir nicht sicher ob das so richtig ist.
Vom Prinzip her sollte es so sein, dass die Sensoren die Werte auslesen, wenn ein gewisser Wert unterschritten ist,
die Pumpe anschalten, dann etwas warten um zu “sehen” wie die Erde sich anfühlt und dann einfach seine Arbeit erledigen…

Aber bitte nicht darauf hinweisen, dass ich die Pumpen nicht direkt anschließen darf, ich hab zwar ein Problem beim Programmieren, aber wie man einen Verbraucher mit einem Transistor ansteuert, das weiß ich doch :wink:

Hi

Ok - so hat die Abfrage wenig Sinn :wink:

Du fragst ab, ob die Feuchte <30° ist.
Wenn JA,

  • knipst Du die Pumpe an (auf LOW setzen)

  • fragst direkt ab, ob die Pumpe LOW ist … was erwartest Du hier?

  • bei erfolgreicher Abfrage, kommt ein delay(50) hinterher

  • und der Text ‘wird gegossen’ wird ausgegeben.

  • außerhalb der IF ist ein weiteres delay - dieses Mal 5 Sekunden.
    Das wiederholt sich so oft, wie loop() hier vorbei kommt und die Feuchte noch unter 30% ist.

Nun aber der Fall, daß die Feuchte NICHT <30 ist - dann schaltest Du die Pumpe DIREKT wieder aus - die Pumpe wird bis jetzt 2,3 Tropfen Wasser gefördert haben - je weiter der Sensor vom Schlauchende weg ist, desto mehr.

  • Du schaltest also die Pumpe AUS
  • Schreibst ‘Ne, nix mit gießen’
  • wartest 2 Sekunden
  • schaltest die Pumpe aus
  • wartest 2 Sekunden

Wenn der ganze Kram durchlaufen ist, wartest Du erneut - dieses Mal 5 Sekunden (die Gleichen wie oben erwähnt).

Dann beginnt Alles von Vorne.

Blöd außerdem, daß ALLES, was sonst so in loop() steht (von wegen Webserber und App-Spielereien - habe die Seite nur grob überflogen) während der ganzen Warterei — nicht funktionieren.
Und viel mehr, als Warten, macht Das nicht.

Du willst:
Prüfen, ob Feuchte < 30 → MERKEN, daß die Pumpe AN sein soll
Prüfen, ob Feuchte > 60 → MERKEN, daß die Pumpe AUS sein soll
Ggf. merkst Du Dir auch die Startzeit (millis() ), wann die Pumpe angeworfen wurde, um Diese ‘nach 35 Sekunden automatisch wieder abschalten zu können’.
Diese Wartezeit wird aus der aktuellen Zeit (millis() ) und der gemerkten Zeit (ebenfalls millis() - aber zum Zeitpunkt des Starten der Pumpe) berechnet - wenn die Differenz größer oder gleich der Maximal-laufzeit ist, wird sich ebenfalls Pumpe AUS gemerkt.
In loop() prüfst Du, ob sich der gemerkte Zustand verändert hat - wenn nicht, läuft Alles, wie Es soll.
Wenn doch, guckst Du, in welche Richtung und schaltest die Pumpe entsprechend, weiter merkst Du Dir die aktuelle Zeit (brauchen wir zwar nur für das Auto-Abschalten, aber vll. will man auch automatisch mindestens 1x alle 37 Stunden das Gießen auch starten - wäre zumindest möglich).

Du suchst die Nachtwächter-Erklärung bzw. möchtest verinnerlichen, wie ‘Blink without delay’ funktioniert.
Alles übersichtlich verlinkt hier, von combie zusammen getragen.

MfG

Pflanzen wachsen bei 60%luftfeuchte am besten
die Bodenfeuchte sollte je nach flanzetyp und wachstumsstadium um die 50% liegen
ein i2c bnp280 tut da sehr gute Dienste

Ich verstehe jetzt nicht ob bereits im Orginalsketch fleißig mit delay() gearbeitet wird oder nur Du die delay()s eingefügt hast.

Würde Dir raten delay() möglichst wenig zu benutzen. 0,1mS delay() kann vertretbar sein, 2-5 Sekunden nicht mehr.
Grüße Uwe

Ich glaube daß die Gißtaktik nicht sehr schlau ist.

Das Wasser muß vom Schlauchausgang am Blumentopf die Erde befeuchten ( kapillar verteilen ) um dann beim Feuchtigkeitssensor als höherer Feuchtigkeitswert ankommen. Das passiert nicht im Sekundenbereich.
Du ergründest wieviel Wasser es braucht um die Feuchtigkeit zu erhöhen. zB Blumentopf 1 brauch 50ml um von 30 bis 55% zu kommen. Dann weiß Du daß bei einem zu niederen Feuchtigkeitswert x Sekunden die Pumpe anschalten mußt. Dann weißt Du daß es y Minuten braucht damit das Wasser beim Sensor als höherer Wert ankommt und daß dann für z Stunden kein neues Wasser brauchst.
In dieser Weise kann Dir keine Überschwämmung passieren und auch ein Fehler in der Pumpensteuerung bzw ein Leerer Wassertak erkannt wird.

Grüße Uwe

Eine sehr einfache art die zu umgehen ist eine Tropfbewässerung aus einem sekundär gefäß

soll Heisen die Tropfbewässerung geht immer wenn das gefäss leer wird wird mittels Pumpe dies wieder befüllt.
eine einfache ohne uC Schaltung mit Schwimmer unten ein oben aus

Genau aus diesem Grund, weil ich ja nicht genau weiß wie ich es RICHTIG bewerkstelligen soll, hab ich den Code
hier reingestellt.

Du willst:
Prüfen, ob Feuchte < 30 → MERKEN, daß die Pumpe AN sein soll
Prüfen, ob Feuchte > 60 → MERKEN, daß die Pumpe AUS sein soll
Ggf. merkst Du Dir auch die Startzeit (millis() ), wann die Pumpe angeworfen wurde, um Diese ‘nach 35 Sekunden automatisch wieder abschalten zu können’.
Diese Wartezeit wird aus der aktuellen Zeit (millis() ) und der gemerkten Zeit (ebenfalls millis() - aber zum Zeitpunkt des Starten der Pumpe) berechnet - wenn die Differenz größer oder gleich der Maximal-laufzeit ist, wird sich ebenfalls Pumpe AUS gemerkt.
In loop() prüfst Du, ob sich der gemerkte Zustand verändert hat - wenn nicht, läuft Alles, wie Es soll.
Wenn doch, guckst Du, in welche Richtung und schaltest die Pumpe entsprechend, weiter merkst Du Dir die aktuelle Zeit (brauchen wir zwar nur für das Auto-Abschalten, aber vll. will man auch automatisch mindestens 1x alle 37 Stunden das Gießen auch starten - wäre zumindest möglich).

Du suchst die Nachtwächter-Erklärung bzw. möchtest verinnerlichen, wie ‘Blink without delay’ funktioniert.
Alles übersichtlich verlinkt hier, von combie zusammen getragen.

Das mit dem Nachtwächter habe ich mir vor kurzem auch mal angeschaut, eben auch wegen dem “delay” und der Programmabfolge.
Ich werde mir den “Nachtwächter” dann eben so oder so ähnlich eintragen:

Schaue mal was der Sensor für nen Wert hat…
Ist der Wert unter 30%, dann schalte die Pumpe (meinetwegen) mal für 5 Sekunden an und dann
wieder aus…

Drehe mal deine Runde und schaue nach 30 Minuten wieder nach, ob der Wert in der Zwischenzeit passt…
Falls nach 30 Minuten der Wert immer noch unter 30% liegen sollte,
schalte die Pumpe wieder für 5 Sekunden an.
Ist der Wert aber in der Zwischenzeit in Ordnung, lasse die Pumpe aus und schaue
einfach in 30 Minuten wieder vorbei.

uwefed:
Ich verstehe jetzt nicht ob bereits im Orginalsketch fleißig mit delay() gearbeitet wird oder nur Du die delay()s eingefügt hast.

Würde Dir raten delay() möglichst wenig zu benutzen. 0,1mS delay() kann vertretbar sein, 2-5 Sekunden nicht mehr.
Grüße Uwe

Ja Uwe, im Originalcode wurden bereits viele delay`s verwendet… Aber das “Warum” geht mir nicht ganz in den Kopf.
Ich dachte der “delay” Befehl ist eigentlich für solche Sachen gerade da…

Ich schreibe den Code nun mal um, versuche es zumindest und werde mein Ergebnis wieder rein stellen.
Und noch etwas:
das mit den kurzen Schaltzeiten darf jetzt nicht als gegeben verstanden werden! Das war nur ein Beispiel wie ich es
mir ganz grob überlegt habe.
Mir ist bewusst dass meine Pumpe in der kurzen Zeit eventuell zu wenig Wasser hoch fördert, das ist aber
dann nur über Testen und Probieren zu ermitteln… :slight_smile:

So, jetzt war ich ein paar Stunden da gesessen und mein Schädel hat gedampft…
Ich hoffe ich hab verstanden um was es ging…
Ich setzte jetzt nur mal einen Teil des Sketch rein, jenen den ich hoffentlich jetzt richtig
abgeändert habe.
Und nochmals: die Zeiten die ich hier rein setze, sind nur für Testzwecke gedacht und entsprechen nicht den Zeiten die später eingesetzt werden…

unsigned long Pumpe6_zeit;
int Pumpen6_Status = HIGH;
int Pumpe_6 = 12;

void setup() {
  Serial.begin(115200);
  pinMode(Pumpe_6, OUTPUT);  // teilt dem Arduino mit, dass das ein Ausgang ist.
}

void loop()
{

//
//   Pumpenanschluss 6:
//
  {                                                               // Sensorausgang 5 für den Pumpenanschluss einrichten......
                                                                  // Bemerkung zu den Sensorwerte im seriellen Monitor:
      if (( MMeasure.Percent[5]) <= 30)                           // Wenn der Wert unter 30% liegt.....
     {
        if (Pumpe_6 == LOW)                                       // Wenn der Anschluss auf LOW liegt
       {
          if (millis() - Pumpe6_zeit > 10000)                     // Pumpenstatus alle 10 Sekunden überprüfen                  
         {
              digitalWrite(Pumpe_6, LOW);                         // Den Pumpenanschluss einschalten (LOW)
              Pumpe6_zeit = millis();
              Pumpen6_Status = LOW;
              Serial.println("Pumpe ist angeschaltet");
         }
       }
     }
      else                                                        // Ansonsten.....
     {
        if (( MMeasure.Percent[5]) >= 40)                           // Wenn der Wert unter 30% liegt.....
       {
        if (Pumpe_6 == HIGH)                                       // Wenn der Anschluss auf LOW liegt
         {
           if (millis() - Pumpe6_zeit > 8000                         // nachdem die Pumpe 2 Sekunden gelaufen ist
           {
             digitalWrite(Pumpe_6, HIGH);                            // schalte den Abschluss wieder aus (HIGH)
             Pumpen6_Status = HIGH;
             Serial.println("Pumpe ist ausgeschaltet");
           }
         }
       }
     }
  }
}
}

Hi

Pumpen6_Status - da reicht ein boolean
Pumpe_6 wird der Pin sein - da reicht ein byte.
Da sich der Pin wohl nicht während der Laufzeit ändert, auch gerne ein const byte Pumpe_6=12;
Dann schreibt man Variablen im Allgemeinen klein, CamelCase ist möglich.
Konstanten gerne Groß, wobei ich hier auch oft von abweiche ...

Du kannst einen digitalen Pin auch abfragen - so kannst Du Dir ggf. den separaten Status sparen.

Die Kommentare sollten schon dem Sketch entsprechen - Prüfung auf 8000 und im Kommentar 2 Sekunden - irgend etwas passt hier nicht.
Ändere den Kommentar, daß die Zahl keine Rolle dort spielt es aber klar ist, was diese Zahl macht.

Beim Abschalten der Pumpe die Pumpe6_zeit ggf erneut auf millis() setzen, um die Wartezeit nach dem Pumpen zu starten?

Sonst sollte Das funktionieren, sofern ich Nichts gravierendes übersehen habe.

MfG

In Ordnung, das mit den Zahlenangaben kann irritieren und ist nicht immer sinnvoll…
Für mich momentan aber immer noch eine Hilfe auf die ich gerne zurück greife.
Den Pumpenanschluss hab ich jetzt auf const umgestellt, wusste auch nicht dass sich das im Speicher bemerkbar machen kann, aber um so größer der Sketch, um so sparsamer sollte man damit umgehen, verstanden…
Was du aber jetzt mit dem boolean meinst, da komme ich nicht dahinter. Denk bitte daran dass ich blutiger Anfänger bin und selbst mit so manchen Lesen nicht dahin komme, was gemeint ist.
Die Variablen hab ich auch mal geändert, wobei ich aber nicht einmal wusste dass man mehrere Begriffe mit unterschiedlicher Schreibweise als CamelCase bezeichnet (z.B. pumpen6_Status)
Die Konstante hab ich jetzt noch ganz bewusst klein geschrieben lassen. In meinem Fall ist das eh nur ein Wort mit Zahl und damit kann man, denk ich mal, auch als Geübter zurecht kommen.

Nun noch einmal ein abgeänderter Code, hier habe ich im else mal einen Maximalwert noch eingesetzt, dürfte doch auch noch stimmen wenn mich meine Logik nicht täuscht.

unsigned long pumpe6_Zeit;
int pumpen6_Status = HIGH;
const byte pumpe_6 = 12;

void setup() {
  Serial.begin(115200);
  pinMode(pumpe_6, OUTPUT);  // teilt dem Arduino mit, dass das ein Ausgang ist.
}

void loop()
{

//
//   Pumpenanschluss 6:
//
  {                                                               // Sensorausgang 5 für den Pumpenanschluss einrichten......
                                                                  // Bemerkung zu den Sensorwerte im seriellen Monitor:
    if (( MMeasure.Percent[5]) <= 30)                             // Wenn der Wert unter 30% liegt.....
      {
        if (pumpe_6 == LOW)                                       // Wenn der Anschluss auf LOW liegt
          {
            if (millis() - pumpe6_Zeit > 10000)                   // Pumpenstatus überprüfen                  
              {
                digitalWrite(pumpe_6, LOW);                       // Den Pumpenanschluss einschalten (LOW)
                pumpe6_Zeit = millis();
                pumpen6_Status = LOW;
                digitalRead(pumpe_6
                Serial.println("Pumpe ist angeschaltet");
              }
            }
          }
        else                                                        // Ansonsten.....
          {
            if (( MMeasure.Percent[5]) >= 40)                       // Wenn der Wert über 40% liegt.....
          {
            if (pumpe_6 == HIGH)                                    // Schaue ob der Anschluss auf HIGH liegt
          {
            if (millis() - pumpe6_Zeit > 8000                       // nachdem die Pumpe gelaufen ist
          {
              digitalWrite(pumpe_6, HIGH);                          // schalte den Abschluss wieder aus (HIGH)
              pumpen6_Status = HIGH;
              Serial.println("Pumpe ist ausgeschaltet");
          }
        }
      }
    }
  }
}

Hi

int pumpen6_Status = HIGH;
Damit braucht die Information, ob die Pumpe an oder aus ist, zwei Byte oder 16 Bit auf den AVR-Arduinos.
Auf einem ARM wohl 4 Byte = 64 Bit - aber Die haben ja auch wesentlich mehr Speicherplatz - gefällt mir trotzdem nicht :wink:
Ausreichend ist Es hier, wenn wir mit dem Minimum an Speicher auskommen - wäre ein Byte:
byte pumpen6_Status=HIGH;
Wenn wir noch verhindern wollen, daß der Status unsinnige Werte annehmen kann - viel mehr als AN und AUS wird’s wohl nicht geben, nehmen wir boolean.
boolean pumpen6_Status=HIGH;
Das begrenzt den Wertebereich auf 0 und 1, HIGH und LOW, TRUE und FALSE.
Alles, was nicht Null ist, wird TRUE/HIGH/1

In Zeile 23 if (pumpe6 == LOW) - was denkst Du, machst Du Da?
pumpe6 ist ‘12’ - die Pinnummer - Du willst eher
if (digitalRead(pumpe6)==LOW)
Das hattest Du in #9 auch schon flasch - ist mir aber nicht aufgefallen.

Drücke in der IDE Mal STRG+T - Das rückt den Code auf Klammer-Ebene ein.
Auch denke ich, hast Du in den Abfragen einen Fehler - Du fragst auf LOW ab, um in der IF auf LOW zu setzen.
Gleiches bei HIGH - denke, hier muß ‘gewechselt’ werden, oder?
Schau Mal, ob Du Damit was anfangen kannst:

const boolean AN = HIGH;    //Hier eintragen, bei welchem Pegel am Pin die Pumpe AN ist
const boolean AUS = !AN;

const byte pumpenanzahl = 6;    //Anzahl der Pumpen

unsigned long last_pumpe[pumpenanzahl];
boolean statuspumpe[pumpenanzahl]  {AN, AN, AN, AN, AN, AN};
const byte PinPumpe[pumpenanzahl]  {12, 13, 14, 15, 16, 17};

void setup() {
  Serial.begin(115200);
  for (byte b = 0; b < pumpenanzahl; b++) {  //Hier stand Mal ein falsches >
    pinMode(PinPumpe[b], OUTPUT);  // teilt dem Arduino mit, dass das ein Ausgang ist.
  }
}

void loop() {

  static byte aktpumpe = pumpenanzahl;
  aktpumpe++;   //Zählt die Pumpen der Reihe nach durch
  aktpumpe%=pumpenanzahl;

  if ( MMeasure.Percent[aktpumpe - 1] <= 30) {                          // Wenn der Wert unter 30% liegt.....
    if (digitalRead(PinPumpe[aktpumpe]) == AUS) {                                      // Wenn der Anschluss auf LOW liegt
      if (millis() - last_pumpe[aktpumpe] > 10000) {                  // Pumpenstatus überprüfen
        digitalWrite(PinPumpe[aktpumpe], AN);                       // Den Pumpenanschluss einschalten (LOW)
        last_pumpe[aktpumpe] = millis();
        statuspumpe[aktpumpe] = AN;
        Serial.print("Pumpe ");
        Serial.print(aktpumpe);
        Serial.println(" ist angeschaltet");
      }
    }
  } else if ( MMeasure.Percent[aktpumpe - 1] >= 40) {                    // Wenn der Wert über 40% liegt.....
    if (digitalRead(PinPumpe[aktpumpe]) == AN) {                                   // Schaue ob der Anschluss auf HIGH liegt
      if (millis() - last_pumpe[aktpumpe] > 8000) {                      // nachdem die Pumpe gelaufen ist
        digitalWrite(PinPumpe[aktpumpe], AUS);                          // schalte den Abschluss wieder aus (HIGH)
        statuspumpe[aktpumpe] = AUS;
        Serial.println("Pumpe ");
        Serial.print(aktpumpe);
        Serial.println("ist ausgeschaltet");
      }
    }
  }
}

Ich setze die einleitende Klammer in die Zeile der IF/FOR/whatever, macht den Code kompakter.

MfG

Edit
Das >, auf Das die gefühlten nächsten 10 Posts sich bezieht, wurde mittlerweile in ein korrektes < getauscht.
Sorry für die Verwirrung

Uuuupppsss,
jetzt bin ich erst einmal platt....
Danke für den Code, ich werde jetzt erst einmal lesen um zu verstehen was du da alles rein gesetzt hast.

In Zeile 23 if (pumpe6 == LOW) - was denkst Du, machst Du Da?

Ehrlich gesagt wollte ich dem Programm nur sagen, dass es den Anschluss nachschauen soll und sagen was es machen soll wenn der Anschluss angeschaltet ist (LOW)

Ich weiß schon, man kann diverse Befehle zusammen in einer Klammer setzen.
Das wäre einer meiner nächsten Fragen gewesen, ich hab das noch nicht so richtig am Schirm.
Und genau so hast du mir auch meiner nächsten Frage vorraus gegriffen, anscheinend ist dir klar was ich vor habe.....
Wie schreibe ich in einer Befehlszeile rein, dass hier mehrere Anschlüsse sind und wie sage ich dem Programm wie es dann diese Anschlüsse ansteuern, besser gesagt, schalten und überwachen soll.

Auch denke ich, hast Du in den Abfragen einen Fehler - Du fragst auf LOW ab, um in der IF auf LOW zu setzen.
Gleiches bei HIGH - denke, hier muß 'gewechselt' werden, oder?

Gebe ich dir vollkommen recht, Schreibfehler

Ich drucke mir den Code mal aus und schaue wie weit ich mit meiner Logik hier komme.

Vorerst einmal vielen Dank für deine Bemühungen, aber so komme ich doch ein Stückchen weiter.....

Ich versuche mal so nach und nach zu erklären wie ich deinen Code verstehe

const boolean AN = HIGH; //Hier eintragen, bei welchem Pegel am Pin die Pumpe AN ist

Mit der ersten Zeile wird der Status "HIGH" als "AN" bezeichnet und da es ja mehrere Anschlüsse sind,
ist das dann eine Konstante (const) mit der Mehrfachbezeichnung AN = HIGH und "boolean" verhindert
dass das Programm Fehler mitbringt und begrenzt hier das Wort "AN" auf den Befehl "HIGH"

Nur sollte die zweite Zeile dann nicht den Pegel "LOW" deklarieren?

const boolean AUS = !AN;

Nur so wäre jetzt min Gedankengang:
const boolean AUS = LOW

Oder bewirkt die Bezeichnung "!AN" eben diesen entgegengesetzen Befehl?

Zeile 3 gibt die Anzahl der Pumpen und durch den Befehl "const byte" sparen wir wieder ein paar Byte ein

const byte pumpenanzahl = 6;

Zeile 4 gibt mir momentan noch etwas Rätsel auf...... Das versuche ich erst einmal raus zu finden....

unsigned long last_pumpe[pumpenanzahl];

Zeile 5 ist wieder diese Mehrfachbezeichnung und Mehrfachbefehle im Code (boolean statuspumpe)
In der eckigen Klammer wird nur wieder nachgesehen wieviel Pumpen abgefragt werden [pumpenanzahl]

boolean statuspumpe[pumpenanzahl] {AN, AN, AN, AN, AN, AN};

Auch wieder die Eingrenzung durch "booelan" auf die Bezeichnung "AN"

Ich hoffe ich habe das bisher so richtig verstanden, den Rest versuche ich morgen zu verstehen,
mir glüht die Birne, dafür dass ich soviel in so kurzer Zeit und das auch noch zu solcher
Stunde rein gebrügelt bekomme :slight_smile:

Hi

Das !AN macht genau Das - negiert AN.
So reicht es, wenn Du AN auf LOW setzt um die Logik umzudrehen.
Habe selber Relais-Karten (SSR wie Normale, beide LOW-Aktiv) wie Einzel-SSR, Die ich aber derzeit HIGH-Aktiv verwende (könnte auch den Plus-Anschluss fest auf Vdd legen und den Minus schalten).
pumpenanzahl wird auf 6 gesetzt und dem Kompiler gesagt, daß diese Zuweisung konstant ist - so kann Er überall die 6 fest im Code einbauen und muß Diese nicht erst aus dem Speicher auslesen, was auch wieder einige Zeilen Code bedeutet.
last_pumpe ist die Zeit, wo die Pumpe zuletzt 'betrachtet' wurde - also die gemerkte Zeit.
Un Das in einer Schleife ducharbeiten zu können, sind die verschiedenen Zeiten in einem Array.
Gleiches mit dem statuspumpe.
Alles separate Variablen, aber einfach per durchzählen ansprechbar.

MfG

Super, wieder was gelernt

Das !AN macht genau Das - negiert AN.

Und in der Zeile:

( MMeasure.Percent[aktpumpe - 1] <= 30)

bezieht sich die Zahl 1 dann auch auf den Sensoranschluss der überprüft werden soll ?!?

Und in der Setupzeile steht ja:

for (byte b = 0; b > pumpenanzahl; b++)

Dieses “b” kann ich doch auch als a, z. y oder sonst wie bezeichnen, das bezieht sich ja nur
auf die Zählung der Anschlüsse. Das b++ soll ja immer nur zum ersten “b” eine 1 dazurechnen und sich
bis 6 hochzählen, denn mehr Anschlüsse wurde ja mit “pumpenanzahl” nicht deklariert.
Aber nur für meine Verständnis:
Wird hier in diesem Fall nicht mit der Zahl 0 begonnen?

Mfg

Jörg

for (byte b = 0; b > pumpenanzahl; b++)

Die Schleife wird nie ausgeführt.
Denn 0 ist kleiner pumpenanzahl.
for loop - cppreference.com sagt dazu:

condition - either
an expression which is contextually convertible to bool. This expression is evaluated before each iteration, and if it yields false, the loop is exited.

Tipp:
Mit einem "Range based for" geht man der Problematik aus dem Weg.

Die Schleife wird nie ausgeführt.
Denn 0 ist kleiner pumpenanzahl.

for (byte b = 0; b > pumpenanzahl; b++)

Ist es so dann richtig?:

for (byte b = 0; b> pumpenzahl; ++b)

for (byte b = 0; b> pumpenzahl; ++b)

Die Schleife wird nie ausgeführt.
Denn 0 ist kleiner pumpenanzahl.

Ich kann den Code nicht reparieren, denn er entspricht nicht meinem Stil.

Aber ich kann dir zeigen wie sowas bei mir aussehen könnte.

Ich muss allerdings zugeben, dass dieses Programm aus meiner Wühlkiste stammt, und vermutlich nicht exakt deinen Anforderungen entspricht.
Ziehe daraus, was dir schmeckt, den Rest verwerfe.
Es auch noch nie in der Praxis eingesetzt worden.
Also keine Garantie auf korrekte Funktion.

class Pumpe
{
  private:
    const byte pumpenPin; // der Pin, an dem die Pumpe hängt
    const byte sensorPin; // Bodenfeuchtesensor
    int schwellWert;      // unterhalb dieses Wertes wird Wasser benötigt  
    unsigned long pumpZeit;  // laufzeit der Pumpe
    unsigned long pauseZeit; // mindest Pause zwischen 2 Pumpvorgängen
    unsigned long zeitMerker; // interner Merker
    void *schritt;            // State des endlichen Automaten/ Schrittkette

  public:
  Pumpe(const byte pumpenPin, const byte sensorPin, const unsigned int schwellWert, const unsigned long pumpZeit, const unsigned long pauseZeit):
        pumpenPin(pumpenPin),sensorPin(sensorPin),schwellWert(schwellWert),pumpZeit(pumpZeit),pauseZeit(pauseZeit),zeitMerker(0),schritt(nullptr){}

  void begin()
  {
    digitalWrite(pumpenPin,HIGH); // Relais, low aktiv
    pinMode(pumpenPin,OUTPUT);        
  }

  void run()
  {
    if(!schritt) schritt = &&start;
    goto *schritt;
   
    start:
     if(analogRead(sensorPin) < schwellWert) 
     {
      schritt = &&pumpen;
      zeitMerker = millis();
      digitalWrite(pumpenPin,LOW); // Pumpe ein
     }
     goto ende;
     
     pumpen:
     if(millis() - zeitMerker >= pumpZeit)
     {
       schritt = &&pause;
       zeitMerker = millis();
       digitalWrite(pumpenPin,HIGH); // Pumpe aus
     }
     goto ende;
     
     pause:
     if(millis() - zeitMerker >= pauseZeit)
     {
       schritt = &&start; // und wieder von vorne
     }
     goto ende;
    
    ende:;
  }
};

Pumpe pumpen[] { // {pumpenPin, sensorPin, schwellWert, pumpZeit, pauseZeit}
                  {3,A0,300,10000,50000},
                  {4,A1,433,10000,50000},
                  {5,A2,255,10000,50000},
                  {6,A3,504,10000,50000},
                  {7,A4,166,10000,50000},
                  {8,A5,257,10000,50000},
                };


void setup() 
{
  for(Pumpe &p:pumpen) p.begin();
}

void loop() 
{
  for(Pumpe &p:pumpen) p.run();
}