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