Wieder bewässerung

oldmann:
... das war für mich eine Nummer zu groß. :blush:

Das glaube ich nicht, denn sonst hätte ich Dir diese Variante nicht angeboten. Richtig deutlich werden die Vorteile bei vielen Pumpen.

oldmann:
IDE findet keine Fehler. Ich auch ;D

"Ein Programm, das tut, was es soll, ist ein gutes Programm!" hat mir mal jemand geschrieben, noch besser, wenn Du es verstehst!

Sollen noch mehr Pumpen dazukommen?

Eigentlich ja.
Ich habe 2 genommen um die Übersicht nicht verlieren.
Ich denke, wann alles funktioniert, lässt sich der Sketch leicht erweitern.

Du kennst den Giesomat Sensor und das Shield dazu?
Gibt es schon einen Beispielscode dazu.

Hallo

agmue;

Ich gehe Deinem Tipp nach, brauche aber erst ein „delay“. Nein ich versuche mit millis. :wink:

In der letzten Woche habe ich versucht zu viel Stoff aufbearbeiten. Es ist ein totales Chaos entstanden. Muss ein System da.

FredRam;

Danke für deinen Tipp.

Ja der „Giesomat“ kenne ich. Eine interessante Lösung für einem Bewässerung.
Händler aus Fernen Osten bitten mittlerweile bezahlbaren Sensoren die arbeiten mit gleichen Prinzip, und geben am Ausgang eine Spannung 0-3V (Habe ein paar bestellt, leider der weg ist sehr lange) der Vorteil: ein analog Eingang genug, und so viele verwendbar, wie viele freie Eingänge stehen zu Verfügung.

Zu code für Arduino:

Der Michael Haugk schreib: (Zitat)
„Der Rest sollte für den geübten Arduino-Programmierer eine Kleinigkeit sein“
Ich brauche den Rest, und bin leider kein „geübte Arduino-Programmierer“. :cry:

agmue;

Bevor ich wieder Fehler beginne muss fragen. Aus Deinem Vorschlag:

const byte messPin, relaisPin;
  const int trockenWert; 
  const unsigned long messIntervall, giessIntervall, nachgiessenIntervall;
  unsigned int messwert;
  unsigned long vorhin, intervall;
  byte schritt;

Was nach Dir haben zu bedeuten „vorhin“ und „intervall“?
Und in diesem Abschnitt:

void loop()
{ jetzt = millis();
  for (Blumen &b : blumen) b.run();  // alle Feldelemente werden nacheinender mit der Methode run abgearbeitet
}

Was meinst Du mit „jetzt“ ?
Danke im Voraus.

oldmann:
Was nach Dir haben zu bedeuten „vorhin“ und „intervall“?
...
Was meinst Du mit „jetzt" ?

Das entstammt dem Beispiel der IDE BlinkWithoutDelay, nur anders benannt:

currentMillis = jetzt
previousMillis = vorhin
interval = intervall

Für mein Gehirn ist es einfacher, sich vorzustellen, millis() würde sich während loop() nicht ändern, was sich aber als fataler Fehler herausstellen könnte. Daher verwende ich jetzt, dann stimmt die Annahme.

Hi

millis() ist quasi die Stop-Uhr des Arduino - Sie zählt stur im 1ms-Takt vorwärts (ok, keine STOP-Uhr).
Das ist also die aktuelle Uhrzeit des Arduino - und die Methode .run benötigt die aktuelle Uhrzeit, um daraus abzuleiten, ob 'die Zeit um ist'.
jetzt ist eine globale Variable, wird in jedem loop()-Durchlauf gesetzt und dann in ALLEN 'Blumen' angewendet.

MfG

Danke

OK das mit die millis ist mir klar. Was mich aber momentan beschäftigt:

Im agmue’s Vorschlag gibt ein Intervall für Feuchtigkeit Messungen, finde ich auch richtig. Um das erreichen muss die zeit der letzten Messung festgehalten sein, ich sehe aber keinen geeigneten, außer „vorhin“, Merker. Ist das so, dass wenn ich in run Methode einen Merker „vorhin“ setze, wird die Messung Zeit für jede Blume gemerkt, auch bei gleicher Benennung? Muss ich nach anderer Lösung suchen? Oder habe ich das falsch interpretiert?

oldmann:
Ist das so, dass wenn ich in run Methode einen Merker „vorhin“ setze, wird die Messung Zeit für jede Blume gemerkt, auch bei gleicher Benennung?

