Eine Kleine Bewässerungssteuerung

Hallo allerseits,

nun hab ich mal ne Idee hab Sie Auch soweit umgesetzt aber ganz zufrieden bin ich natürlich nicht.
Ich habe eine Arduino Mega mit Lan Shield und eine 8fach Relay board.

Meine Zielsetzung war es eine kleine Bewässerungssteuerung zu schreiben hierfür habe ich einfach den Code vom blink bespiel werwendet.

Allerdings möchte ich auch meine Pumpe hierdrüber und irgendwie bekomme ich das nicht hin das es simultan Läuft.

Ich würde mich sehr freuen wenn einer von euch eine Idee hat.

/*
  Bewässerungssteuerung für 7 Kreisen, 2 Zyklen täglich und 1 Pumpe
 */
 
// Pin 22 - 29 Asugang zum Relay
// give it a name:
int relay1 = 22;
int relay2 = 23;
int relay3 = 24;
int relay4 = 25;
int relay5 = 26;
int relay6 = 27;
int relay7 = 28;
int relay8 = 29;
// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
  pinMode(relay3, OUTPUT);
  pinMode(relay4, OUTPUT);
  pinMode(relay5, OUTPUT);
  pinMode(relay6, OUTPUT);
  pinMode(relay7, OUTPUT);
  pinMode(relay8, OUTPUT);
}
void loop (1) {
  digitalWrite(relay8, HIGH);   
  delay(3454000);               // Pumpe
  digitalWrite(relay8, LOW);   
  
  delay(39746000);                  // Föderunterbrechung bis Neustart
}

// the loop routine runs over and over again forever:
void loop(2) {
  digitalWrite(relay1, HIGH);   
  delay(235500);               // Beregnungsdauer Kreis 1
  digitalWrite(relay1, LOW);   
  
  digitalWrite(relay2, HIGH);   
  delay(340167);               // Beregnungsdauer Kreis 2
  digitalWrite(relay2, LOW);   
  
  digitalWrite(relay3, HIGH);   
  delay(287833);               // Beregnungsdauer Kreis 3
  digitalWrite(relay3, LOW);   
  
  digitalWrite(relay4, HIGH);   
  delay(680333);               // Beregnungsdauer Kreis 4
  digitalWrite(relay4, LOW);   
 
  digitalWrite(relay5, HIGH);   
  delay(471000);               // Beregnungsdauer Kreis 5
  digitalWrite(relay5, LOW);   
  
  digitalWrite(relay6, HIGH);   
  delay(497167);               // Beregnungsdauer Kreis 6
  digitalWrite(relay6, LOW);   
  
  digitalWrite(relay7, HIGH);   
  delay(942000);               // Beregnungsdauer Kreis 7
  digitalWrite(relay7, LOW);   
  
  delay(39746000);                  // Beregnungsunterbrechung bis Neustart
}

Die Delays sind absolut kontraproduktiv! Schau dir blinkwithoutdelay an.

Danke für den Hinweis allerdings erschließt sich mir noch nicht wie ich hier für jeden kreis eine Feste zeit eingeben kann.

So, wie du das programmiert hast, läuft das streng sequenziell ab.

digitalWrite(relay2, HIGH); // Relais2 ein
delay(340167); // mach 340167ms nichts
digitalWrite(relay2, LOW); // Relais2 aus

Ein delay() bedeuted, dass der Arduino stehen bleibt und auf nichts reagiert.

du muss dafür sorgen, dass die loop() ständig durchlaufen wird.

Dann hast du irgendwo eine Tabelle, in der steht, wann die einzelnen Aktionen stattfinden sollen. Du fragst nur ab, ob der Zeitpunkt gekommen ist, und löst die entsprechende Aktion aus.
so kannst du deine Aktionen beliebig ineinander verschachteln.

Such doch mal im Forum. Hier gabs schon einige Bewässerungsprojekte.

Und es gab mal einen Fred zu einer Modellbahn Hausbeleuchtung, bei auch verschiedene Aktionen zeitlich versetzt stattfinden sollen. Ein sehr ähnliches Problem.

Hallo Günther,
leider komm ich irgendwie mit der suche nicht so ganz klarimmer wenn ich da was eingebe komm ich bei google raus.
Ein weiteres Problem was ich habe ist das ich im Englischen nicht so firm bin.
Warum ist delay zu vermeiden ???

