Bordcomputer defekt nach einem halben Jahr Dauerbetrieb, auf Fehlersuche

Hallo liebe community.

Ich habe vor einem halben Jahr ein Aeroponik- System gebaut. Ein Bordcomputer fragt Werte von Sensoren ab ( 2x Temperatursensoren, 1x Feuchtigkeitssensor) und zeigt diese auf einem LCD- Display an. Abhängig von zwei Schwimmerschaltern (Minimum und Maxium) werden Geräte (Heizstab, Wasserförderpumpe, Hochdruckpumpe, Luftpumpe, Umwälzpumpe, Förderpumpe) ein- oder ausgeschaltet. Der Schwimmerschalter (Minimum) schaltet alle Geräte ab, also eine Notabschaltung, und eine Förderpumpe an, die den Tank wieder auffüllt. Der Schwimmerschalter (Maximum) schaltet die Förderpumpe aus wenn der Tank voll ist. Das Programm periodic_pump regelt die Intervall- Bewässerung per Hochdruckpumpe des Aeroponik- Systems solange Wasser Im Tank ist.

Im Anhang befindet sich der Schaltplan.

Jetzt zum Problem:
Der Bordcomputer hat ein halbes Jahr ohne Probleme funktioniert und alles erfolgreich geregelt. Gestern plötzlich hat er die Hochdruckpumpe jedoch nicht mehr ausgeschaltet. Außerdem hat er komische ( negative Werte) für die Luftfeuchtigkeit angezeigt. Ich habe dann den Stecker gezogen und wieder reingesteckt. Danach hat er die Hochdruckpumpe immer noch nicht wieder ausgeschaltet und es sind gar keine Werte mehr auf dem LCD- Display erschienen.

Ich habe folgendes ausprobiert:

  • geschaut ob alle Stecker noch stecken, sich nichts gelöst hat usw.
  • Programm neu hochgeladen
  • Arduino Uno durch einen neuen ausgetauscht
    ... alles ohne Erfolg

dann habe ich einen neuen Sketch hochgeladen, der nur die periodic_pump beeinhaltet, um zu sehen ob das Relais, das die Hochdruckpumpe schaltet kaputt gegangen ist. Mit dem Sketch hat der Arduino Uno die Hochdruckpumpe wieder wie gewohnt an und ausgeschaltet, am Relais kann es also nicht liegen.

// Sketch reduziert auf periodic pump

// Pumpensteuerung // Der Sketch funktioniert einwandfrei

unsigned long timestore_Pumpensteuerung;               // Zeitmerker für Pumpensteuerung

// Pins für Heizstab, Hochdruckpumpe, Umwaelzpumpe und Foerderpumpe
int RelaisHeizstab = 8;                   // eigentlich 8
int RelaisHochdruckpumpe = 9;             // eigentlich 9
int RelaisUmwaelzpumpe = 10;
int RelaisFoerderpumpe = 11;

void setup() {

  // Deklarieren der Pins
  pinMode(RelaisHeizstab, OUTPUT);
  pinMode(RelaisHochdruckpumpe, OUTPUT);
  pinMode(RelaisUmwaelzpumpe, OUTPUT);
  pinMode(RelaisFoerderpumpe, OUTPUT);

  // Ausgangszustände herstellen
  digitalWrite(RelaisHeizstab, LOW);                  // Der Heizstab ist normalerweise an
  digitalWrite(RelaisHochdruckpumpe, LOW);            // Die Hochdruckpumpe ist normalerweise an
  digitalWrite(RelaisUmwaelzpumpe, LOW);              // Die Umwaelzpumpe ist normalerweise an
  digitalWrite(RelaisFoerderpumpe, HIGH);             // Die Förderpumpe ist normalerweise aus
}

void loop()
{
  // Pumpensteuerung
  periodicPump();
}

void periodicPump()                                                                           //DANN geht es hier weiter
{
  if (digitalRead(RelaisHochdruckpumpe) && (millis() - timestore_Pumpensteuerung > 90000))     // wenn der PumpenPin HIGH (aus) ist und die Zeit abgelaufen // anfangs hatte ich hier 900000 also 15 Minuten // jetzt 90000 also 1,5 Minuten
  {
    digitalWrite(RelaisHochdruckpumpe, LOW);                                                  // Pumpenpin LOW setzen ( an)
    timestore_Pumpensteuerung = millis();                                                     // Zeit merken
  }
  if (!digitalRead(RelaisHochdruckpumpe) && (millis() - timestore_Pumpensteuerung > 2000))   // Wenn PumpenPin  LOW ist ( an) UND Zeit abgelaufen // anfangs hatte ich hier 15000 also 15 Sekunden // jetzt 2000 also 2 Sekunden
  {
    digitalWrite (RelaisHochdruckpumpe, HIGH);                                                // Pumpe aus machen
    timestore_Pumpensteuerung = millis();                                                     // Zeit merken
  }
}

Dann habe ich den Teil, für das Abfragen der Sensorwerte und das Anzeigen auf dem LCD wieder mit reingenommen. Dann hat die Intervallbewässerung wieder nicht funktionert.

