Bewässerungsanlage

Hallo zusammen,
da ich neu in diesem Forum bin möchte ich mich erstmal für die sehr lehrreichen vorhanden Threads bedanken!

Ich bin noch ein absoluter Anfänger in Sachen Arduino und Programmierung, somit bitte ich ein bisschen nachsichtig zu sein :-))

Zu meinem Problem: Ich wollte mir für den Balkon eine einfache Bewässerungsanlage bauen. Diese Anlage soll im ersten Versuch lediglich die Feuchtigkeit messen und bei unterschreiten eines Schwellenwertes ein Relais schalten, welches eine Pumpe steuert. Die Pumpe soll dann für z.B. 30 Sekunden laufen.

Zudem soll eine rote LED und eine grüne LED (wenn alle Pflanzen feucht sind) leuchten.

Nun habe ich folgenden Sketch programmiert. Mein Problem ist, dass bei diesem Sketch lediglich die Rote LED leuchtet und die Tauchpumpe ständig pumpt. Ein Abschalten kommt nicht vor. Auch wenn ich den Sensor in das Wasser halte und der serielle Monitor einen Wert von ca. 50 ausgibt.

unsigned long time;             //Variable für die Zeit
unsigned long PumpON = 3000;    //Wie lange die Pumpe laufen soll, später ca. 20 Sekunden
boolean PumpState = false;      //Pumenstatus
int treshold = 700;             //Wert für die Feuchte wann dei Pumpe einschalten soll
int messwert = 0;               //Variable für den Feuchtewert

void setup() {
  Serial.begin(9600);
  pinMode(13, OUTPUT); // Rote LED Pflanze ist trocken
  pinMode(12, OUTPUT); // Grüne LED Pflanze ist feucht
  pinMode(8, OUTPUT); // Relai Bewässerung
}

void loop() {
  messwert = analogRead(A0);
  Serial.print("Feuchtigkeits-Messwert:");
  Serial.println(messwert);
   
  if (messwert<treshold && PumpState == false){     //Pflanze ist feucht
    digitalWrite(12, HIGH);                    //Grüne LED an
    digitalWrite(13, LOW);                     //Rote LED aus
    digitalWrite(8, LOW);}
     
  else (messwert>treshold && PumpState == false);{     //Pflanze ist trocken
    PumpState = true;
    time = millis();
    digitalWrite (12, LOW);
    digitalWrite (13, HIGH);
    }
    if ((millis() - time) >= PumpON && PumpState == true){
      PumpState = false;
      digitalWrite (12, HIGH);
      digitalWrite (13, LOW);
    }
  delay(10000); //Pause zwischen den Zeiten Original 30 min
}

Was mache ich falsch?

Für euere Hilfe wäre ich sehr dankbar. Gruß

else (messwert>treshold && PumpState == false);

Der Strichpunkt da ist völlig falsch. Der schließt die Bedingung ab. Der Code-Block danach wird immer ausgeführt

Das delay() gehört auch raus. Wenn du nur alle X Minuten was messen willst, dann mach das auch mit millis(). Aber loop() muss ständig durchlaufen damit die An-Zeit der Pumpe korrekt berechnet wird.

Danke für die Antwort. Wusste nicht, dass der ; die Bedienung abschließt. Den ; habe ich deswegen reingemacht, weil ich sonst folgende Fehlermeldung bekomme:

exit status 1
expected ';' before '{' token

Somit geht jetzt aktuell gar nichts mehr :confused:

Im Hinblick auf die Pause zwischen den Messzeiten habe ich leider keine Ahnung, wie ich noch eine weiter Zeitmessung "einbauen" kann. Muss ich diese komplett vor dem ersten "if" vorschalten?

Danke

Es muss natürlich auch "else if" statt "else" heißen. Der Strichpunkt war keine Lösung. Dadurch wurde eine Bedingung wohl zu einer Anweisung. C/C++ Fehler sind manchmal etwas kryptisch wie man hier sieht, aber du musst trotzdem darüber nachdenken woher der Fehler kommt.