Weil du dann während der Zeit nichts anders machen kannst. z.B. nicht mehrere Relais gleichzeitig mit unterschiedlichen Zeiten.

Auf Timer0 wird aber im Millisekunden-Takt eine Variable hochgezählt. Deren Stand bekommst du mit millis(). Dadurch kann man Zeitstempel ablegen und ausrechnen wie viel Zeit seit einem bestimmten Ereignis vergangen ist. Also eine Zeitdauer bestimmen ohne dass alles blockiert ist.

Was du da mit loop() machst passt übrigens auch nicht so recht. Und die Pins kann man schön in einem Array unterbringen.

Weil du dann während der Zeit nichts anders machen kannst. z.B. nicht mehrere Relais gleichzeitig mit unterschiedlichen Zeiten.

Ok das klingt Logisch das versteh ich

Weil du dann während der Zeit nichts anders machen kannst. z.B. nicht mehrere Relais gleichzeitig mit unterschiedlichen Zeiten.

darauf kann ich mir einen Reim machen.

Der Rest naja irgendwie kann ich da nicht mehr folgen?!?!?

Sorry bin echt neu in dem Thema ich hab schonmal ein Projekt damit Probiert aber hab auch damals das ganze nicht so recht verstanden.

Guten Morgen allerseits,

ich habe gestern durch zufall noch eine Lösung gefunden die Einfach und funktional ist.

/*
  Bewässerungssteuerung mit 7 Beregnungs Zyklen, 2 Tageszyklen. und Pumpensteuerung
  Stand 05.05.15 23:17
 */
 