//Sketch alles außer LCD- Display funktioniert nicht.

// Ezo-Hum-Sensor

//This code was written to be easy to understand.
//Modify this code as you see fit.
//This code will output data to the Arduino serial monitor.
//Type commands into the Arduino serial monitor to control the humidity sensor.
//This code was written in the Arduino 1.8.13 IDE
//An Arduino UNO was used to test this code.
//This code was last tested 8/2020


#include <SoftwareSerial.h>                           //we have to include the SoftwareSerial library, or else we can't use it
#define rx 4                                         //define what pin rx is going to be
#define tx 5                                         //define what pin tx is going to be

SoftwareSerial myserial(rx, tx);                      //define how the soft serial port is going to work


String inputstring = "";                              //a string to hold incoming data from the PC
String sensorstring = "";                             //a string to hold the data from the Atlas Scientific product
boolean input_string_complete = false;                //have we recived all the data from the PC
boolean sensor_string_complete = false;               //have we recived all the data from the Atlas Scientific product

// Pumpensteuerung
unsigned long timestore_Pumpensteuerung;               // Zeitmerker für Pumpensteuerung


// Steuerung von Heizstab, Hochdruckpumpe, Umwaelzpumpe und Foerderpumpe
int RelaisHeizstab = 8;
int RelaisHochdruckpumpe = 9;
int RelaisUmwaelzpumpe = 10;
int RelaisFoerderpumpe = 11;

int Niveauschalterminimum = 2;
int Niveauschaltermaximum = 6;
bool Auffuellvorgang = false; // Auffüllvorgang ist nicht aktiviert


void setup() {

  // Ezo-Hum-Sensor
  Serial.begin(9600);                                 //set baud rate for the hardware serial port_0 to 9600
  myserial.begin(9600);                               //set baud rate for the software serial port to 9600
  inputstring.reserve(10);                            //set aside some bytes for reciving data from the PC
  sensorstring.reserve(30);                           //set aside some bytes for reciving data from Atlas Scientific product


  // Notabschaltung Heizstab, Hochdruckpumpe, Umwaelzpumpe und Foerderpumpe
  pinMode(RelaisHeizstab, OUTPUT);
  pinMode(RelaisHochdruckpumpe, OUTPUT);
  pinMode(RelaisUmwaelzpumpe, OUTPUT);
  pinMode(RelaisFoerderpumpe, OUTPUT);
  pinMode(Niveauschalterminimum, INPUT_PULLUP);
  pinMode(Niveauschaltermaximum, INPUT_PULLUP);

  digitalWrite(RelaisHeizstab, LOW);
  digitalWrite(RelaisHochdruckpumpe, LOW);
  digitalWrite(RelaisUmwaelzpumpe, LOW);
  digitalWrite(RelaisFoerderpumpe, HIGH);             // Die Förderpumpe ist normalerweise aus
}

//Ezo-Hum-Sensor
void serialEvent() {                                  //if the hardware serial port_0 recives a char
  inputstring = Serial.readStringUntil(13);           //read the string until we see a <CR>
  input_string_complete = true;                       //set the flag used to tell if we have recived a completed string from the PC
}
void loop() {

  //Ezo-Hum-Sensor
  if (input_string_complete == true) {                //if a string from the PC has been recived in its entirety
    myserial.print(inputstring);                      //send that string to the Atlas Scientific product
    myserial.print('\r');                             //add a <CR> to the end of the string
    inputstring = "";                                 //clear the string
    input_string_complete = false;                    //reset the flag used to tell if we have recived a completed string from the PC
  }

  if (myserial.available() > 0) {                     //if we see that the Atlas Scientific product has sent a character
    char inchar = (char)myserial.read();              //get the char we just recived
    sensorstring += inchar;                           //add the char to the var called sensorstring
    if (inchar == '\r') {                             //if the incoming character is a <CR>
      sensor_string_complete = true;                  //set the flag
    }
  }

  if (sensor_string_complete == true) {               //if a string from the Atlas Scientific product has been recived in its entirety
    if (isdigit(sensorstring[0]) == false) {          //if the first character in the string is a digit
      Serial.println(sensorstring);                   //send that string to the PC's serial monitor
    }
    else                                              //if the first character in the string is NOT a digit
    {
      print_Humidity_data();                          //then call this function
    }
    sensorstring = "";                                //clear the string
    sensor_string_complete = false;                   //reset the flag used to tell if we have recived a completed string from the Atlas Scientific product
  }
}