Ich habe jetzt nochmal alles überprüft...aber ich bin absolut ratlos, wo genau der/die Fehler sind :o :o

hier nochmal mein aktueller Sketch:

unsigned long time;             //Variable für die Zeit
unsigned long PumpON = 3000;    //Wie lange die Pumpe laufen soll
boolean PumpState = false;      //Pumenstatus
int treshold = 700;             //Wert für die Feuchte wann dei Pumpe einschalten soll
int messwert = 0;               //Variable für den Feuchtewert
unsigned long Pausenzeit = 10000; // Interval für Messungen


void setup() {
  Serial.begin(9600);
  pinMode(13, OUTPUT); // Rote LED Pflanze ist trocken
  pinMode(12, OUTPUT); // Grüne LED Pflanze ist feucht
  pinMode(8, OUTPUT); // Relai Bewässerung
}

void loop() {
  messwert = analogRead(A0);
  Serial.print("Feuchtigkeits-Messwert:");
  Serial.println(messwert);
  time = millis();

  if ((millis() - time) >= Pausenzeit){
    }
       
    else if (messwert<treshold && PumpState == false){     //Pflanze ist feucht
    digitalWrite(12, HIGH);                    //Grüne LED an
    digitalWrite(13, LOW);                     //Rote LED aus
    digitalWrite(8, LOW);}
     
    else if (messwert>treshold && PumpState == false){     //Pflanze ist trocken
    PumpState = true;
    time = millis();
    digitalWrite (12, LOW);
    digitalWrite (13, HIGH);
    }
      if ((millis() - time) >= PumpON && PumpState == true){
      PumpState = false;
      digitalWrite (12, HIGH);
      digitalWrite (13, LOW);
 }     
}

Kann mir bitte jemand helfen?

maze44:
Ich habe jetzt nochmal alles überprüft...aber ich bin absolut ratlos, wo genau der/die Fehler sind :o :o

Kann mir bitte jemand helfen?

Welche Fehlermeldung bekommst du jetzt ?

Evtl. liegt es an deiner IDE-Version.

Ich verwende die Version 1.6.5 und da kompiliert dein obiger Sketch fehlerfrei.

Nur weil etwas kompiliert heißt nicht das es richtig ist. Der Fehler liegt jetzt in der Programm-Logik. Das mit der Pausenzeit ist z.B. falsch. Kann gut sein dass da noch mehr nicht passt.

maze44:
Kann mir bitte jemand helfen?

Morgen gerne. Wenn Dir langweilig ist, kannst Du zum Beispiel etwas zum Thema „endlicher Automat“ oder „Blinken ohne delay()“ lesen. Was mir dazu eingefallen ist, findest Du hier. Das alles in einen Sketch für Dich zu verwandeln, solltest Du nicht tun, bevor Du auch die Folgeseite gelesen hast. Am Ende der Folgeseite sind auch zwei oder drei (soweit ich mich erinnere -- ist nicht erst gestern entstanden) Links zu guten Erklärungen hier im Forum.

Wenn Du klar sagen kannst, was wann passieren soll, wirst Du nur wenig Probleme haben, Deinen Sketch zusammenzuschreiben. Evtl. hilft auch die Seite der Wikipedia zum Thema Programmablaufplan. Je klarer Du formulieren kannst, was Du brauchst (also was wann passieren soll [und für wie lange]), desto schneller kannst Du Dir Deinen Sketch zusammenschreiben.

Und wenn was unklar ist, hier melden :slight_smile:

Gruß

Gregor

Also ein Fehler, der mir direkt ins Auge springt:
Du hast im loop() stehen:
time = millis();
direkt darauf überprüfst Du, ob die Pausenzeit überschritten wird:
if ((millis() - time) >= Pausenzeit){
}
Da er folglich stets die Systemzeit einspeichert und mit dieser wieder vergleicht, wird er nie eine Pause machen.
Die If-Anweisung am Schluss wird er aus dem gleichen Grund auch nicht machen:
if ((millis() - time) >= PumpON && PumpState == true){
PumpState = false;
digitalWrite (12, HIGH);
digitalWrite (13, LOW);
}

