//Deklaration der benötigten Projekte
#include <Arduino.h>
//End of Deklaration der benötigten Projekte
//Deklaration der Funktionen
void f_SetupSerial();
void f_Main();
void f_CheckTimer();
void f_CheckSensor();
void f_CheckSensorValue();
void f_Interrupt_Triggered();
void f_ResetAmpel();
void f_setAmpel();
void f_WasserGeben();
void f_WasserStoppen();
int getSensorAnalogValue();
int getSensorDigitalValue();
//End of Deklaration der Funktionen
//Deklaration der Konstanten
String strSetupProjektName = "ESP32 - Feuchtigkeitssensor";
String strSetupProjektVersion = "Version 0.2";
// Modulspezifisch
//Arduino Board
#define GREEN_LED 23 // Pin 37 GPIO23 VSPI MOSI für die grüne LED
#define BLUE_LED 22 // Pin 36 GPIO22 I2CSCL für die blaue LED
#define RED_LED 21 // Pin 33 GPIO21 I2C SDA für die rote LED
#define SENSOR_PIN_A0 34 // Pin 5 GPIO34 ADC6 für den analogen Bodenfeuchtesensor
#define SENSOR_PIN_D0 35 // Pin 6 GPIO35 ADC7 für den digitalen Sensor-Ausgang
#define OUTPUT2RELAIS_IN1 2 // GPIO2 für den Relais Input 1
//End of Deklaration der Konstanten
//Deklaration initiales Setzten der Variabeln
int intSensorAnalogValue = 0; // Variable für den analogen Sensorwert
int intSensorDigitalValue = 0; // Variable für den digitalen Sensorwert
String strFeuchtigkeit = ""; // Trocken / ideal / feucht
String strSerielOutput = ""; // String für die serielle Ausgabe
bool boolSensorInterrupt = false; // Boolean, fuer die Entprellung des SchwellWertAusgang des FeuchtigkeitsSensor
bool boolWasser_geben = false; // globale Variabel um Wasser zu geben
int intFeuchtigkeitOKlow = 1900; // SensortWert unterer Schwelle, ab dem es nicht mehr als zu feucht ist
int intFeuchtigleitOKhigh = 2200; // SensorWert oberer Schwelle, ab dem es dann trocken wird
// Timer für Diverses
unsigned long lngStartMainLoopMillis;
unsigned long lngCurrentMainLoopMillis;
const unsigned long lngMainLoopPeriod = 5000; //Periode für das Aufrufen des MainLoops. the value is a number of milliseconds
bool boolMainLoopPeriodAbgelaufen;
unsigned long lngStartCheckWasserGebenMillis;
unsigned long lngCurrentCheckWasserGebenMillis;
const unsigned long lngCheckWasserGebenPeriod = 60000; // Periode nach welcher geprüft werden soll, ob es Wasser benötigt.
bool boolCheckWasserGebenPeriodAbgelaufen;
unsigned long lngStartLastInterruptMillis;
unsigned long lngCurrentLastInterruptMillis;
const unsigned long lngLastInterruptPeriod = 15000; // Periode wie lange kein weiterer Interrupt zugelassen wird.
bool boolLastInterruptPeriodAbgelaufen;
unsigned long lngStartWasserGebenMillis;
unsigned long lngCurrentWasserGebenMillis;
const unsigned long lngWasserGebenPeriod = 5000; // Periode, wie lange das Relais für die Pumpe oder Ventil angesteurt werden soll
bool boolWasserGebenPeriodeAktiv = false;
//End of Deklaration initiales Setzten der Variabeln
void setup() {
f_SetupSerial();
Serial.println ("Setup Pinout's Board");
pinMode(BLUE_LED, OUTPUT); // Setzt den PIN für die blaue LED als Ausgang.
pinMode(RED_LED, OUTPUT); // Setzt den PIN für die rote LED als Ausgang.
pinMode(GREEN_LED, OUTPUT); // Setzt den PIN für die grüne LED als Ausgang.
pinMode(SENSOR_PIN_A0, INPUT); // Setzt den PIN für die Feuchtigkeitssensor A0 als Eingang.
attachInterrupt(digitalPinToInterrupt(SENSOR_PIN_D0),f_Interrupt_Triggered,RISING);
pinMode(SENSOR_PIN_D0, INPUT); // Setzt den PIN für die Feuchtigkeitssensor D0 als Eingang.
digitalWrite(OUTPUT2RELAIS_IN1, LOW); // Definieren des Ausgangs sogleich auf LOW, dass nach pinMode der Ausgang nicht das Relais schaltet.
pinMode(OUTPUT2RELAIS_IN1, OUTPUT); // Setzt den PIN für das Relais D1 als Ausgang.
Serial.println ("Setup Ampel");
f_ResetAmpel();
f_Main();
Serial.println ("Setup Done");
Serial.println ("Starte MainLoop");
lngStartLastInterruptMillis = millis();
}
// Mainloop mit MainLoopZähler
void loop() {
// Prüfen der Perioden
f_CheckTimer();
if (boolMainLoopPeriodAbgelaufen)
{
f_Main();
lngStartMainLoopMillis = lngCurrentMainLoopMillis; // Reset MainloopTimer
}
if (boolCheckWasserGebenPeriodAbgelaufen or (boolLastInterruptPeriodAbgelaufen and boolSensorInterrupt))
{
if (boolLastInterruptPeriodAbgelaufen and boolSensorInterrupt) // Interrupt nur akzeptieren wenn die Periode abgelaufen ist
{
Serial.println ("Interrupt ausgeloest");
lngStartLastInterruptMillis = lngCurrentLastInterruptMillis; // Reset InterruptTimer
}
if (boolWasser_geben and not boolWasserGebenPeriodeAktiv) // insofern es nötig ist zu Wässer werden die Flags gesetzt
{
Serial.println ("Setze Wasser geben ");
boolWasserGebenPeriodeAktiv = true;
boolCheckWasserGebenPeriodAbgelaufen = false;
}
boolSensorInterrupt = false; // allfälliger Interrupt reseten da eben ein Check statt fand
lngStartCheckWasserGebenMillis = lngCurrentCheckWasserGebenMillis;
}
if (boolWasserGebenPeriodeAktiv)
{
f_WasserGeben();
boolWasser_geben = false;
}
else
{
f_WasserStoppen();
}
}
// Function Main
void f_Main(){
f_CheckSensor();
f_CheckSensorValue();
f_setAmpel();
f_prnSerielOutput();
}
// Function Check Timers und setze entsprechende Flags
void f_CheckTimer(){
// Check Mainloop Timer, um die Sensoren abzufragen.
lngCurrentMainLoopMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started)
if (lngCurrentMainLoopMillis - lngStartMainLoopMillis >= lngMainLoopPeriod) //test whether the period has elapsed
{
boolMainLoopPeriodAbgelaufen = true;
}
else
{
boolMainLoopPeriodAbgelaufen = false;
}
// Check, ob der Timer abgelaufen ist, dass ein Interrupt wieder akzeptiert werden soll
lngCurrentLastInterruptMillis = millis();
if (lngCurrentLastInterruptMillis - lngStartLastInterruptMillis >= lngLastInterruptPeriod) //test whether the period has elapsed
{
boolLastInterruptPeriodAbgelaufen = true;
}
else
{
boolLastInterruptPeriodAbgelaufen = false;
boolSensorInterrupt = false; // Rücksetzen des Interrupt-Flags solange der Timer nicht abgelaufen ist.
}
// Check, ob die SperrDauer fürs erneute Wassser geben abgelaufen ist
lngCurrentCheckWasserGebenMillis = millis();
if (lngCurrentCheckWasserGebenMillis - lngStartCheckWasserGebenMillis >= lngCheckWasserGebenPeriod) //test whether the period has elapsed
{
boolCheckWasserGebenPeriodAbgelaufen = true;
}
else
{
boolCheckWasserGebenPeriodAbgelaufen = false;
}
// Check, ob die Dauer fürs Wasser geben abgelaufen ist
if (boolWasserGebenPeriodeAktiv)
{
if (digitalRead(OUTPUT2RELAIS_IN1) == LOW) // einmaliger Durchlauf
{
Serial.println ("Reset lngStartWasserGebenMillis");
lngStartWasserGebenMillis = millis();
}
lngCurrentWasserGebenMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started)
if ((lngCurrentWasserGebenMillis - lngStartWasserGebenMillis >= lngWasserGebenPeriod)) //test whether the period has elapsed
{
boolWasserGebenPeriodeAktiv = false;
}
else
{
boolWasserGebenPeriodeAktiv = true;
}
}
}
// Function Serielle USB Schnittstelle konfigurieren
void f_SetupSerial() {
Serial.begin(115200); // Begin der seriellen Kommunikation
Serial.println ("*********************************");
Serial.println ("Projekt INFO");
Serial.println ("Projekt Name: " + strSetupProjektName);
Serial.println ("Projekt Vers: " + strSetupProjektVersion);
Serial.println ("*********************************");
}
//Function Prüfe Sensor
void f_CheckSensor(){
intSensorAnalogValue = getSensorAnalogValue();
intSensorDigitalValue = getSensorDigitalValue();
}
//Function Werte des Senors prüfen und entscheiden, ob die Erde "feucht", "i.O" oder "trocken" ist
void f_CheckSensorValue(){
strFeuchtigkeit = "";
if(intSensorAnalogValue >= 0 && intSensorAnalogValue < intFeuchtigkeitOKlow) /* unterer Grenzwert (zu nass) */
{
strFeuchtigkeit = "feucht";
strSerielOutput = "Sensor Wert: " + strFeuchtigkeit + " / ";
boolWasser_geben = false;
}
else if(intSensorAnalogValue >= intFeuchtigkeitOKlow && intSensorAnalogValue <= intFeuchtigleitOKhigh) /* Grenzwert i.O. (nicht zu nass und auch nicht zu trocken) */
{
strFeuchtigkeit = "Wert ok";
strSerielOutput = "Sensor Wert: " + strFeuchtigkeit + " / ";
boolWasser_geben = false;
}
else if(intSensorAnalogValue >= intFeuchtigleitOKhigh) /* oberer Grenzwert (zu trocken) */
{
strFeuchtigkeit = "trocken";
strSerielOutput = "Sensor Wert: " + strFeuchtigkeit + " / ";
boolWasser_geben = true;
}
}
//Liest den analogen Wert des Bodenfeuchtesensors und gibt diesen zurück.
int getSensorAnalogValue(){
return analogRead(SENSOR_PIN_A0);
}
//Liest den digitalen Wert des Bodenfeuchtesensors und gibt diesen zurück.
int getSensorDigitalValue(){
return digitalRead(SENSOR_PIN_D0);
}
//Function Print SerielOutput
void f_prnSerielOutput(){
Serial.print (strSerielOutput);
Serial.print (intSensorAnalogValue);
Serial.print (" D0:");
Serial.print (intSensorDigitalValue);
Serial.print (" / MainLoopPeriode: ");
Serial.print (boolMainLoopPeriodAbgelaufen ? "TRUE" : "FALSE");
Serial.print (" / LastInterruptPeriode: ");
Serial.print (boolLastInterruptPeriodAbgelaufen ? "TRUE" : "FALSE");
Serial.print (" / CheckWasserGebenPeriode: ");
Serial.print (boolCheckWasserGebenPeriodAbgelaufen ? "TRUE" : "FALSE");
Serial.print (" / WasserGebenPeriodeAktiv: ");
Serial.print (boolWasserGebenPeriodeAktiv ? "TRUE" : "FALSE");
Serial.println();
}
// Function wenn Interrupt getriggert wird
// keine weiteren Befehle in dieser Interrupt Routine möglich. Prog stürzt ab
void f_Interrupt_Triggered(){
if (boolSensorInterrupt)
{
// Ignoriere Interrupt auf Grund des Prellens des FeuchtigkeitsSensor Ausgang D0
}
else
{
boolSensorInterrupt = true;
}
}
//Setzte die Farben der Ampel-LED zurück.
void f_ResetAmpel(){
analogWrite(RED_LED, 0);
analogWrite(GREEN_LED, 0);
analogWrite(BLUE_LED, 0);
delay(500);
analogWrite(RED_LED, 255);
analogWrite(GREEN_LED, 0);
analogWrite(BLUE_LED, 0);
delay(500);
analogWrite(RED_LED, 0);
analogWrite(GREEN_LED, 0);
analogWrite(BLUE_LED, 255);
delay(500);
analogWrite(RED_LED, 0);
analogWrite(GREEN_LED, 255);
analogWrite(BLUE_LED, 0);
delay(500);
analogWrite(RED_LED, 0);
analogWrite(GREEN_LED, 0);
analogWrite(BLUE_LED, 0);
delay(500);
}
/* Function f_setAmpel LED's
LED grün = ok
LED blau = feucht
LED rot = trocken
*/
void f_setAmpel(){
if (strFeuchtigkeit == "trocken")
{
analogWrite(RED_LED, 255);
analogWrite(GREEN_LED, 0);
analogWrite(BLUE_LED, 0);
}
else if (strFeuchtigkeit == "Wert ok")
{
analogWrite(RED_LED, 0);
analogWrite(GREEN_LED, 255);
analogWrite(BLUE_LED, 0);
}
else if (strFeuchtigkeit == "feucht")
{
analogWrite(RED_LED, 0);
analogWrite(GREEN_LED, 0);
analogWrite(BLUE_LED, 255);
}
else
{
analogWrite(RED_LED, 255);
analogWrite(GREEN_LED, 255);
analogWrite(BLUE_LED, 255);
}
delay(500);
analogWrite(RED_LED, 0);
analogWrite(GREEN_LED, 0);
analogWrite(BLUE_LED, 0);
}
void f_WasserGeben(){
if (digitalRead(OUTPUT2RELAIS_IN1) == LOW) // nur ausführen wenn der Ausgang noch nicht geschalten wurde
{
Serial.println ("Wasser_geben ausloesen");
digitalWrite(OUTPUT2RELAIS_IN1, HIGH); /* Wasser geben ein*/
analogWrite(RED_LED, 255);
analogWrite(GREEN_LED, 255);
analogWrite(BLUE_LED, 255);
lngStartWasserGebenMillis=millis(); // Timer fuers Wasser geben reseten
}
}
void f_WasserStoppen(){
if (digitalRead(OUTPUT2RELAIS_IN1) == HIGH ) // nur ausführen, wenn der Ausgang noch nicht ausgeschalten wurde
{
Serial.println ("WASSER Stopp");
digitalWrite(OUTPUT2RELAIS_IN1, LOW); /* Wasser geben aus */
analogWrite(RED_LED, 0);
analogWrite(GREEN_LED, 0);
analogWrite(BLUE_LED, 0);
boolWasserGebenPeriodeAktiv = false;
boolWasser_geben = false;
}
}