void print_Humidity_data(void) {                      //this function will pars the string

  char sensorstring_array[30];                        //we make a char array
  char *HUM;                                          //char pointer used in string parsing.
  char *TMP;                                          //char pointer used in string parsing.
  char *NUL;                                          //char pointer used in string parsing (the sensor outputs some text that we don't need).
  char *DEW;                                          //char pointer used in string parsing.

  float HUM_float;                                      //float var used to hold the float value of the humidity.
  float TMP_float;                                      //float var used to hold the float value of the temperatur.
  float DEW_float;                                      //float var used to hold the float value of the dew point.

  sensorstring.toCharArray(sensorstring_array, 30);   //convert the string to a char array
  HUM = strtok(sensorstring_array, ",");              //let's pars the array at each comma
  TMP = strtok(NULL, ",");                            //let's pars the array at each comma
  NUL = strtok(NULL, ",");                            //let's pars the array at each comma (the sensor outputs the word "DEW" in the string, we dont need it)
  DEW = strtok(NULL, ",");                            //let's pars the array at each comma

  //uncomment this section if you want to take the values and convert them into floating point number.
  /*
    HUM_float=atof(HUM);
    TMP_float=atof(TMP);
    DEW_float=atof(DEW);
  */


  // Pumpensteuerung
  if (digitalRead(Niveauschalterminimum) == LOW )              // wenn der Schalterzusand LOW ist ( Schalter geschlossen)
  {
    periodicPump();
  } else digitalWrite(RelaisHochdruckpumpe, HIGH);                            // Neu: SONST würde es hier weiter gehen


  // Steuerung von Heizstab, Umwälzpumpe und Förderpumpe

  // Zustand 1
  if (digitalRead(Niveauschalterminimum) == LOW && digitalRead(Niveauschaltermaximum) == LOW) // wenn der Niveauschalterminimum geschlossen ist und der Niveauschaltermaximum geschlossen ist
  {
    digitalWrite(RelaisHeizstab, LOW);          // Heizstab an
    digitalWrite(RelaisUmwaelzpumpe, LOW);      // Umwälzpumpe an
    digitalWrite(RelaisFoerderpumpe, HIGH);     // Foerderpumpe aus
    Auffuellvorgang = false;                    // Auffuellvorgang deaktiviert
  }

  // Zustand 2
  if (digitalRead(Niveauschalterminimum) == LOW && digitalRead(Niveauschaltermaximum) == HIGH && Auffuellvorgang == false ) // wenn der Niveauschalterminimum geschlossen ist, der Niveauschaltermaximum offen ist und der Auffuellvorgang deaktiviert ist
  {
    digitalWrite(RelaisHeizstab, LOW);          // Heizstab an
    digitalWrite(RelaisUmwaelzpumpe, LOW);      // Umwälzpumpe an
    digitalWrite(RelaisFoerderpumpe, HIGH);     // Foerderpumpe aus
  }

  // Zustand 3
  if (digitalRead(Niveauschalterminimum) == LOW && digitalRead(Niveauschaltermaximum) == HIGH && Auffuellvorgang == true ) // wenn der Niveauschalterminimum geschlossen ist, der Niveauschaltermaximum offen ist und der Auffuellvorgang aktiviert ist
  {
    digitalWrite(RelaisHeizstab, LOW);          // Heizstab an
    digitalWrite(RelaisUmwaelzpumpe, LOW);      // Umwälzpumpe an
    digitalWrite(RelaisFoerderpumpe, LOW);      // Foerderpumpe an
  }

  // Zustand 4
  if (digitalRead(Niveauschalterminimum) == HIGH && digitalRead(Niveauschaltermaximum) == HIGH) // wenn der Niveauschalterminimum offen ist und der Niveauschaltermaximum offen ist
  {
    digitalWrite(RelaisHeizstab, HIGH);         // Heizstab ausmachen
    digitalWrite(RelaisUmwaelzpumpe, HIGH);     // Umwälzpumpe ausmachen
    digitalWrite(RelaisFoerderpumpe, LOW);
    Auffuellvorgang = true;                     // Auffuellvorgang aktivieren
  }

}

void periodicPump()                                                                           //DANN geht es hier weiter
{
  if (digitalRead(RelaisHochdruckpumpe) && (millis() - timestore_Pumpensteuerung > 900000))     // wenn der PumpenPin HIGH (aus) ist und die Zeit abgelaufen // HIER 900000
  {
    digitalWrite(RelaisHochdruckpumpe, LOW);                                                  // Pumpenpin LOW setzen ( an)
    timestore_Pumpensteuerung = millis();                                                     // Zeit merken
  }
  if (!digitalRead(RelaisHochdruckpumpe) && (millis() - timestore_Pumpensteuerung > 15000))   // Wenn PumpenPin  LOW ist ( an) UND Zeit abgelaufen // HIER 15000
  {
    digitalWrite (RelaisHochdruckpumpe, HIGH);                                                // Pumpe aus machen
    timestore_Pumpensteuerung = millis();                                                     // Zeit merken
  }
}

Auch wenn ich nur die periodic_pump und die Schwimmerschalter plus Aktionen (Notabschaltung und Auffüllvorgang) in einen Sketch packe, funktioniert die Intervallbewässerung nicht, die Hochdruckpumpe schaltet also nicht mehr ab.

// Sketch ohne Auffüllvorgang und Notabschaltung // funktioniert nicht einwandfrei, die Hochdruckpumpe schalter nicht ab nach 15 Sekunden! warum???

// Ezo-Hum-Sensor