Die Methode kann so geschrieben werden, als gäbe es nur eine Blume und eine Pumpe. Das Feld blumen[] hat aber zwei Elemente, weshalb es auch zweimal die Variable vorhin gibt: blumen[0].vorhin und blumen[1].vorhin. Die Initialisierung von vorhin erfolgt im Constructor, ist also im Feld blumen[] nicht direkt sichtbar. Wenn Du Dir vorstellst, jedes Element von blumen[] hat 10 Konstanten und Variablen1), dann gehört eine zu vorhin.


Anm:

  1. Wenn ich mich verzählt haben sollte, dann sind es so viele, wie Konstanten und Variablen im Constructor hinter dem Doppelpunkt stehen. Auch vorhin(0) ist dort zu finden.

oldmann:
Hallo

Ja der „Giesomat“ kenne ich. Eine interessante Lösung für einem Bewässerung.
Händler aus Fernen Osten bitten mittlerweile bezahlbaren Sensoren die arbeiten mit gleichen Prinzip, und geben am Ausgang eine Spannung 0-3V (Habe ein paar bestellt, leider der weg ist sehr lange) der Vorteil: ein analog Eingang genug, und so viele verwendbar, wie viele freie Eingänge stehen zu Verfügung.

Der riesige Vorteil des Giesomat ist das digitale Signal.
Achtung vor der Ware aus Fernost: Die sind nicht versiegelt.
Nach ein paar Wochen löst sich der Lötstopplack.

Guten Tag

Das alles ist mir klar. Nur weil die Sensoren günstig sind habe die bestellt.

In erste Linie will wissen ob funktionieren so wie deklariert. Wenn ja mache ich mir Gedanken über Versieglung.
In meinem Fall sind die Verbindungen kurz, also das analoge Signal wird nicht so stark gestört. Für langen Verbindungen wurde ich, klar der Giesomat bevorzugen.
Nach meinen Erkenntnissen, arbeitet in diesen Sensoren der NE555, ein Schaltkreis der sehr zuverlässig ist. Will keine Verübung machen, mall sehen. Im schlimmsten fall habe ich ein paar € falsch investiert (verloren).
Der große Vorteil dieser Variante:
alle Arduino Bords verwendbar, und keine zusätzlichen Schaltungen notwendig.
Es sei denn man seeeehr Großen Balkon hat :smiley:

MfG

Mal ein Vorschlag mit run():

#include <Streaming.h>
const unsigned long pausenIntervall = 1000;  // Pause während des Giessens
unsigned long jetzt;                         // Variable für den aktuellen Zeitpunkt

struct Blumen                            // Struktur mit Konstanten, Variablen und Methoden
{ Blumen(const byte messPin, const byte relaisPin, const unsigned int trockenWert, const unsigned long messIntervall, const unsigned long giessIntervall, const unsigned long nachgiessenIntervall):
    messPin(messPin), relaisPin(relaisPin), trockenWert(trockenWert), messIntervall(messIntervall), giessIntervall(giessIntervall), nachgiessenIntervall(nachgiessenIntervall), messwert(0), vorhin(0), intervall(0), zaehler(0), schritt(0) {}

  void init()
  { pinMode(relaisPin, INPUT_PULLUP);
    pinMode(relaisPin, OUTPUT);
  }

  void run()
  { if (jetzt - vorhin >= intervall)
    { vorhin = jetzt;
      switch (schritt)
      { case MESSEN:
          if (trockenWert > analogRead(messPin))
          { digitalWrite(relaisPin, LOW); // Pumpe einschalten
            zaehler = 0;
            intervall = giessIntervall;
            schritt = GIESSEN;
          } else {
            intervall = messIntervall;
          }
          break;
        case GIESSEN:
          digitalWrite(relaisPin, HIGH); // Pumpe ausschalten
          if (5 > ++zaehler)
          { intervall = pausenIntervall;
            schritt = PAUSE;
          } else {
            intervall = nachgiessenIntervall;
            schritt = MESSEN;
          }
          break;
        case PAUSE:
          digitalWrite(relaisPin, LOW);
          intervall = giessIntervall;
          schritt = GIESSEN;
          break;
      }
      if (messPin == 15) Serial << "messPin: " << messPin << "  \twert: " << analogRead(messPin) << "  \tintervall: " << intervall << "  \tschritt: " << schritt << "  \tzaehler: " << zaehler << endl;
    }
  }