// Pin 22 - 29 zur Ansteuerung der Ventile über Relay´s
// give it a name:
int relay1 = 22;
int relay2 = 23;
int relay3 = 24;
int relay4 = 25;
int relay5 = 26;
int relay6 = 27;
int relay7 = 28;
int relay8 = 29;
// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
  pinMode(relay3, OUTPUT);
  pinMode(relay4, OUTPUT);
  pinMode(relay5, OUTPUT);
  pinMode(relay6, OUTPUT);
  pinMode(relay7, OUTPUT);
  pinMode(relay8, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {    
  digitalWrite(relay8, HIGH);  // Pumpe an
                                                    // alle Zeiten ca.
  digitalWrite(relay1, HIGH);   
  delay(235500);               // Beregnungsdauer Kreis 1 = 4 Minuten
  digitalWrite(relay1, LOW);    
  
  digitalWrite(relay2, HIGH);   
  delay(340167);               // Beregnungsdauer Kreis 2 = 6 Minuten
  digitalWrite(relay2, LOW);    
  
  digitalWrite(relay3, HIGH);   
  delay(287833);               // Beregnungsdauer Kreis 3 = 5 Minuten
  digitalWrite(relay3, LOW);    
  
  digitalWrite(relay4, HIGH);   
  delay(680333);               // Beregnungsdauer Kreis 4 = 11 Minuten
  digitalWrite(relay4, LOW);    
 
  digitalWrite(relay5, HIGH);   
  delay(471000);               // Beregnungsdauer Kreis 5 = 8 Minuten
  digitalWrite(relay5, LOW);    
  
  digitalWrite(relay6, HIGH);   
  delay(497167);               // Beregnungsdauer Kreis 6 = 8 Minuten
  digitalWrite(relay6, LOW);    
  
  digitalWrite(relay7, HIGH);   
  delay(942000);               // Beregnungsdauer Kreis 7 = 16 Minuten
  digitalWrite(relay7, LOW);    
 
  digitalWrite(relay8, LOW);   // Pumpe aus
  //digitalWrite(relay8, HIGH);   
  //delay(1000);               // Beregnungsdauer Kreis 8
  //digitalWrite(relay8, LOW);    
  
  delay(39746000);                  // Beregnungsunterbrechung bis Neustart
}

dennoch bin ich sehr interessiert die richtige umsetzung zu verstehen. Denn das Board nur für die Bewässerung zu benutzen wäre doch reichlich übertrieben.

Holzjunkie:
Hallo Günther,
leider komm ich irgendwie mit der suche nicht so ganz klarimmer wenn ich da was eingebe komm ich bei google raus.

Ja, du kommst bei Google raus, aber als Suchergebnisse kommen nur Arduino-Forumsseiten. (bis auf die ersten paar Werbelinks)

Holzjunkie:
Ein weiteres Problem was ich habe ist das ich im Englischen nicht so firm bin.

Wenn du nach "Bewässerung" suchst, kannst du davon ausgehen, dass die Suchergebnisse überwiegend deutsch sind. ::slight_smile:

Holzjunkie:
Warum ist delay zu vermeiden ???

Dazu hast du ja schon Antworten. Und sonst: nimm dir das BlinkwithoutDelay Beispiel und versuche das zu verstehen.
Dann baust du eine zweite LED ein, die mit anderen Zeiten blinken soll.

Grüße

Gunther

Holzjunkie:
ich habe gestern durch zufall noch eine Lösung gefunden die Einfach und funktional ist.

Was dort im Code gezeigt wird mag zwar funktionieren und für Spezialfälle auch ausreichend sein, hat aber mit "schöner" Programmierung nichts zu tun.
Nehmen wir mal ein einfaches Beispiel zur Erweiterung des bestehenden Codes an: Die ganze Anlage soll über einen Not-Aus-Schalter deaktiviert werden können. In der setup() wird ein Eingang definiert und der loop() abgefragt. Allerdings ist der Programmablauf blockiert (hier durch die delay()-Anweisungen), erst nach einmaligem Komplettdurchlauf ist die Anlage abschaltbar!
Man köntne weitere Beispiele benennen wie blinkende LEDs als Anzeige einer laufenden Pumpe oder eine parallel laufende Temperaturanzeige usw.. All das ist mit diesem Programmierstil gar nicht möglich, da könnte man ebensogut ein paar billige Zeitschaltuhren nehmen.

Holzjunkie:
Ich würde mich sehr freuen wenn einer von euch eine Idee hat.

Die von Dir beschriebene Aufgabe (eine Bewässerungspumpe bewässert zyklisch nacheinander verschiedene Segmente, die über Ventile gesteuert werden) ist extrem simpel und kann von Dir wahlweise mit einer einfachen und den Programmablauf blockierenden "delay" Logik realisiert werden, so dass außer den genannten Schaltfunktionen nichts anderes mehr laufen kann.

Oder wahlweise auch mit einer blockierfreien Steuerung ohne delay(), bei der man dann zum Beispiel auch noch einen Button überwachen könnte, der zwischen verschiedenen Betriebsarten umschalten kann, z.B. "Automatikbetrieb" und "Aus". Oder sogar noch kompliziertere Dinge.

Um das 12-Stunden-Intervall täglich zu einer bestimmten Uhrzeit zu starten, würdest Du eine RTC Echtzeituhr in Deiner Schaltung (und im Programm) benötigen.

Ansonsten fängt der 12h Ablauf immer dann neu an zu laufen, wenn das Arduino Board einen Power-On-Reset oder Reset per Reset-Knopf bekommt.

Einfachster Ablauf mit blockierender Logik, ungetestetes Codebeispiel für "Active HIGH" schaltende Solid-State-Relais:

#define RELAY_PUMPE 13  // a pin number to switch HIGH/LOW in intervals
byte relayVentile[]={2,3,4,5,6,7,8,9};       // switches for duration
#define RELAY_ACTIVE HIGH

#define MILLISECONDS_PER_DAY 86400000L
#define MILLISECONDS_PER_HOUR 3600000L
#define MILLISECONDS_PER_MINUTE 60000L
#define MILLISECONDS_PER_SECOND 1000L

long durationON[]={ // ON time in milliseconds
  5*MILLISECONDS_PER_MINUTE, // erstes Ventil 5 Minuten
  6*MILLISECONDS_PER_MINUTE, // zweites Ventil 6 Minuten
  7*MILLISECONDS_PER_MINUTE, 
  8*MILLISECONDS_PER_MINUTE, 
  9*MILLISECONDS_PER_MINUTE, 
  10*MILLISECONDS_PER_MINUTE, 
  11*MILLISECONDS_PER_MINUTE,
  1*MILLISECONDS_PER_HOUR+2*MILLISECONDS_PER_MINUTE+3*MILLISECONDS_PER_SECOND, 
};  // letztes Ventil: 1 Stunde und 2 Minuten und 3 Sekunden

void setup() {
  // alle Relais-Pins auf AUS und OUTPUT schalten
  digitalWrite(RELAY_PUMPE,!RELAY_ACTIVE);
  pinMode(RELAY_PUMPE,OUTPUT);
  for (int i=0;i<sizeof(relayVentile);i++)
  {
    digitalWrite(relayVentile[i],!RELAY_ACTIVE);
    pinMode(relayVentile[i],OUTPUT);
  }
}

void loop() {
  unsigned long startTime=millis();   // Startzeit merken
  digitalWrite(RELAY_PUMPE,RELAY_ACTIVE); // Pumpe ein
  for (int i=0;i<i<sizeof(relayVentile);i++) // Alle Ventile in for-Schleife nacheinander
  {
    digitalWrite(relayVentile[i],RELAY_ACTIVE); // Ventil ein
    delay(durationON[i]);    // Ventil offen für bestimmte Dauer
    digitalWrite(relayVentile[i],!RELAY_ACTIVE); // Ventil aus
  }
  digitalWrite(RELAY_PUMPE,!RELAY_ACTIVE); // Pumpe aus
  long duration=millis()-startTime; // Dauer bis hierher
  delay(12*MILLISECONDS_PER_HOUR-duration); // Rest bis 12h Pause
}

Für mechanische Relais, die meist auf "Active LOW" schaltend konfiguriert sind, im Code verwenden:

#define RELAY_ACTIVE LOW

Hallo Jurs,

vielen dank für dein Beispiel ich habe mir die Freiheit genommen und es für mich verständlich zukommentiren.
Allerdings verstehe ich nicht ganz warum sich die Pumpe nicht abschaltet.

Das Fehlt mir jetzt noch irgend wie.
Ein RTC Modul habe ich mir jetzt auch noch bestellt.
Ich will in Laufe der Woche nochmal sehen ob ich daraus jetzt ein Programm hinbekomme ohne Delay.

Dennoch hier nochmal der Code die Zeiten habe ich jetzt abgewandelt um das ganze schneller Kontrollieren zu können.

#define RELAY_PUMPE 9                      // Ausgang für Relay Anschluss Pumpe Pin 2
byte relayVentile[]={2,3,4,5,6,7,8};       // Ausgänge für Relay Anschluss Beregnungskreise Pin 3-9
#define RELAY_ACTIVE HIGH                  

#define MILLISECONDS_PER_DAY 86400000L     // dauer eines Tages in Millisekunden
#define MILLISECONDS_PER_HOUR 3600000L     // dauer eines Tages in Millisekunden
#define MILLISECONDS_PER_MINUTE 60000L     // dauer eines Tages in Millisekunden
#define MILLISECONDS_PER_SECOND 1000L      // dauer eines Tages in Millisekunden

long durationON[]={                        // Einschaltzeiten der Relays
                                           // 60*MILLISECONDS_PER_SECOND+2*MILLISECONDS_PER_MINUTE+3*MILLISECONDS_PER_SECOND = Ansteuerzeit: 1 Stunde und 2 Minuten und 3 Sekunden
  4*MILLISECONDS_PER_SECOND,               // Ventil 1 einschaltzeit = 5 Minuten
  6*MILLISECONDS_PER_SECOND,               // Ventil 2 einschaltzeit = 6 Minuten
  5*MILLISECONDS_PER_SECOND,               // Ventil 3 einschaltzeit = 7 Minuten
  11*MILLISECONDS_PER_SECOND,               // Ventil 4 einschaltzeit = 8 Minuten
  8*MILLISECONDS_PER_SECOND,               // Ventil 5 einschaltzeit = 9 Minuten
  8*MILLISECONDS_PER_SECOND,              // Ventil 6 einschaltzeit = 10 Minuten 
  11*MILLISECONDS_PER_SECOND,              // Ventil 7 einschaltzeit = 11 Minuten
  1*MILLISECONDS_PER_MINUTE+10*MILLISECONDS_PER_SECOND,              // Relay Pumpe einschaltzeit = 1 Stunde 1 Minute 
};  

void setup() {                             // Anfang der Setup Einstellungen
  
  digitalWrite(RELAY_PUMPE,!RELAY_ACTIVE);  // Setze digitalenWert (1 od. 0) für Pumpen Relay auf 0 (!RELAY_ACTIVE) also AUS
  pinMode(RELAY_PUMPE,OUTPUT);              // definiert Pin 2 (RELAY_PUMPE) als output
  for (int i=0;i<sizeof(relayVentile);i++)  // ???
  {                                         // ???
  digitalWrite(relayVentile[i],!RELAY_ACTIVE);  //Setze digitalenWert (1 od. 0) für alle ([i]) Ventil Relay´s auf 0 (!RELAY_ACTIVE) also AUS
    pinMode(relayVentile[i],OUTPUT);              // definiert Pin 3-9 (RELAY_VENTILE[i]) als output
  }                                         // ???
}                                           // Beendet die Setup Einstellungen

void loop() {                               // Beginn der Programm endlosschleife
  unsigned long startTime=millis();         // Startzeit merken in Millisekunden ???unsigned long???
  digitalWrite(RELAY_PUMPE,RELAY_ACTIVE);   // Setze digitalenWert (1 od. 0) für Pumpen Relay auf 1 (RELAY_ACTIVE)also AN
  for (int i=0;i<i<sizeof(relayVentile);i++)// ???
  {
    digitalWrite(relayVentile[i],RELAY_ACTIVE);   // Setze digitalenWert (1 od. 0) für Ventil Relay´s auf 1 (RELAY_ACTIVE)also AN
    delay(durationON[i]);                         // Ventil offen für bestimmte Dauer
    digitalWrite(relayVentile[i],!RELAY_ACTIVE);  //Setze digitalenWert (1 od. 0) für alle ([i]) Ventil Relay´s auf 0 (!RELAY_ACTIVE) also AUS
  }
    digitalWrite(RELAY_PUMPE,!RELAY_ACTIVE);      // Setze digitalenWert (1 od. 0) für Pumpen Relay auf 0 (!RELAY_ACTIVE) also AUS
  long duration=millis()-startTime;               // Dauer bis hierher
  delay(12*MILLISECONDS_PER_SECOND-duration); // Rest bis 12h Pause ???Hier Stimmt was nicht??? er geht nicht aus!!!!
}

Vielen vielen Dank das war mir schonmal eine große hilfe jetzt muß ich das nurnoch nachvollziehen und verstehen lernen.

Hier passt was nicht mit der Syntax:

for (int i=0;i<i<sizeof(relayVentile);i++)

Das ist ein "i <" zu viel drin.

Die for-Schleifen iterieren einfach über alle Relais.

Holzjunkie:
Allerdings verstehe ich nicht ganz warum sich die Pumpe nicht abschaltet.

Das Fehlt mir jetzt noch irgend wie.

Dass der "Code ungetestet" ist, habe ich dazugeschrieben, als ich den gepostet habe.

Das "i zuviel" hat Serenifly bereits erkannt, das ist falsch und die Zeile sollte lauten:

  for (int i=0;i<sizeof(relayVentile);i++) // Alle Ventile in for-Schleife nacheinander

Im übrigen solltest Du, wenn Du das Array "relayVentile[]" auf 7 Ventile reduzierst,

byte relayVentile[]={2,3,4,5,6,7,8};       // Ausgänge für Relay Anschluss Beregnungskreise Pin 3-9

erstens darauf achten, dass die tatsächlichen Pin-Deklarationen der Ventile (2-8) mit dem Kommentar (3-9) zusammenpassen sollten, da hast Du eine Diskrepanz drin.

Und wenn es nur 7 Ventile gibt, wären in dem Fall auch die definierten Schaltzeiten auf 7 Schaltzeiten zu reduzieren:

long durationON[]={ // ON time in milliseconds
  5*MILLISECONDS_PER_MINUTE, // erstes Ventil 5 Minuten
  6*MILLISECONDS_PER_MINUTE, // zweites Ventil 6 Minuten
  7*MILLISECONDS_PER_MINUTE, // drittes Ventil
  8*MILLISECONDS_PER_MINUTE, // viertes Ventil
  9*MILLISECONDS_PER_MINUTE, // fünftes Ventil
  10*MILLISECONDS_PER_MINUTE, // sechstes Ventil
  11*MILLISECONDS_PER_MINUTE,// siebentes (und letztes) Ventil
};

Wenn nur 7 Ventile geschaltet werden, werden ja keine 8 Ventilschaltdauern benötigt, sondern auch nur 7.

Hallo und guten Morgen,

ich danke euch für eure hilfe nun funktioniert alles. Jetzt werde ich das ganze versuchen genauer nachzuvollziehen um es dann weiter anzupassen.

@entschuldige bitte ich wollte mich nicht über deine Hilfe beschweren. Ich hab nur selbst nicht den Fehler gefunden.