//This code was written to be easy to understand.
//Modify this code as you see fit.
//This code will output data to the Arduino serial monitor.
//Type commands into the Arduino serial monitor to control the humidity sensor.
//This code was written in the Arduino 1.8.13 IDE
//An Arduino UNO was used to test this code.
//This code was last tested 8/2020


#include <SoftwareSerial.h>                           //we have to include the SoftwareSerial library, or else we can't use it
#define rx 4                                         //define what pin rx is going to be
#define tx 5                                         //define what pin tx is going to be

SoftwareSerial myserial(rx, tx);                      //define how the soft serial port is going to work


String inputstring = "";                              //a string to hold incoming data from the PC
String sensorstring = "";                             //a string to hold the data from the Atlas Scientific product
boolean input_string_complete = false;                //have we recived all the data from the PC
boolean sensor_string_complete = false;               //have we recived all the data from the Atlas Scientific product

// Pumpensteuerung
unsigned long timestore_Pumpensteuerung;               // Zeitmerker für Pumpensteuerung

// LCD- Display
unsigned long timestore_LCD;               // Zeitmerker für LCD Display

// Temperatur Nährlösung
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>
#include <OneWire.h>

LiquidCrystal_I2C lcd(0x27, 20, 4);

#define ONE_WIRE_BUS 3 //Data von Temp.Sensor
OneWire oneWire(ONE_WIRE_BUS );
DallasTemperature sensors(&oneWire);

// Steuerung von Heizstab, Hochdruckpumpe, Umwaelzpumpe und Foerderpumpe
int RelaisHeizstab = 8;
int RelaisHochdruckpumpe = 9;
int RelaisUmwaelzpumpe = 10;
int RelaisFoerderpumpe = 11;

void setup() {

  // Ezo-Hum-Sensor
  Serial.begin(9600);                                 //set baud rate for the hardware serial port_0 to 9600
  myserial.begin(9600);                               //set baud rate for the software serial port to 9600
  inputstring.reserve(10);                            //set aside some bytes for reciving data from the PC
  sensorstring.reserve(30);                           //set aside some bytes for reciving data from Atlas Scientific product

  lcd.init();
  lcd.backlight();
  sensors.begin();

  // Notabschaltung Heizstab, Hochdruckpumpe, Umwaelzpumpe und Foerderpumpe
  pinMode(RelaisHeizstab, OUTPUT);
  pinMode(RelaisHochdruckpumpe, OUTPUT);
  pinMode(RelaisUmwaelzpumpe, OUTPUT);
  pinMode(RelaisFoerderpumpe, OUTPUT);

// Ausgangszustände herstellen
  digitalWrite(RelaisHeizstab, LOW);                  // Der Heizstab ist normalerweise an
  digitalWrite(RelaisHochdruckpumpe, LOW);            // Die Hochdruckpumpe ist normalerweise an
  digitalWrite(RelaisUmwaelzpumpe, LOW);              // Die Umwaelzpumpe ist normalerweise an
  digitalWrite(RelaisFoerderpumpe, HIGH);             // Die Förderpumpe ist normalerweise aus
}

//Ezo-Hum-Sensor
void serialEvent() {                                  //if the hardware serial port_0 recives a char
  inputstring = Serial.readStringUntil(13);           //read the string until we see a <CR>
  input_string_complete = true;                       //set the flag used to tell if we have recived a completed string from the PC
}
void loop() {

  //Ezo-Hum-Sensor
  if (input_string_complete == true) {                //if a string from the PC has been recived in its entirety
    myserial.print(inputstring);                      //send that string to the Atlas Scientific product
    myserial.print('\r');                             //add a <CR> to the end of the string
    inputstring = "";                                 //clear the string
    input_string_complete = false;                    //reset the flag used to tell if we have recived a completed string from the PC
  }

  if (myserial.available() > 0) {                     //if we see that the Atlas Scientific product has sent a character
    char inchar = (char)myserial.read();              //get the char we just recived
    sensorstring += inchar;                           //add the char to the var called sensorstring
    if (inchar == '\r') {                             //if the incoming character is a <CR>
      sensor_string_complete = true;                  //set the flag
    }
  }

  if (sensor_string_complete == true) {               //if a string from the Atlas Scientific product has been recived in its entirety
    if (isdigit(sensorstring[0]) == false) {          //if the first character in the string is a digit
      Serial.println(sensorstring);                   //send that string to the PC's serial monitor
    }
    else                                              //if the first character in the string is NOT a digit
    {
      print_Humidity_data();                          //then call this function
    }
    sensorstring = "";                                //clear the string
    sensor_string_complete = false;                   //reset the flag used to tell if we have recived a completed string from the Atlas Scientific product
  }
}