  const byte messPin, relaisPin;
  const int trockenWert;
  const unsigned long messIntervall, giessIntervall, nachgiessenIntervall;
  unsigned int messwert;
  unsigned long vorhin, intervall;
  byte zaehler, schritt;
  enum {MESSEN, GIESSEN, PAUSE};
};

Blumen blumen[]  // Ein Feld der Struktur Blumen
{ // messPin, relaisPin, trockenWert, messIntervall, giessIntervall, nachgiessenIntervall
  {A1, 2, 200, 3000, 500, 5000},  // Werte für Blume und Pumpe 1
  {A2, 3, 250, 2500, 500, 5000}   // Werte für Blume und Pumpe 2
};

void setup()
{ Serial.begin(115200);
  Serial.println(F("Anfang"));
  for (Blumen &b : blumen) b.init();  // alle Feldelemente werden nacheinender mit der Methode init abgearbeitet
}

void loop()
{ jetzt = millis();
  for (Blumen &b : blumen) b.run();
}

EDIT: Kommenrar " // Pumpe einschalten" ergänzt.

Wow! :astonished:

Hier mein aktueller Stand:

unsigned long jetzt;                      // Variable für den aktuellen Zeitpunkt
byte zyklenzahl = 0;                      // Die Pumpe soll 4-mal kurz laufen dafuer Variable zyklenzahl

struct Blumen                             // Struktur mit Konstanten, Variablen und Methoden
{ Blumen(const byte messPin, const byte relaisPin, const unsigned int trockenWert, const unsigned long messIntervall, const unsigned long giessIntervall, const unsigned long nachgiessenIntervall):
    messPin(messPin), relaisPin(relaisPin), trockenWert(trockenWert), messIntervall(messIntervall), giessIntervall(giessIntervall), nachgiessenIntervall(nachgiessenIntervall), messwert(0), vorhin(0), intervall(0), schritt(0) {}

  void init()
  { pinMode(relaisPin, OUTPUT);
  }

  void run() {
    messwert = analogRead(messPin);       // Sensorwert auslesen
    if ((jetzt - vorhin >= messIntervall) && (messwert <= trockenWert)) {  // Wenn Messinterval abgelaufen und Blume troken
	vorhin = jetzt;                       // Aktuelle Messzeitwert legen
    intervall = millis();                 // Aktuelle Zeitwert fuer Pumpen legen
    }
        switch (schritt) {
      case 0:
        if ((millis() - intervall >= nachgiessenIntervall) && (zyklenzahl < 4)) {  // Wenn Pumpepause abgelaufen und wenige als 4 Zyklen
           intervall = millis();          // Aktuelle Zeitwert fuer Pumpen legen
           digitalWrite(relaisPin, HIGH); // Pumpe einschalten
           schritt = 1;                   // Weiter zu naechsten Schritt
        }
        break;
      case 1:
        if (millis() - intervall >= giessIntervall) {  // Pumpenzeit abgelaufen
           intervall = millis();          // Aktuelle Zeitwert fuer Pumpen legen 
           digitalWrite(relaisPin, LOW);  // Pumpe auschalten
           zyklenzahl++;                  // Zyklenzahl +1
           schritt = 0;                   // Wieder zu ersten Schritt
        }
        break;
    }
  }

  const byte messPin, relaisPin;
  const int trockenWert; 
  const unsigned long messIntervall, giessIntervall, nachgiessenIntervall;
  unsigned int messwert;
  unsigned long vorhin, intervall;
  byte schritt;
};

Blumen blumen[]  // Ein Feld der Struktur Blumen
{ // messPin, relaisPin, trockenWert, messIntervall, giessIntervall, nachgiessenIntervall
  {A0, 2, 200, 3000, 500, 5000},
  {A1, 3, 250, 2500, 500, 5000},
  {A2, 4, 250, 2000, 250, 3000}
};

void setup()
{ for (Blumen &b : blumen) b.init();  // alle Feldelemente werden nacheinender mit der Methode init abgearbeitet
}

void loop()
{ jetzt = millis();
  for (Blumen &b : blumen) b.run();  // alle Feldelemente werden nacheinender mit der Methode run abgearbeitet
}

Du hast mir den ganzen Spaß verdorben :wink:
ein Paar unterschiede kann man sehen 8)

