// Inkludierte Bibliotheken
#include "DHT.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <RTClib.h>
// Adressierung des LCD
LiquidCrystal_I2C lcd(0x27, 20, 4);
// Timer
RTC_DS1307 rtc;
// Belegung der Temperatursensoren
#define DHTPIN1 11
#define DHTPIN2 10
#define DHTPIN3 9
#define DHTTYPE DHT22
DHT dht1(DHTPIN1, DHTTYPE);
DHT dht2(DHTPIN2, DHTTYPE);
DHT dht3(DHTPIN3, DHTTYPE);
// Setzen des SetPoints
float setpoint = 50;
float setpoint_preset = 0;
// Setzen der Holder
int update_lcd_timer = 250;
// Temperaturen für die Gerichte
byte fish_temp = 60;
byte beef_temp = 65;
byte pork_temp = 70;
// Übertemperatur
byte over_temp = 75;
// Belegung des Relais
#define relais1 8
// Belegung der Taster
#define button_auto_input 7
#define button_decrease_input 6
#define button_increase_input 5
#define button_section_input 4
// Variablen für den Toggle-Schalter
bool button_read = false;
bool button_on = false;
//Variable für das Relais
bool switch1 = false;
//Setzen der benötigten Timer
// Timer für die Taster
unsigned long button_millis = 0;
unsigned long button_decrease_millis = 0;
unsigned long button_increase_millis = 0;
unsigned long button_section_millis = 0;
// Timer für den LCD-Screen
unsigned long lcd_millis = 0;
// Vorwärtsdeklaration der Funktionen
void update_lcd(float temperature, float temp_overheat, float temp_environment);
void switch_automatic();
void handle_section();
void handle_relais(float temperature, float temp_overheat);
void execute_relais();
void timer();
// Setzen der State-Machine
// States des Relais
enum current_state_relais {
relais_off,
relais_on,
};
current_state_relais state_relais = relais_off;
// States für den LCD
enum current_state_section {
section_status,
section_fish,
section_beef,
section_pork,
};
current_state_section state_section = section_status;
void setup() {
// Belegung der Outputs
pinMode(relais1, OUTPUT);
// Belegung der Inputs
pinMode(button_auto_input, INPUT_PULLUP);
pinMode(button_decrease_input, INPUT_PULLUP);
pinMode(button_increase_input, INPUT_PULLUP);
pinMode(button_section_input, INPUT_PULLUP);
// Setzen des Outputs des Relais auf HIGH, um Zustand zu setzen
digitalWrite(relais1, HIGH);
// Initialisierung des LCD
lcd.begin(20, 4);
lcd.backlight();
// Begrüßungstext
lcd.setCursor(3, 0);
lcd.print("Matze und Timo");
lcd.setCursor(5, 1);
lcd.print("SmokingKing");
lcd.setCursor(7, 2);
lcd.print("REV 1.3");
delay(500);
// LCD löschen
lcd.clear();
// Initialisierung Serial-Monitor
Serial.begin(9600);
// Initialisierung der Temp.Sensoren
dht1.begin();
dht2.begin();
dht3.begin();
}
void loop() {
// Auslesen der Sensoren
float temperature = dht1.readTemperature();
float temp_overheat = dht2.readTemperature();
float temp_environment = dht3.readTemperature();
// Ausgabe einer Fehlermeldung, wenn Werte unplausibel
if (isnan(temperature)) {
Serial.println("Fehler beim Auslesen der Temperatur des ersten Sensors!");
return;
}
if (isnan(temp_overheat)) {
Serial.println("Fehler beim Auslesen der Temperatur des zweiten Sensors!");
return;
}
// Ausgabe Fehlermeldung, wenn die Uhr nicht funktioniert
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
abort();
}
// Abrufen der Funktionen für den LCD
update_lcd(temperature, temp_overheat, temp_environment);
// Abrufen der Funktionen für den Taster
switch_automatic();
// Abrufen der funktion für die Sektionen
handle_section();
// Abrufen der Funktionen für das Relais
handle_relais(temperature, temp_overheat);
execute_relais();
// Abrufen der Funktionen für den Timer
timer();
}
//--------------------------------------------------------------------------------------//
//--------------------------------------------------------------------------------------//
//--------------------------------------------------------------------------------------//
// Abschnitt zum Updaten des LCD
void update_lcd(float temperature, float temp_overheat, float temp_environment) {
// Variablen für diesen Abschnitt
unsigned long lcd_timer = millis() - lcd_millis;
//
switch (state_section) {
case section_status:
if (lcd_timer > 250 && temp_overheat < over_temp) {
// Ausgabe Temperatur
lcd.setCursor(0, 0);
lcd.print("Temperatur :");
lcd.setCursor(12, 0);
lcd.print(temperature);
lcd.setCursor(18, 0);
lcd.write(223); // Grad-Symbol
lcd.setCursor(19, 0);
lcd.print("C");
// Ausgabe SetPoint
lcd.setCursor(0, 1);
lcd.print("SetPoint :");
lcd.setCursor(12, 1);
lcd.print(setpoint);
lcd.setCursor(18, 1);
lcd.write(223);
lcd.setCursor(19, 1);
lcd.print("C");
// Ausgabe für Heating
lcd.setCursor(0, 2);
lcd.print("Heating :");
// Ausgabe Brenner-Temperatur
lcd.setCursor(0, 3);
lcd.print("BrennerTemp:");
lcd.setCursor(12, 3);
lcd.print(temp_overheat);
lcd.setCursor(18, 3);
lcd.write(223); // Grad-Symbol
lcd.setCursor(19, 3);
lcd.print("C");
lcd_millis = millis();
}
// Ausgabe der Übertemperatur bei Temperatur im Brenner-Raum
else if (temp_overheat > over_temp) {
if (lcd_timer > 500) {
lcd.clear();
}
if (lcd_timer > 1000) {
lcd.setCursor(2, 0);
lcd.print("OVERTEMPERATURE !");
lcd.setCursor(4, 2);
lcd.print("COOLING DOWN");
lcd.setCursor(2, 3);
lcd.print("open the chamber");
lcd_millis = millis();
}
}
// Ausgabe Automatikbetrieb ON/OFF
if (switch1 && temp_overheat < over_temp) {
lcd.setCursor(12, 2);
lcd.print("ON ");
} else if (temp_overheat < over_temp) {
lcd.setCursor(12, 2);
lcd.print("OFF ");
}
break;
// Sektion FISH
case section_fish:
if (lcd_timer > update_lcd_timer && temp_overheat < over_temp) {
// Ausgabe Uhrzeit
lcd.setCursor(0, 1);
lcd.print("Uhrzeit :");
// Ausgabe Sektion
lcd.setCursor(0, 0);
lcd.print(" FISH ");
// Ausgabe Setoint
lcd.setCursor(0, 2);
lcd.print("Temp.Preset:");
lcd.setCursor(12, 2);
lcd.print(setpoint_preset);
lcd.setCursor(18, 2);
lcd.write(223);
lcd.setCursor(19, 2);
lcd.print("C");
// Ausgabe Temperatur
lcd.setCursor(0, 3);
lcd.print("Temperatur :");
lcd.setCursor(12, 3);
lcd.print(temperature);
lcd.setCursor(18, 3);
lcd.write(223);
lcd.setCursor(19, 3);
lcd.print("C");
lcd_millis = millis();
}
else if (temp_overheat > over_temp) {
if (lcd_timer > 500) {
lcd.clear();
}
if (lcd_timer > 1000) {
lcd.setCursor(2, 0);
lcd.print("OVERTEMPERATURE !");
lcd.setCursor(4, 2);
lcd.print("COOLING DOWN");
lcd.setCursor(2, 3);
lcd.print("open the chamber");
lcd_millis = millis();
}
}
break;
// Sektion BEEF
case section_beef:
if (lcd_timer > update_lcd_timer && temp_overheat < over_temp) {
// Ausgabe Uhrzeit
lcd.setCursor(0, 1);
lcd.print("Uhrzeit :");
// Ausgabe Sektion
lcd.setCursor(0, 0);
lcd.print(" BEEF ");
// Ausgabe Setoint
lcd.setCursor(0, 2);
lcd.print("Temp.Preset:");
lcd.setCursor(12, 2);
lcd.print(setpoint_preset);
lcd.setCursor(18, 2);
lcd.write(223);
lcd.setCursor(19, 2);
lcd.print("C");
// Ausgabe Temperatur
lcd.setCursor(0, 3);
lcd.print("Temperatur :");
lcd.setCursor(12, 3);
lcd.print(temperature);
lcd.setCursor(18, 3);
lcd.write(223);
lcd.setCursor(19, 3);
lcd.print("C");
lcd_millis = millis();
}
else if (temp_overheat > over_temp) {
if (lcd_timer > 500) {
lcd.clear();
}
if (lcd_timer > 1000) {
lcd.setCursor(2, 0);
lcd.print("OVERTEMPERATURE !");
lcd.setCursor(4, 2);
lcd.print("COOLING DOWN");
lcd.setCursor(2, 3);
lcd.print("open the chamber");
lcd_millis = millis();
}
}
break;
// Sektion PORK
case section_pork:
if (lcd_timer > update_lcd_timer && temp_overheat < over_temp) {
// Ausgabe Uhrzeit
lcd.setCursor(0, 1);
lcd.print("Uhrzeit :");
// Ausgabe Sektion
lcd.setCursor(0, 0);
lcd.print(" PORK ");
// Ausgabe Setoint
lcd.setCursor(0, 2);
lcd.print("Temp.Preset:");
lcd.setCursor(12, 2);
lcd.print(setpoint_preset);
lcd.setCursor(18, 2);
lcd.write(223);
lcd.setCursor(19, 2);
lcd.print("C");
// Ausgabe Temperatur
lcd.setCursor(0, 3);
lcd.print("Temperatur :");
lcd.setCursor(12, 3);
lcd.print(temperature);
lcd.setCursor(18, 3);
lcd.write(223);
lcd.setCursor(19, 3);
lcd.print("C");
lcd_millis = millis();
}
else if (temp_overheat > over_temp) {
if (lcd_timer > 500) {
lcd.clear();
}
if (lcd_timer > 1000) {
lcd.setCursor(2, 0);
lcd.print("OVERTEMPERATURE !");
lcd.setCursor(4, 2);
lcd.print("COOLING DOWN");
lcd.setCursor(2, 3);
lcd.print("open the chamber");
lcd_millis = millis();
}
}
break;
}
}
//--------------------------------------------------------------------------------------//
//--------------------------------------------------------------------------------------//
//--------------------------------------------------------------------------------------//
// Abschnitt für den Toggle-Schalter
void switch_automatic() {
// Auslesen des Tasters für den Automatikbetrieb
button_read = digitalRead(button_auto_input);
// Variablen für diesen Abschnitt
unsigned long button_timer = millis() - button_millis;
// Festlegung der Logik für den Toggleschalter
if (button_read == true) {
button_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;
switch1 = !switch1;
}
}
//--------------------------------------------------------------------------------------//
//--------------------------------------------------------------------------------------//
//--------------------------------------------------------------------------------------//
// Abschnitt zur Auswahl der Sektionen (Menu) und des SetPoints
void handle_section() {
// Auslesen der Taster
bool button_decrease = digitalRead(button_decrease_input);
bool button_increase = digitalRead(button_increase_input);
bool button_section = digitalRead(button_section_input);
// Variablen für diesen Abschnitt
unsigned long button_decrease_timer = millis() - button_decrease_millis;
unsigned long button_increase_timer = millis() - button_increase_millis;
unsigned long button_section_timer = millis() - button_section_millis;
// Setzen der Logik für die setpoint-Taster
if (button_decrease == false && button_decrease_timer > 100) {
setpoint--;
button_decrease_millis = millis();
}
if (button_increase == false && button_increase_timer > 100) {
setpoint++;
button_increase_millis = millis();
}
// Logik für den Sektions-Schalter
if (button_section == false && button_section_timer > 200) {
state_section = static_cast<current_state_section>((state_section + 1) % 4);
button_section_millis = millis();
lcd.clear();
}
// Setzen der Setpoints für die Presets
switch (state_section) {
case section_fish:
setpoint_preset = fish_temp;
break;
case section_beef:
setpoint_preset = beef_temp;
break;
case section_pork:
setpoint_preset = pork_temp;
break;
}
}
//--------------------------------------------------------------------------------------//
//--------------------------------------------------------------------------------------//
//--------------------------------------------------------------------------------------//
// Abschnitt zur Steuerung des Relais
void handle_relais(float temperature, float temp_overheat) {
if (switch1){
// Steuerung des Relais
switch (state_section) {
case section_status:
if (switch1 && temperature > (setpoint + 1)) {
state_relais = relais_off;
}
if (switch1 && temperature < (setpoint - 1)) {
state_relais = relais_on;
}
if (temp_overheat > over_temp) {
switch1 = false;
}
break;
case section_fish:
if (switch1 && temperature > (setpoint_preset + 1)) {
state_relais = relais_off;
}
if (switch1 && temperature < (setpoint_preset - 1)) {
state_relais = relais_on;
}
if (temp_overheat > over_temp) {
switch1 = false;
}
break;
case section_beef:
if (switch1 && temperature > (setpoint_preset + 1)) {
state_relais = relais_off;
}
if (switch1 && temperature < (setpoint_preset - 1)) {
state_relais = relais_on;
}
if (temp_overheat > over_temp) {
switch1 = false;
}
break;
case section_pork:
if (switch1 && temperature > (setpoint_preset + 1)) {
state_relais = relais_off;
}
if (switch1 && temperature < (setpoint_preset - 1)) {
state_relais = relais_on;
}
if (temp_overheat > over_temp) {
switch1 = false;
}
break;
}
}
else{
state_relais = relais_off;
}
}
//--------------------------------------------------------------------------------------//
//--------------------------------------------------------------------------------------//
//--------------------------------------------------------------------------------------//
// Abschnitt zum Setzten des Status des Relais
void execute_relais() {
switch (state_relais) {
case relais_on:
digitalWrite(relais1, LOW);
break;
case relais_off:
digitalWrite(relais1, HIGH);
break;
}
}
//--------------------------------------------------------------------------------------//
//--------------------------------------------------------------------------------------//
//--------------------------------------------------------------------------------------//
// Abschnitt für den Timer
void timer() {}
//--------------------------------------------------------------------------------------//
//--------------------------------------------------------------------------------------//
//--------------------------------------------------------------------------------------//