void print_Humidity_data(void) {                      //this function will pars the string

  char sensorstring_array[30];                        //we make a char array
  char *HUM;                                          //char pointer used in string parsing.
  char *TMP;                                          //char pointer used in string parsing.
  char *NUL;                                          //char pointer used in string parsing (the sensor outputs some text that we don't need).
  char *DEW;                                          //char pointer used in string parsing.

  float HUM_float;                                      //float var used to hold the float value of the humidity.
  float TMP_float;                                      //float var used to hold the float value of the temperatur.
  float DEW_float;                                      //float var used to hold the float value of the dew point.

  sensorstring.toCharArray(sensorstring_array, 30);   //convert the string to a char array
  HUM = strtok(sensorstring_array, ",");              //let's pars the array at each comma
  TMP = strtok(NULL, ",");                            //let's pars the array at each comma
  NUL = strtok(NULL, ",");                            //let's pars the array at each comma (the sensor outputs the word "DEW" in the string, we dont need it)
  DEW = strtok(NULL, ",");                            //let's pars the array at each comma

  Serial.println();                                   //this just makes the output easier to read by adding an extra blank line.

  Serial.print("HUM:");                               //we now print each value we parsed separately.
  Serial.print(HUM);                                //this is the humidity value.

  Serial.print("Air TMP:");                           //we now print each value we parsed separately.
  Serial.print(TMP);                                //this is the air temperatur value.

  Serial.print("DEW:");                               //we now print each value we parsed separately.
  Serial.print(DEW);                                //this is the dew point.
  Serial.println();                                   //this just makes the output easier to read by adding an extra blank line.

  //uncomment this section if you want to take the values and convert them into floating point number.
  /*
    HUM_float=atof(HUM);
    TMP_float=atof(TMP);
    DEW_float=atof(DEW);
  */

  // LCD - Display
  if (millis() - timestore_LCD > 5000 ) // wenn Pausenzeit um wird der Display erneuert
  {
    lcd.setCursor(0, 0);              // Werte auf LCD anzeigen
    lcd.print("Wurzelzone:");
    lcd.setCursor(0, 1);
    lcd. print("T:");
    lcd.print(TMP);
    lcd.print("\337C");
    lcd. print(" Hum:");
    lcd.print(HUM);
    lcd.print("%");
    lcd.setCursor(0, 2);
    lcd.print("NL:");
    lcd.print(sensors.getTempCByIndex(0));
    lcd.print("\337C");
    lcd.print(" Dew:");
    lcd.print(DEW);

    sensors.requestTemperatures();

    lcd.setCursor(0, 3);
    lcd.print("Rasen:     ");
    lcd.print("T:");
    lcd.print(sensors.getTempCByIndex(1));
    lcd.print("\337C");

    timestore_LCD = millis();            // Ausschaltzeit merken
  }

 // Pumpensteuerung
 
    periodicPump();


}

void periodicPump()                                                                           //DANN geht es hier weiter
{
  if (digitalRead(RelaisHochdruckpumpe) && (millis() - timestore_Pumpensteuerung > 900000))     // wenn der PumpenPin HIGH (aus) ist und die Zeit abgelaufen // HIER 900000
  {
    digitalWrite(RelaisHochdruckpumpe, LOW);                                                  // Pumpenpin LOW setzen ( an)
    timestore_Pumpensteuerung = millis();                                                     // Zeit merken
  }
  if (!digitalRead(RelaisHochdruckpumpe) && (millis() - timestore_Pumpensteuerung > 15000))   // Wenn PumpenPin  LOW ist ( an) UND Zeit abgelaufen // HIER 15000
  {
    digitalWrite (RelaisHochdruckpumpe, HIGH);                                                // Pumpe aus machen
    timestore_Pumpensteuerung = millis();                                                     // Zeit merken
  }
}

Hat jemand eine Vermutung wo das Problem liegen könnte oder Vorschläge für mich wie ich den Fehler finden kann?

Herzliche Grüße Leonardo

Hier ist der Schaltplan:

P.S.: Irgendetwas muss ja an der Hardware kaputt gegangen sein wenn es plötzlich nach einen halben Jahr ohne Probleme nicht mehr funktioniert, oder?

Wenn der Fehler immer noch vorhanden ist, solltest du mittels serieller Ausgaben auf den Monitor nachprüfen, an welcher Stelle das Problem entsteht.

Hallo,
überrüfe alle Verbindungen auf Korrision.
Tausche Schritt für Schritt die Hardware aus.

@HotSystems: Kannst Du mir bitte erklären wie Du da genau vorgehen würdest?

@paulpaulson: Ich habe mir gestern die Verbindungen angeschaut und habe keinen Rost entdeckt.

Könnt Ihr mir dafür eine Reihenfolge empfehlen? Kann ein kaputter Sensor, dessen Wert "nur" abgefragt und auf dem LCD Monitor abgebildet wird überhaupt zu so einem Fehler führen? Oder ist nur ein Ereignis, das eine Aktion auslöst wie zum Beispiel die beiden Schwimmerschalter in der Lage zu so einem Fehler zu führen?

Ich würde an bestimmten Stellen im Sketch serielle Ausgaben reinbringen, um zu sehen, an welcher Stelle der Sketch stehen bleibt bzw. nicht mehr funktioniert.
Sowas nennt man debuggen.