Eine Frage:

 case GIESSEN:
          digitalWrite(relaisPin, HIGH);
          if (5 > ++zaehler)
          { intervall = pausenIntervall;
            schritt = PAUSE;
          } else {
            intervall = nachgiessenIntervall;
            schritt = MESSEN;

Was hast Du vor mit "nachgiessenIntervall"
Ich finde keine verwendung.

MfG

oldmann:
Du hast mir den ganzen Spaß verdorben :wink:
...
Was hast Du vor mit "nachgiessenIntervall"
Ich finde keine verwendung.

Sorry, das wollte ich nicht, Du darfst meinen Beitrag gerne ignorieren :slight_smile:

Ich dachte, nach dem Giessen müßte man eine längere Messpause einlegen, damit sich die Feuchtigkeit ausbreiten kann. Daher habe ich eine längere Pause eingeplant. Aber das ist nur so theoretisch in meiner Phantasie entstanden, ich habe keinen grünen Daumen und keine Erfahrung mit Topfpflanzen.

Ich habe den Zeitvergleich nur einmal drin und variiere dafür den Wert der Variablen intervall.

digitalWrite(relaisPin, HIGH); // Pumpe einschalten

Da die Relais meist mittels LOW aktiviert werden, ist die Logik bei mir umgekehrt.

Als gegen Leistung: :grinning:

Kleine Töpfe – wenig Blumenerde – geringe Speicher Kapazitäten – oft gießen.
Zu viel Wasser schadet dem meisten pflanzen. Weil Wasser kann nicht sofort durch den Boden aufgenommen werden, wenn Zuviel lauft über.
Aus diesem Grunde – gießen, pause, gießen, pause…
10 min später prüft kaum jemand. In der Natur hat die Bodenfeuchtigkeit keinem konstantem wert.

Zu dem Sketch:

Das verstehe ich nicht.

case MESSEN – if Bedingung erfüllt, Pumpe ein, Zähler auf null, für variable „intervall“ der Wert „giessIntervall“ gesetzt und weiter in
case GIESSEN – und hier als erster Schritt: Pumpe aus.

Wie lange ist dann die Pumpe gelaufen?

oldmann:
Wie lange ist dann die Pumpe gelaufen?

intervall = giessIntervall; der fünfte Wert der Struktur, also 500 ms.

Auf dem seriellen Monitor kannst Du Dir das ansehen, habe ich extra dringelassen.

Danke

Ich habe die ganze zeit in der switch Ausführung die braek Anweisung für mich weggedrückt,
also die run Methode quasi als eine Schleife gesehen. Jetzt muss ich das richtig durchkauen.

Zwei Fragen habe ich noch: if (messPin == 15) Serial – warum 15? und wie komm der andere Sensor
auf dem seriellen Monitor?

Hi

oldmann:
Zwei Fragen habe ich noch: if (messPin == 15) Serial – warum 15? und wie komm der andere Sensor
auf dem seriellen Monitor?

So ganz ohne Punkt und Komma ist der Satz einfach nur eine Anreihung von mehr oder minder sinnlosen Buchstaben.
Immerhin auch Große dabei ...
Auch habe ich diesen Snipped in den Code-Tags hier nicht wirklich gefunden - was möchtest Du mir damit sagen, damit ich Dir darauf antworten kann?

MfG

  if (messPin == 15) Serial << "messPin: " << messPin << "  \twert: " << analogRead(messPin) << "  \tintervall: " << intervall << "  \tschritt: " << schritt << "  \tzaehler: " << zaehler << endl;

In den Code im Feld Blumen blumen[] gibt nur zwei werte für messPin: A1 und A2, und hier messPin == 15. Was bedeutet Wert 15?
Auf dem seriellen Monitor wird gezeigt der Wert messPin A1. Wie bekomme ich auf dem seriellen Monitor den anderen Wert: messPin A2?

MfG

oldmann:
Was bedeutet Wert 15?

Die Arduino-Pins haben unterschiedliche Bezeichnungen, bei einem UNO kennst Du die Pins 0 bis 13, A0 ist 14, A1 ist auch 15, A2 ist auch 16 usw.

if (messPin == 16) ...

Bei switch/case hadere ich auch immer mit den Bezeichnungen, weil man vom Warten aus giesst und von Giessen aus wartet. Wenn Dich das stört, kann man das mit einem Merker besser lösen. Siehe #41.