#include <Arduino.h>
// Setzen der Bibliotheken
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
// Adressierung des LCD
LiquidCrystal_I2C lcd(0x27, 20, 4);
// Belegung der Relais
#define relais_1 10
#define relais_2 9
// Belegung der Taster
#define button_automatic_input 7
#define button_decrease_input 6
#define button_increase_input 5
// Variablen für den Taster des Automatik_Betriebs
bool button_read = false;
bool button_on = false;
bool switch0 = false;
// Belegung der Feuchtigkeitssensoren
#define moisture_sensor1 A1
#define moisture_sensor2 A2
#define moisture_sensor3 A3
// Variablen für die Feuchtigkeitssensoren
int average_moisture_value = 0;
byte average_moisture_value_percent = 0;
// Setzen der Variablen für den SetPoint
byte setpoint = 60;
// Setzen der Timer
unsigned long button_millis = 0;
unsigned long button_decrease_millis = 0;
unsigned long button_increase_millis = 0;
unsigned long relais_millis = 0;
unsigned long serial_millis = 0;
unsigned long lcd_millis = 0;
unsigned long operation_state_millis = 0;
unsigned long relais_state_millis = 0;
unsigned long fault_millis = 0;
// Zeitstempel für den Bewässerungsvorgang
unsigned long watering_time =1500;
unsigned long delay_time = 3000;
// Implementierung der State_Machine
enum current_operation_state {
system_off,
pouring_activ,
pouring_inactive,
timeout_fault,
};
current_operation_state operation_state = system_off;
enum current_relais_state {
switched_off,
relais1_activ,
relais_off_1,
relais2_activ,
relais_off_2,
};
current_relais_state relais_state = switched_off;
// Variable für den Counter
int counter = 0;
int previous_state = system_off;
// Speicheradresse im EEPROM anlegen
int eeprom_address_1 = 0;
// Variablen für den Timeout
int counter_timeout = 0;
int previous_relais_state = switched_off;
// Vorausdeklaration der Abschnitte
void serial_monitor();
void lcd_display();
void toggle_switch();
void update_setpoint();
void measure_moisture();
void manage_operation_states();
void manage_relais_states();
void set_states();
void setup() {
// Setzen der Pins
// Ausgänge
pinMode(relais_1, OUTPUT);
pinMode(relais_2, OUTPUT);
// Eingänge
pinMode(button_automatic_input, INPUT_PULLUP);
pinMode(button_decrease_input, INPUT_PULLUP);
pinMode(button_increase_input, INPUT_PULLUP);
pinMode(moisture_sensor1, INPUT);
pinMode(moisture_sensor2, INPUT);
// Initialisierung des LCD
lcd.init();
lcd.backlight();
// Auslesen des EEPROM
counter = EEPROM.read(eeprom_address_1);
if (counter == 255) {
counter = 0;
}
// Starten des Serial_Monitors
Serial.begin(9600);
}
void loop() {
// Abruf der Funktion für den Serial_Monitor
serial_monitor();
// Abruf der Funktion für das LCD-Display
lcd_display();
// Abruf der Funktion für den Toggle-Switch
toggle_switch();
// Abruf der Funktion zur Änderung des SetPoints
update_setpoint();
// Abruf der Funktion zum Auslesen der Feuchtigkeitssensoren
measure_moisture();
// Abruf der Funktion zur Verwaltung der Operation_States
manage_operation_states();
// Abruf der Funktionen zur Verwaltung der Relais_states
manage_relais_states();
// Abruf der Funktion zum Updaten der States
set_states();
}
//==============================================================//
//=========================FUNCTIONS============================//
//==============================================================//
void serial_monitor() {
// Variablen für diesen Abschnitt
unsigned long serial_timer = millis() - serial_millis;
if (serial_timer > 250) {
Serial.print(" Start-Taster = ");
Serial.println(switch0);
Serial.print(" SetPoint = ");
Serial.print(setpoint);
Serial.print(" Feucht. = ");
Serial.print(average_moisture_value_percent);
Serial.print(" OperationState = ");
Serial.print(operation_state);
Serial.print(" RelaisState = ");
Serial.print(relais_state);
Serial.print(" CT = ");
Serial.print (counter_timeout);
serial_millis = millis();
}
}
//==============================================================//
//=========================FUNCTIONS============================//
//==============================================================//
void lcd_display() {
switch(operation_state) {
case system_off:
lcd.setCursor(0, 0);
lcd.print("Watering stopped ");
break;
case pouring_inactive:
lcd.setCursor(0, 0);
lcd.print("Watering available ");
break;
case pouring_activ:
lcd.setCursor(0, 0);
lcd.print("Watering active ");
break;
case timeout_fault:
lcd.setCursor(0, 0);
lcd.print("Add water ");
break;
}
lcd.setCursor(0, 1);
lcd.print("====================");
if (average_moisture_value_percent < 10) {
lcd.setCursor(12, 2);
lcd.print(" ");
}
lcd.setCursor(0, 2);
lcd.print("Moisture =");
lcd.setCursor(11, 2);
lcd.print(average_moisture_value_percent);
lcd.setCursor(13, 2);
lcd.print("%");
lcd.setCursor(0, 3);
lcd.print("SetPoint =");
lcd.setCursor(11, 3);
lcd.print(setpoint);
lcd.setCursor(13, 3);
lcd.print("%");
lcd.setCursor(16, 3);
lcd.print("C=");
lcd.setCursor(18, 3);
lcd.print(counter);
}
//==============================================================//
//=========================FUNCTIONS============================//
//==============================================================//
void toggle_switch() {
// Variablen für diesen Abschnitt
button_read = digitalRead(button_automatic_input);
unsigned long button_timer = millis() - button_millis;
if (button_read == true) {
button_millis = millis();
fault_millis = millis();
}
if (button_read == false && button_on == false && button_timer > 20) {
button_on = true;
}
if (button_read == true && button_on == true) {
button_on = false;
switch0 = !switch0;
}
}
//==============================================================//
//=========================FUNCTIONS============================//
//==============================================================//
void update_setpoint() {
// Variablen für diesen Abschnitt
bool button_increase = digitalRead(button_increase_input);
bool button_decrease = digitalRead(button_decrease_input);
unsigned long button_increase_timer = millis() - button_increase_millis;
unsigned long button_decrease_timer = millis() - button_decrease_millis;
if (button_increase == false && button_increase_timer > 150) {
setpoint++;
button_increase_millis = millis();
}
if (button_decrease == false && button_decrease_timer > 150) {
setpoint--;
button_decrease_millis = millis();
}
setpoint = max(10, min(setpoint, 99));
}
//==============================================================//
//=========================FUNCTIONS============================//
//==============================================================//
void measure_moisture() {
// Variablen für diesen Abschnitt
int moisture_sensor_value1 = analogRead(moisture_sensor1);
int moisture_sensor_value2 = analogRead(moisture_sensor2);
average_moisture_value = ((moisture_sensor_value1 + moisture_sensor_value2) / 2);
average_moisture_value_percent = map(average_moisture_value, 800, 380, 0, 100);
}
//==============================================================//
//=========================FUNCTIONS============================//
//==============================================================//
void manage_operation_states() {
// Variablen für diesen Abschnitt
unsigned long fault_timer = millis() - fault_millis;
if (switch0 && counter_timeout < 3 && average_moisture_value_percent < (setpoint - 1)) {
operation_state = pouring_activ;
if (previous_state != pouring_activ) {
counter++;
EEPROM.write(eeprom_address_1, counter);
}
}
if (switch0 && average_moisture_value_percent >= (setpoint + 1)) {
operation_state = pouring_inactive;
}
if (operation_state != pouring_activ) {
operation_state = pouring_inactive;
}
if (counter_timeout == 3) {
operation_state = timeout_fault;
}
if (button_read == false && fault_timer > 2000) {
counter = 0;
eeprom_address_1 = 0;
counter_timeout = 0;
switch0 = false;
button_on = false;
}
if (operation_state == pouring_inactive) {
counter_timeout = 0;
}
if (!switch0 && counter_timeout < 3) {
operation_state = system_off;
relais_state = relais_off_1;
}
previous_state = operation_state;
}
//==============================================================//
//=========================FUNCTIONS============================//
//==============================================================//
void manage_relais_states() {
// Varaiblen für diesen Abschnitt
unsigned long relais_state_timer = millis() - relais_state_millis;
if (operation_state == pouring_activ && counter_timeout < 3) {
switch(relais_state) {
case relais1_activ:
if (relais_state_timer > watering_time) {
relais_state = relais_off_1;
relais_state_millis = millis();
}
break;
case relais_off_1:
if (relais_state_timer > delay_time) {
relais_state = relais2_activ;
relais_state_millis = millis();
}
break;
case relais2_activ:
if (relais_state_timer > watering_time) {
relais_state = relais_off_2;
relais_state_millis = millis();
}
break;
case relais_off_2:
if (relais_state_timer > delay_time) {
relais_state = relais1_activ;
relais_state_millis = millis();
if (previous_state != relais_off_2) {
counter_timeout++;
}
}
break;
default:
relais_state = relais1_activ;
relais_state_millis = millis();
}
} else {
relais_state = switched_off;
}
previous_relais_state = relais_state;
}
//==============================================================//
//=========================FUNCTIONS============================//
//==============================================================//
void set_states() {
switch (relais_state) {
case switched_off:
digitalWrite(relais_1, LOW);
digitalWrite(relais_2, LOW);
break;
case relais1_activ:
digitalWrite(relais_1, HIGH);
digitalWrite(relais_2, LOW);
break;
case relais_off_1:
digitalWrite(relais_1, LOW);
digitalWrite(relais_2, LOW);
break;
case relais2_activ:
digitalWrite(relais_1, LOW);
digitalWrite(relais_2, HIGH);
break;
case relais_off_2:
digitalWrite(relais_1, LOW);
digitalWrite(relais_2, LOW);
break;
default:
digitalWrite(relais_1, LOW);
digitalWrite(relais_2, LOW);
}
}
//==============================================================//
//===========================END================================//
//==============================================================//