Ich habe in meinem ersten Beitrag überhaupt nicht den ersten Sketch gepostet, der anfangs auf dem Arduino hochgeladen war und ein halbes Jahr fehlerfrei lief ehe es dann zu dem oben genannten Fehler kam:

hier ist er:

// Ezo-Hum-Sensor

//This code was written to be easy to understand.
//Modify this code as you see fit.
//This code will output data to the Arduino serial monitor.
//Type commands into the Arduino serial monitor to control the humidity sensor.
//This code was written in the Arduino 1.8.13 IDE
//An Arduino UNO was used to test this code.
//This code was last tested 8/2020


#include <SoftwareSerial.h>                           //we have to include the SoftwareSerial library, or else we can't use it
#define rx 4                                         //define what pin rx is going to be
#define tx 5                                         //define what pin tx is going to be

SoftwareSerial myserial(rx, tx);                      //define how the soft serial port is going to work


String inputstring = "";                              //a string to hold incoming data from the PC
String sensorstring = "";                             //a string to hold the data from the Atlas Scientific product
boolean input_string_complete = false;                //have we recived all the data from the PC
boolean sensor_string_complete = false;               //have we recived all the data from the Atlas Scientific product

// Pumpensteuerung
unsigned long timestore_Pumpensteuerung;               // Zeitmerker für Pumpensteuerung

// LCD- Display
unsigned long timestore_LCD;               // Zeitmerker für LCD Display

// Temperatur Nährlösung
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>
#include <OneWire.h>

LiquidCrystal_I2C lcd(0x27, 20, 4);

#define ONE_WIRE_BUS 3 //Data von Temp.Sensor
OneWire oneWire(ONE_WIRE_BUS );
DallasTemperature sensors(&oneWire);

// Steuerung von Heizstab, Hochdruckpumpe, Umwaelzpumpe und Foerderpumpe
int RelaisHeizstab = 8;
int RelaisHochdruckpumpe = 9;
int RelaisUmwaelzpumpe = 10;
int RelaisFoerderpumpe = 11;

int Niveauschalterminimum = 2;
int Niveauschaltermaximum = 6;
bool Auffuellvorgang = false; // Auffüllvorgang ist nicht aktiviert


void setup() {

  // Ezo-Hum-Sensor
  Serial.begin(9600);                                 //set baud rate for the hardware serial port_0 to 9600
  myserial.begin(9600);                               //set baud rate for the software serial port to 9600
  inputstring.reserve(10);                            //set aside some bytes for reciving data from the PC
  sensorstring.reserve(30);                           //set aside some bytes for reciving data from Atlas Scientific product

  lcd.init();
  lcd.backlight();
  sensors.begin();

  // Notabschaltung Heizstab, Hochdruckpumpe, Umwaelzpumpe und Foerderpumpe
  pinMode(RelaisHeizstab, OUTPUT);
  pinMode(RelaisHochdruckpumpe, OUTPUT);
  pinMode(RelaisUmwaelzpumpe, OUTPUT);
  pinMode(RelaisFoerderpumpe, OUTPUT);
  pinMode(Niveauschalterminimum, INPUT_PULLUP);
  pinMode(Niveauschaltermaximum, INPUT_PULLUP);

  digitalWrite(RelaisHeizstab, LOW);
  digitalWrite(RelaisHochdruckpumpe, LOW);
  digitalWrite(RelaisUmwaelzpumpe, LOW);
  digitalWrite(RelaisFoerderpumpe, HIGH);             // Die Förderpumpe ist normalerweise aus
}

//Ezo-Hum-Sensor
void serialEvent() {                                  //if the hardware serial port_0 recives a char
  inputstring = Serial.readStringUntil(13);           //read the string until we see a <CR>
  input_string_complete = true;                       //set the flag used to tell if we have recived a completed string from the PC
}
void loop() {

  //Ezo-Hum-Sensor
  if (input_string_complete == true) {                //if a string from the PC has been recived in its entirety
    myserial.print(inputstring);                      //send that string to the Atlas Scientific product
    myserial.print('\r');                             //add a <CR> to the end of the string
    inputstring = "";                                 //clear the string
    input_string_complete = false;                    //reset the flag used to tell if we have recived a completed string from the PC
  }

  if (myserial.available() > 0) {                     //if we see that the Atlas Scientific product has sent a character
    char inchar = (char)myserial.read();              //get the char we just recived
    sensorstring += inchar;                           //add the char to the var called sensorstring
    if (inchar == '\r') {                             //if the incoming character is a <CR>
      sensor_string_complete = true;                  //set the flag
    }
  }

  if (sensor_string_complete == true) {               //if a string from the Atlas Scientific product has been recived in its entirety
    if (isdigit(sensorstring[0]) == false) {          //if the first character in the string is a digit
      Serial.println(sensorstring);                   //send that string to the PC's serial monitor
    }
    else                                              //if the first character in the string is NOT a digit
    {
      print_Humidity_data();                          //then call this function
    }
    sensorstring = "";                                //clear the string
    sensor_string_complete = false;                   //reset the flag used to tell if we have recived a completed string from the Atlas Scientific product
  }
}

void print_Humidity_data(void) {                      //this function will pars the string

  char sensorstring_array[30];                        //we make a char array
  char *HUM;                                          //char pointer used in string parsing.
  char *TMP;                                          //char pointer used in string parsing.
  char *NUL;                                          //char pointer used in string parsing (the sensor outputs some text that we don't need).
  char *DEW;                                          //char pointer used in string parsing.

  float HUM_float;                                      //float var used to hold the float value of the humidity.
  float TMP_float;                                      //float var used to hold the float value of the temperatur.
  float DEW_float;                                      //float var used to hold the float value of the dew point.

  sensorstring.toCharArray(sensorstring_array, 30);   //convert the string to a char array
  HUM = strtok(sensorstring_array, ",");              //let's pars the array at each comma
  TMP = strtok(NULL, ",");                            //let's pars the array at each comma
  NUL = strtok(NULL, ",");                            //let's pars the array at each comma (the sensor outputs the word "DEW" in the string, we dont need it)
  DEW = strtok(NULL, ",");                            //let's pars the array at each comma

  Serial.println();                                   //this just makes the output easier to read by adding an extra blank line.

  Serial.print("HUM:");                               //we now print each value we parsed separately.
  Serial.print(HUM);                                //this is the humidity value.

  Serial.print("Air TMP:");                           //we now print each value we parsed separately.
  Serial.print(TMP);                                //this is the air temperatur value.

  Serial.print("DEW:");                               //we now print each value we parsed separately.
  Serial.print(DEW);                                //this is the dew point.
  Serial.println();                                   //this just makes the output easier to read by adding an extra blank line.

  //uncomment this section if you want to take the values and convert them into floating point number.
  /*
    HUM_float=atof(HUM);
    TMP_float=atof(TMP);
    DEW_float=atof(DEW);
  */

  // LCD - Display
  if (millis() - timestore_LCD > 5000 ) // wenn Pausenzeit um wird der Display erneuert
  {
    lcd.setCursor(0, 0);              // Werte auf LCD anzeigen
    lcd.print("Wurzelzone:");
    lcd.setCursor(0, 1);
    lcd. print("T:");
    lcd.print(TMP);
    lcd.print("\337C");
    lcd. print(" Hum:");
    lcd.print(HUM);
    lcd.print("%");
    lcd.setCursor(0, 2);
    lcd.print("NL:");
    lcd.print(sensors.getTempCByIndex(0));
    lcd.print("\337C");
    lcd.print(" Dew:");
    lcd.print(DEW);

    sensors.requestTemperatures();

    lcd.setCursor(0, 3);
    lcd.print("Rasen:     ");
    lcd.print("T:");
    lcd.print(sensors.getTempCByIndex(1));
    lcd.print("\337C");

    timestore_LCD = millis();            // Ausschaltzeit merken
  }

  // Pumpensteuerung
  if (digitalRead(Niveauschalterminimum) == LOW )              // wenn der Schalterzusand LOW ist ( Schalter geschlossen)
  {
    periodicPump();
  } else digitalWrite(RelaisHochdruckpumpe, HIGH);                            // Neu: SONST würde es hier weiter gehen


  // Steuerung von Heizstab, Umwälzpumpe und Förderpumpe

  // Zustand 1
  if (digitalRead(Niveauschalterminimum) == LOW && digitalRead(Niveauschaltermaximum) == LOW) // wenn der Niveauschalterminimum geschlossen ist und der Niveauschaltermaximum geschlossen ist
  {
    digitalWrite(RelaisHeizstab, LOW);          // Heizstab an
    digitalWrite(RelaisUmwaelzpumpe, LOW);      // Umwälzpumpe an
    digitalWrite(RelaisFoerderpumpe, HIGH);     // Foerderpumpe aus
    Auffuellvorgang = false;                    // Auffuellvorgang deaktiviert
  }

  // Zustand 2
  if (digitalRead(Niveauschalterminimum) == LOW && digitalRead(Niveauschaltermaximum) == HIGH && Auffuellvorgang == false ) // wenn der Niveauschalterminimum geschlossen ist, der Niveauschaltermaximum offen ist und der Auffuellvorgang deaktiviert ist
  {
    digitalWrite(RelaisHeizstab, LOW);          // Heizstab an
    digitalWrite(RelaisUmwaelzpumpe, LOW);      // Umwälzpumpe an
    digitalWrite(RelaisFoerderpumpe, HIGH);     // Foerderpumpe aus
  }

  // Zustand 3
  if (digitalRead(Niveauschalterminimum) == LOW && digitalRead(Niveauschaltermaximum) == HIGH && Auffuellvorgang == true ) // wenn der Niveauschalterminimum geschlossen ist, der Niveauschaltermaximum offen ist und der Auffuellvorgang aktiviert ist
  {
    digitalWrite(RelaisHeizstab, LOW);          // Heizstab an
    digitalWrite(RelaisUmwaelzpumpe, LOW);      // Umwälzpumpe an
    digitalWrite(RelaisFoerderpumpe, LOW);      // Foerderpumpe an
  }

  // Zustand 4
  if (digitalRead(Niveauschalterminimum) == HIGH && digitalRead(Niveauschaltermaximum) == HIGH) // wenn der Niveauschalterminimum offen ist und der Niveauschaltermaximum offen ist
  {
    digitalWrite(RelaisHeizstab, HIGH);         // Heizstab ausmachen
    digitalWrite(RelaisUmwaelzpumpe, HIGH);     // Umwälzpumpe ausmachen
    digitalWrite(RelaisFoerderpumpe, LOW);
    Auffuellvorgang = true;                     // Auffuellvorgang aktivieren
  }

}

void periodicPump()                                                                           //DANN geht es hier weiter
{
  if (digitalRead(RelaisHochdruckpumpe) && (millis() - timestore_Pumpensteuerung > 900000))     // wenn der PumpenPin HIGH (aus) ist und die Zeit abgelaufen // HIER 900000
  {
    digitalWrite(RelaisHochdruckpumpe, LOW);                                                  // Pumpenpin LOW setzen ( an)
    timestore_Pumpensteuerung = millis();                                                     // Zeit merken
  }
  if (!digitalRead(RelaisHochdruckpumpe) && (millis() - timestore_Pumpensteuerung > 15000))   // Wenn PumpenPin  LOW ist ( an) UND Zeit abgelaufen // HIER 15000
  {
    digitalWrite (RelaisHochdruckpumpe, HIGH);                                                // Pumpe aus machen
    timestore_Pumpensteuerung = millis();                                                     // Zeit merken
  }
}

@HotSystems: Kannst Du mir das bitte an einer Stelle demonstrieren?:slight_smile:

Hallo
überprüfe ob

sensors.begin();

einen Fehler zurückgibt.

Meinst Du so:

void setup() {

  // Ezo-Hum-Sensor
  Serial.begin(9600);                                 //set baud rate for the hardware serial port_0 to 9600
  myserial.begin(9600);                               //set baud rate for the software serial port to 9600
  inputstring.reserve(10);                            //set aside some bytes for reciving data from the PC
  sensorstring.reserve(30);                           //set aside some bytes for reciving data from Atlas Scientific product

  lcd.init();
  lcd.backlight();
  sensors.begin();
  Serial.println("Sensoren sind in Ordnung");

Wenn jetzt "Sensoren sind in Ordnung" auf dem seriellen Monitor erscheint dann hängt sich der Sketch nicht an dieser Stelle auf?

Nur mal kurz als Hinweis:
Ist es das: "endless summer", Optimierung der Parameter mit Hilfe von Sensoren

Dann frag mal den Mod an, ob er das wieder auf macht und das von hier integriert.

Ich find das (sehr kurze) automatic-close auch nicht schick, aber vielleicht ergibt sich dann aus dem Kontext eine Lösung...

Ja, genau. So kannst du das machen. Auch an mehreren Stellen, dann wird die Info größer.

@my_xy_projekt:

Danke für den Tipp! Kannst Du mir erklären wie ich den Moderator kontaktieren kann? Das ist uwefed, oder?

@HotSystems. Okay danke für die Info. Startet sensors.begin() die Abfrage aller Sensoren? Das würde ja heißen, dass einer der Sensoren nicht antwortet wenn "Sensoren sind in Ordnung" nicht auf dem seriellen Monitor angezeigt würde? Könnte man die Suche nach dem defekten Sensor dann noch gezielter eingrenzen?

Das Auslesen/Abfragen der Sensoren wird an anderer Stelle gestartet.

Z.B. hier:

Jo.

Interessant finde ich, das der "endlessSummer" jetzt bei mir mit dem letzten Eintrag vor 30 Minuten steht...
Warum auch immer.

Wenn man den letzten Eintrag liest:

könnte man davon ausgehen, das Du den selbst wieder aufmachen kannst.

Und ja, ansonsten wäre @uwefed der Ansprechpartner :wink:

Ich weiß mal nicht wie man einen Beitrag aus der Versenkung zurückholt.
Ich habe mal versucht etwas zum abschließenden Post dazuzuschrteiben und so zu sehen ob der Tread wieder offen wird. Hat nicht geklappt aber wie my_xy_projekt bemerkt hat, ist die Modifikationszeit geändert worden.
Ich werde heute Abend mal sehen ob ich es verstehe wie man den Tread wieder freischaltet.
Grüße Uwe

Hab den anderen Trad geöffnet.
War einfacher als ich befürchtete; einfach auf den richtigen Knopf gedrückt. Schwieriger war es den Knopf zu finden....
Grüße Uwe

1 Like

Vielen Dank, fürs Öffnen des Threads! Ich bin gerade unterwegs und kann mich leider erstmal nicht um das Projekt kümmern bzw. das Reparieren des Bordcomputers. Ich melde mich im alten Thread, wenn ich Eure Ratschläge ausprobiert habe um den Fehler zu finden.

Herzliche Grüße Leonardo

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.