Nächstes Problem: ich sehe gar nicht, wo Du die Pumpe überhaupt anschaltest, folgende Zeile fehlt:
digitalWrite(8, HIGH);

Frage: Arbeitet Dein Relais Low-Aktiv? (also mit Low schaltest Du es an, mit High aus)

Danke schon mal für die Antworten. Also an der IDE liegt es nicht...kann den Sketch komplementieren, aber der Arduino macht gerade nicht was er soll :wink:

Den Rest der Antworten muss ich erstmal "auswerten" und nachvollziehen. Sollte dennoch jemand einen Tipp für meinen Sketch haben, bin ich sehr dankbar!

Gruß

Serenifly:
Nur weil etwas kompiliert heißt nicht das es richtig ist. Der Fehler liegt jetzt in der Programm-Logik. Das mit der Pausenzeit ist z.B. falsch. Kann gut sein dass da noch mehr nicht passt.

Völlig klar, aber da hätte der TO sich auch besser ausdrücken können.
Deswegen hatte ich ja nach einer Fehlermeldung gefragt!

Was mir noch einfällt: die IDE markiert time orange, also solltest Du diesen Begriff nicht für eine Variable nutzen.
Habe mir Deinen Code mal vorgenommen und ihn soweit umgeschrieben, dass er funktionieren und für Deine Kenntnisse verständlich sein sollte. Weiteres wäre z.B. der Einsatz von Konstanten für die Pins; Verbesserung der If-Bedingungen (booleans können statt PumpState==true auch einfach Pumpstate oder statt PumpState==false als !PumpState abgefragt werden; Ausschalten der Seriellen Konsole wenn nicht benötigt (so wird das System stets Daten über die serielle Schnittstelle senden, obwohl Du es, wenn fertig, bestimmt nicht mehr an einer Konsole hängen lässt.
Was ich nochmals fragen muss: Wird das Relais low-aktiv betrieben? Wenn ja, dann wird die Pumpe nach diesem Code genau umgekehrt zu Deinen Vorstellungen laufen. Was dagegen zu tun ist, wirst Du sicherlich wissen :wink:
Hier der Code:

unsigned long zeit=0;           //Variable für die Zeit (Überprüfung a)
unsigned long PumpON = 3000;    //Wie lange die Pumpe laufen soll
boolean PumpState = false;      //Pumpenstatus
int treshold = 700;             //Wert für die Feuchte wann dei Pumpe einschalten soll
int messwert = 0;               //Variable für den Feuchtewert
unsigned long Pausenzeit = 10000; // Interval für Messungen


void setup() {
  Serial.begin(9600);
  pinMode(13, OUTPUT); // Rote LED Pflanze ist trocken
  pinMode(12, OUTPUT); // Grüne LED Pflanze ist feucht
  pinMode(8, OUTPUT); // Relais Bewässerung
}

void loop() {
  if (PumpState==false && (millis() - zeit) >= Pausenzeit){    //wenn Pausenzeit vorbei
    messwert = analogRead(A0);
    Serial.print("Feuchtigkeits-Messwert:");
    Serial.println(messwert);
    zeit = millis();
    if (messwert<treshold){                      //Pflanze ist feucht
      digitalWrite(12, HIGH);                    //Grüne LED an
      digitalWrite(13, LOW);                     //Rote LED aus
      digitalWrite(8, LOW);                      //Pumpe aus
    }else if (messwert>treshold){                //Pflanze ist trocken
      PumpState = true;
      digitalWrite (12, LOW);                    //Grüne LED aus
      digitalWrite (13, HIGH);                   //Rote LED an
      digitalWrite(8, HIGH);                     //Pumpe an
    }
  }else if (PumpState==true && (millis() - zeit) >= PumpON){
    PumpState = false;
    zeit = millis();
  }
}

@DerLehmi:
Vielen Dank für deine Ausführungen + Sketch!

Anhand deines Sketches kann ich viel lernen und nachvollziehen. Nochmals danke!

Wie sich herausgestellt hat, verwende ich ein low-aktiv Relais. Jetzt hab ich auch schon einiges über high-aktiv und low-aktiv Relais nachgelesen (wusste nicht, dass es eine Unterschied gibt :-)).

Zum Teil wird in diversen Foren geschrieben, dass man einen Widerstand zwischen dem Spannungskabel des Arduinos und Relais hängen soll. Dies soll zu einer Verzögerung der ersten Schaltung führen.
Auch wird zum Teil ausgeführt, dass im void setup() einfach "digitalWrite(PIN Relai, HIGH); gesetzt werden soll.

Beides funktioniert bei mir nicht. Kannst Du mir nochmal eine kurze Erklärung geben?

Vielen Dank nochmal!

http://forum.arduino.cc/index.php?topic=335254.msg2312421#msg2312421

Aktiv Low Geräte (solche Relais) machen am AVR keine Sorgen, wenn man folgendes Verfahren einhält:

  1. pinMode(xx,INPUT_PULLUP);
  2. pinMode(xx,OUTPUT);

Dann geht der Pin ohne zwischenzeitliche/versehentliche LOW Phase direkt von hochohmig, über eine mini Pullup Phase, zu HIGH.

Vielen Dank für die umfangreiche Hilfe!

Jetzt funktioniert alles so, wie ich es mir vorgestellt habe.

Hier nochmal der fertige Sketch:

unsigned long zeit=0;           //Variable für die Zeit (Überprüfung a)
unsigned long PumpON = 3000;    //Wie lange die Pumpe laufen soll
boolean PumpState = false;      //Pumpenstatus
int treshold = 700;             //Wert für die Feuchte wann dei Pumpe einschalten soll
int messwert = 0;               //Variable für den Feuchtewert
unsigned long Pausenzeit = 10000; // Interval für Messungen


void setup() {
  Serial.begin(9600);
  pinMode(13, OUTPUT); // Rote LED Pflanze ist trocken
  pinMode(12, OUTPUT); // Grüne LED Pflanze ist feucht
  pinMode(8, INPUT_PULLUP);
  pinMode(8, OUTPUT);          // Relais Bewässerung
 
}

void loop() {
  if (PumpState==false && (millis() - zeit) >= Pausenzeit){    //wenn Pausenzeit vorbei
    messwert = analogRead(A0);
    Serial.print("Feuchtigkeits-Messwert:");
    Serial.println(messwert);
    zeit = millis();
    if (messwert<treshold){                      //Pflanze ist feucht
      digitalWrite(12, HIGH);                    //Grüne LED an
      digitalWrite(13, LOW);                     //Rote LED aus
      digitalWrite(8, HIGH);                      //Pumpe aus
    }else if (messwert>treshold){                //Pflanze ist trocken
      PumpState = true;
      digitalWrite (12, LOW);                    //Grüne LED aus
      digitalWrite (13, HIGH);                   //Rote LED an
      digitalWrite(8, LOW);                     //Pumpe an
    }
  }else if (PumpState==true && (millis() - zeit) >= PumpON){
    PumpState = false;
    zeit = millis();
    digitalWrite(8, HIGH);
  }
}

Schön, dass Dir hier geholfen werden konnte :slight_smile:

digitalWrite(PIN Relais, HIGH); gesetzt werden soll.

-->Der Ausgang wird normalerweise mit Low initialisiert, d.h. Dein Relais würde durchschalten, und der eigentliche Wunschzustand würde erst nach dem ersten Schaltvorgang im Programm eintreten.
Daher setzt man den Ausgang direkt nach der Deklarierung auf High (also man schaltet das Relais gleich aus).

  1. pinMode(xx,INPUT_PULLUP);
  2. pinMode(xx,OUTPUT);

Dann geht der Pin ohne zwischenzeitliche/versehentliche LOW Phase direkt von hochohmig, über eine mini Pullup Phase, zu HIGH.

-->Diese Methode war mir bisher nicht bewusst, man lernt eben nie aus....Danke dafür (y)

DerLehmi:
....Danke dafür (y)

Bitte gerne :slight_smile: