/*
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
[] Programm zur Steuerung einer Lüftungsanlage, einem Luftentfeuchter und einer Kondensatpumpe. []
[] Ziel ist es einen Keller zu entfeuchten. Bei überschreiten des MAX innen TP wird die Entf. akt.[]
[] Wenn der Taupunkt der Aussenluft um 5°C kleiner ist wird die Lüftung zur Trocknung verwendet. []
[] Wenn ein Trocknen mit der Aussenluft nicht möglich ist, wird der Luftentfeuchter eingeschaltet.[]
[] Die Kondensatpumpstation läuft kontinuierlich (P ein bei LS-MIN && LS-MAX und umgekehrt) []
[] []
[] Quellen: []
[] https://github.com/MakeMagazinDE/Taupunktluefter/blob/main/Taupunkt_Lueftung.ino []
[] https://forum.arduino.cc/t/hilfe-bei-einer-Implen-pumpensteuerung/509398/7 []
[] https://wokwi.com/arduino/projects/324484140498944595 []
[] https://www.instructables.com/How-to-Use-LCD-HD44780-I2c/ []
[] https://forum.arduino.cc/t/status-eines-output-pins-auslesen/30192 []
[] https://forum.arduino.cc/t/turning-off-i2c-backlight/108963 []
[] https://michaelsarduino.blogspot.com/2015/10/externen-reset-button.html []
[] https://forum.arduino.cc/t/blinkwithoutdelay-die-nachtwachtererklarung/407567 []
[] https://starthardware.org/servo/ []
[] https://github.com/mggates39/MyDelay []
[] []
[] Ersteller: []
[] https://hackaday.io/stefan.schnitzer []
[] [email protected] []
[] []
[] Datum der letzten Revision: []
[] 17.03.2022 []
[] []
[] Revision: []
[] 1.7 []
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
[] DHT 21 Sensoren: []
[] Product Code: HCSENS0026 []
[] Model: AM2301 []
[] Power supply: 3.3-5V DC + Pullup 4k7 bis 10k zwischen +5V und DATA (DHT PIN 6 und 6) []
[] Output signal: digital signal via single-bus []
[] Sensing element: Polymer humidity capacitor []
[] Measuring range: humidity 0-100%RH; temperature -40~80Celsius []
[] Accuracy: humidity +-3%RH(Max +-5%RH); temperature <+-1Celsius []
[] Resolution or sensitivity: humidity 0.1%RH; temperature 0.1Celsius []
[] Repeatability: humidity +-1%RH; temperature +-0.2Celsius []
[] Humidity hysteresis: +-0.3%RH []
[] Long-term Stability: +-0.5%RH/year []
[] Sensing period: Average: 2s, lt. Datenblatt darf nur alle 2s gelesen werden []
[] Dimensions size 59*27*13.5mm []
[] DHTTYPE_1 DHT21 []
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
[] Servo: []
[] Produktmodell: MG90-S []
[] Gewicht: 13,6g []
[] Größe: 22,8 * 12,2 * 28,5 mm []
[] Maximaler Winkel: 180° []
[] Stall Drehmoment: 2kg / cm []
[] Betriebsspannung: 4,8V []
[] Betriebsgeschwindigkeit: 0,11 Sekunden / 60 Grad (4,8V) []
[] Temperaturbereich: 0-55 ℃ []
[] Die Totbandeinstellung: 5 Mikrosekunden []
[] Leitungslänge: 300mm []
[] Steckertyp: JR, FUTABA Allgemein []
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
[] 230V Klappe: []
[] Produktmodell: Belimo LF230 []
[] Stall Drehmoment: 4Nm []
[] Betriebsspannung: 230VAC []
[] Betriebsgeschwindigkeit: 75s AUF / 20s ZU []
[] Temperaturbereich: -30 bis 50°C []
[] AUF durch anlegen von 230VAC - ZU durch Federkraft []
[] Leitung: 1m, 2*0,75mm² []
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
____________________________________________________________________________________________________
____________________________________________________________________________________________________
> Änderungen <
>V1.5: 08.03.2022
-Statt Reset Schaltet der Taster für eine gewisse Zeit aus
-Servo für Zuluftklappe hinzugefügt (inkl Verzögerungszeit)
>V1.6: 16.03.2022
-DHT21 initial zweimal lesen mit >2s Abstand -> dann MIN/MAX initial schreiben
-DHT21 nur mehr mit Taupunkt berechnungs Invervall lesen -nicht jeden Zyklus (>2s lt Datenblatt)
-Bei "Aus auf Zeit" bleibt Displaybel ein (Display Beleuchtung aus Timer Funktion umstrukturiert)
>V1.7: 17.03.2022
-Automatisches Re-Initialisieren der DHT21 Sensoren (PIN LOW bei Fehler dann HIGH)
-230V KLappe hinzugefügt: DO_04 = 30 Relais 5 (Relais ein wenn Lüftung Läuft)
____________________________________________________________________________________________________
____________________________________________________________________________________________________
*/
//----------------------------------------------Bibliotheken--------------------------------------
#include <Wire.h> //One-Wire für DHT-Sensoren
#include <LiquidCrystal_I2C.h> //I²C-LCD 4x20 Zeichen
#include <Servo.h> //Servo für Klappen
#include <DHT.h> //Für Lüftungsklappen Servo
#include <MyDelay.h> //MyDelay für Verzögerungen
//----------------------------------------------Objekte-----------------------------------------
//Verzögerung Lüftung ein nach Zuluft Klappe Auf
void Lueftung_Relais_EIN(); //Dummy Deklaration
MyDelay klappe_nach_auf_t(8000, Lueftung_Relais_EIN); //Verzögerung Objekt
//Verzögerung Klappe Zu nach Lüftung AUS
void Klappe_ZU(); //Dummy Deklaration
MyDelay auslauf_luefter_t(8000, Klappe_ZU); //Verzögerung Objekt
//Servo Objekte für Klappen
Servo klappe_zuluft_srv; //Servo Objekt "klappe_zuluft"
//----------------------------------------------Variablen---------------------------------------
//Messinterval Feuchte
const long interval = 7000; //ms Intervall für aktualisierung Taupunkte
unsigned long previousMillis = 0; //Speicher für Millis bei dem letzte Berechnung ausgeführt wurde
//Bad IO Verzögerung
unsigned long fehler_chxtime = 0; //Speicher für Millis bei dem Fehler Auftritt
unsigned long fehler_timeout = 10000; //ms Verzögerungszeit Live-Fehler-Erkennung
//Intervall für Display Beleuchtung
unsigned long disp_ontime = 0; //Speicher für Millis bei denen Display.bel. eingeschaltet hat
unsigned long disp_off_interv = 20000; //Verzögerungszeit für Display.bel. aus
//Intervall für Ausschalten auf Zeit
unsigned long aus_f_t_start = 0; //Speicher für Millis bei start "Aus auf Zeit"
unsigned long aus_f_t_interv = (60000 * 100); //Zeit f. [60000 * Minuten] "Ausgeschaltet bleiben"
//unsigned long aus_f_t_interv = (60000 * 2); //Zeit f. [60000 * 2 Minuten] "Ausgeschaltet bleiben" Debug
//Intervall für Blink1S
unsigned long b1s_ontime = 0; //Speicher für Millis bei denen Blinktakt eingeschaltet hat
//Sekunden für Anzeige aus bis
unsigned long Sekunden = 0; //Zeit wie lange die Anlage noch aus ist
//Taupunkte Speicher
float Taupunkt_1 = 0.0; //Taupunkt Innen
float Taupunkt_2 = 0.0; //Taupunkt Aussen
//Luftfeuchte und Temperatur
float h1 = 0.0; //Luftfeuchte Innen
float t1 = 0.0; //Temperatur Innen
float h2 = 0.0; //Luftfeuchte Außen
float t2 = 0.0; //Temperatur Außen
//Speicher für MIN-MAX Werte
float h1_max = 0; //Luftfeuchte innen MAX
float h1_min = 0; //Luftfeuchte innen MIN
float t1_max = 0; //Temperatur innen MAX
float t1_min = 0; //Temperatur innen MIN
float h2_max = 0; //Luftfeuchte außen MAX
float h2_min = 0; //Luftfeuchte außen MIN
float t2_max = 0; //Temperatur außen MAX
float t2_min = 0; //Temperatur außen MIN
float TPI_max = 0; //Taupunkt innen MAX
float TPI_min = 0; //Taupunkt innen MIN
float TPA_max = 0; //Taupunkt außen MAX
float TPA_min = 0; //Taupunkt innen MAX
//---------------------------------------------------I/O-(Pin)Belegung--------------------------------------
//DOs Relais RELAIS_EIN=LOW / RELAIS_AUS=LOW
const int DO_00 = 22; //Relais 1 für:230VAC 40W Lüfter Zuluft Keller
const int DO_01 = 24; //Relais 2 für:230VAC 40W Lüfter Abluft Werkstatt
const int DO_02 = 26; //Relais 3 für:230VAC 40W Lüfter Abluft Keller
const int DO_03 = 28; //Relais 4 für:230VAC 300W Luftentfeuchter
const int DO_04 = 30; //Relais 5 für:230VAC 7W Klappenantrieb Zuluft
const int DO_05 = 32; //Relais 6 für:Reserve
const int DO_06 = 34; //Relais 7 für:12VDC 4W Fehler Signalleuchte Rot
const int DO_07 = 36; //Relais 8 für:12VDC 40W Kondensatpumpe
//Status_LED = 13; //Status LED (led builtin)
//DOs direkt 5V
const int DO_08 = 39; //+5V für DHT21-Sensor 1 (innen)
const int DO_09 = 41; //+5V für DHT21-Sensor 2 (aussen)
//PWM
//myservo.attach(9); //Servo Ausgang auf PIN 9
//DIs
const int DI_00 = 23; //LSH Hochschaltpunkt Pumpstation (Sensor - Schwimmer öffner)
const int DI_01 = 25; //LSL Tiefschaltpunkt Pumpstation (Sensor - Schwimmer öffner)
const int DI_02 = 27; //Enable Lüften bzw. Trocknen (Bed.element - Schalter schließer)
const int DI_03 = 29; //Enable Display beleuchtung (Bed.element - Taster Schließer)
const int DI_04 = 31; //Umschalten Live und min Max (Bed.element - Taster Schließer)
const int DI_05 = 33; //Alles aus auf Zeit [x<100min] (Bed.element - Taster Schließer)
const int DI_06 = 35; //Reserve
const int DI_07 = 37; //Reserve
//DHT21
#define DHTPIN_1 7 //Datenleitung für den DHT21-Sensor 1 (Sensor - Luftf. + Temp. innen)
#define DHTPIN_2 6 //Datenleitung für den DHT21-Sensor 2 (Sensor - Luftf. + Temp. außen)
/*I²C LCD 4x20
I2C *SCL Serial ClocK
I2C *SDA Serial Data
*/
//---------------------------------------------------I/O-Belegung--------------------------------------
//globale Variablen und Definitionen
#define RELAIS_EIN LOW //Invertierung der Ausgänge für Relaiskarten Ansteuerung
#define RELAIS_AUS HIGH // -""-
bool keller_feucht = false; //Trocknen ist notwendig
bool enable_lueft_trock; //Trocknen durch Lüften oder Luftentf. aktiviert
bool trocknen; //Trocknen durch Lüftung mit Aussenluft
bool fehler = false; //Fehler-Flag Lüftung Global
bool fehler_ch1 = false; //Fehler-Flag IO_BAD-Sensor 1 (innen)
bool fehler_ch2 = false; //Fehler-Flag IO_BAD-Sensor 2 (außen)
bool dispbelein = false; //Display Beleuchtung ein
bool displive = true; //Zwischen Live und MIN/MAX Werten umschalten
bool b1s = true; //Blinktakt Merker für MIN/MAX Anzeige umschalten
bool Entfeuchter = false; //Luftenentfeucher ein/aus
bool Lueftung = false; //Lüftung ein/aus
bool aus_f_t = false; //Alles aus für eine gewisse Zeit "Lese Eingang"
bool AUS_AUF_ZEIT = false; //Alles aus für eine gewisse Zeit "Funktion Aktiv"
bool lcdbackltimer = false; //Displaybel aus timer aktiv
bool starte_timer_knat = true; //Merker für Timer_knat
bool starte_timer_kzs = true; //Merker für Timer_kzs
#define DHTTYPE_1 DHT21 //DHTTYPE_1 DHT21 Sensor 1 (innen)
#define DHTTYPE_2 DHT21 //DHTTYPE_2 DHT21 Sensor 2 (außen)
#define Korrektur_t_1 0 // °C Korrekturwert Innensensor Temperatur / geändert auf 0 vorher -3
#define Korrektur_t_2 -0.4 // °C Korrekturwert Außensensor Temperatur / geändert auf 0 vorher -4
#define Korrektur_h_1 1.0 // %rH Korrekturwert Innensensor Luftfeuchtigkeit
#define Korrektur_h_2 0 // %rH Korrekturwert Außensensor Luftfeuchtigkeit
#define t_max 75.0 // °C Max Temp für IO-Bad
#define t_min -35.0 // °C Min Temp für IO-Bad
#define h_max 99.0 // %rH Max rH für IO-Bad
#define h_min 5.0 // %rH Min rH für IO-Bad
#define SCHALTmin 5.0 // °C minimaler Taupunktunterschied, bei dem das Relais schaltet
#define HYSTERESE 1.0 // °C Abstand von Ein- und Ausschaltpunkt
#define TEMP1_min 7.4 // °C Minimale Innentemperatur, bei der die Lüftung aktiviert wird / geändert auf 7.5 vorher 10.0
#define TEMP2_min -10.0 // °C Minimale Außentemperatur, bei der die Lüftung aktiviert wird
#define TPI_soll 3.6 // °C Soll Taupunkt Innen
#define TPI_soll_hyst 0.8 // °C Abschalt hysterese für Trocknen (schaltet ab bei 3.6-0.8=2,8 / .. ein bei 4,4°C )
//LCD und DHT Teilnehmer setzen
DHT dht1(DHTPIN_1, DHTTYPE_1); //Der Innensensor wird ab jetzt mit dht1 angesprochen
DHT dht2(DHTPIN_2, DHTTYPE_2); //Der Außensensor wird ab jetzt mit dht2 angesprochen
LiquidCrystal_I2C lcd(0x27, 20, 4); //LCD: I2C-Addresse und Displaygröße setzen //Adresse vorher 0x27 A4+A5 oder 20+21
//---------------------------------------------------Setup-Start-------------------------------------
void setup() {
klappe_zuluft_srv.attach(9); //Servo Ausgang auf PIN 9
pinMode(DO_00, OUTPUT); //Ausgänge initialisieren
pinMode(DO_01, OUTPUT);
pinMode(DO_02, OUTPUT);
pinMode(DO_03, OUTPUT);
pinMode(DO_04, OUTPUT);
pinMode(DO_05, OUTPUT);
pinMode(DO_06, OUTPUT);
pinMode(DO_07, OUTPUT);
pinMode(DO_08, OUTPUT);
pinMode(DO_09, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT); //Pin 13
digitalWrite(DO_00, RELAIS_AUS); //Relais initial ausschalten
digitalWrite(DO_01, RELAIS_AUS);
digitalWrite(DO_02, RELAIS_AUS);
digitalWrite(DO_03, RELAIS_AUS);
digitalWrite(DO_04, RELAIS_AUS);
digitalWrite(DO_05, RELAIS_AUS);
digitalWrite(DO_06, RELAIS_AUS);
digitalWrite(DO_07, RELAIS_AUS);
digitalWrite(DO_08, HIGH); //5V für DHT21 Sensoren ein
digitalWrite(DO_09, HIGH);
pinMode(DI_00, INPUT_PULLUP); //Inputs initialisieren
pinMode(DI_01, INPUT_PULLUP);
pinMode(DI_02, INPUT_PULLUP);
pinMode(DI_03, INPUT_PULLUP);
pinMode(DI_04, INPUT_PULLUP);
pinMode(DI_05, INPUT_PULLUP);
pinMode(DI_06, INPUT);
pinMode(DI_07, INPUT);
lcd.init(); //LCD starten
lcd.backlight(); //LCD Beleuchtung ein
lcd.setCursor(0, 0); //LCD Setze Curser (Zeichen 0, in Zeile 0)
lcd.print(F("PROGV1.7 17.03.2022")); //Schreibe Text mit Revision und Datum d.R.
lcd.setCursor(0, 1); //LCD Setze Curser (Zeichen 0, in Zeile 1)
lcd.print(F("+++++++++++++++++")); //Schreibe Text mit Revision und Datum d.R.
lcd.setCursor(0, 2); //LCD Setze Curser (Zeichen 0, in Zeile 2)
lcd.print(F("stefan.schnitzer")); //Schreibe Text mit Revision und Datum d.R.
lcd.setCursor(0, 3); //LCD Setze Curser (Zeichen 0, in Zeile 3)
lcd.print(F("@hotmail.com")); //Schreibe Text mit Revision und Datum d.R.
delay(500);
byte Grad[8] = {B00111, B00101, B00111, B0000, B00000, B00000, B00000, B00000}; //Sonderzeichen "°" definieren
lcd.createChar(0, Grad);
byte Strich[8] = {B00100, B00100, B00100, B00100, B00100, B00100, B00100, B00100}; //Sonderzeichen "|" definieren
lcd.createChar(1, Strich);
dht1.begin(); //Sensoren starten
dht2.begin();
delay(500);
lcd.setCursor(0, 0);
lcd.print(F("Sensoren starten "));
//Temp und Luftfeuchte initial lesen und in Speicher schreiben
h1 = dht1.readHumidity() + Korrektur_h_1; //Innenluftfeuchtigkeit auslesen und unter „h1“ speichern
t1 = dht1.readTemperature() + Korrektur_t_1; //Innentemperatur auslesen und unter „t1“ speichern
h2 = dht2.readHumidity() + Korrektur_h_2; //Außenluftfeuchtigkeit auslesen und unter „h2“ speichern
t2 = dht2.readTemperature() + Korrektur_t_2; //Außentemperatur auslesen und unter „t2“ speichern
delay(2500); //Nach >2s nochmal lesen
//Temp und Luftfeuchte initial lesen und in Speicher schreiben
h1 = dht1.readHumidity() + Korrektur_h_1; //Innenluftfeuchtigkeit auslesen und unter „h1“ speichern
t1 = dht1.readTemperature() + Korrektur_t_1; //Innentemperatur auslesen und unter „t1“ speichern
h2 = dht2.readHumidity() + Korrektur_h_2; //Außenluftfeuchtigkeit auslesen und unter „h2“ speichern
t2 = dht2.readTemperature() + Korrektur_t_2; //Außentemperatur auslesen und unter „t2“ speichern
//Min/Max Werte inital schreiben
h1_max = h1; //Luftfeuchte innen MAX
h1_min = h1; //Luftfeuchte innen MIN
t1_max = t1; //Temperatur innen MAX
t1_min = t1; //Temperatur innen MIN
h2_max = h2; //Luftfeuchte außen MAX
h2_min = h2; //Luftfeuchte außen MIN
t2_max = t2; //Temperatur außen MAX
t2_min = t2; //Temperatur außen MIN
//Initale Messung anzeigen ---------------------------------------------------------------------------------------------------------
lcd.setCursor(0, 0);
lcd.print(F("I:"));
lcd.print(t1);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write(('C'));
lcd.setCursor(10, 0);
lcd.write((uint8_t)1); // Sonderzeichen |
lcd.print(h1);
lcd.print(F("%"));
//Zeile 1
lcd.setCursor(0, 1);
lcd.print(F("A:"));
lcd.print(t2);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write(('C'));
lcd.setCursor(10, 1);
lcd.write((uint8_t)1); // Sonderzeichen |
lcd.print(h2);
lcd.print(F("%"));
//Zeile 2
lcd.setCursor(0, 2);
lcd.print(F("I "));
lcd.print(Taupunkt_1);
lcd.setCursor(10, 2);
lcd.write((uint8_t)1); // Sonderzeichen |
lcd.setCursor(11, 2);
lcd.print(F("A "));
lcd.print(Taupunkt_2);
//Ende Initale Messung anzeigen ---------------------------------------------------------------------------------------------------------
//Klappe initial Zu
klappe_zuluft_srv.write(0);
//Taupunkte initial berechnen
Taupunkt_1 = taupunkt(t1, h1); //Berechne Taupunkt Innen mit t1 und h1
Taupunkt_2 = taupunkt(t2, h2); //Berechne Taupunkt Außen mit t2 und h2
//Min/Max Werte initial schreiben
TPI_max = Taupunkt_1; //Taupunkt innen MAX
TPI_min = Taupunkt_1; //Taupunkt innen MIN
TPA_max = Taupunkt_2; //Taupunkt außen MAX
TPA_min = Taupunkt_2; //Taupunkt innen MAX
//Dummy definition der Funktionen die über MyDelay aufgerufen werden
klappe_nach_auf_t.start(); //Relais ein nach Klappe offen
auslauf_luefter_t.start(); //Klappe zu nach Lüfter Stillstand
//Fertige Initialisierung Anzeigen
delay(100);
lcd.clear(); //LCD-Inhalt Löschen
lcd.setCursor(0, 0); //LCD-setzte Zeichen 0 Zeile 0
lcd.print(F("Init Ende "));
delay(1000);
lcd.clear();
lcd.noBacklight(); //LCD Beleuchtung aus
}
//---------------------------------------------------Setup-Ende-------------------------------------
/*
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
*/
//---------------------------------------------------LOOP START-------------------------------------
void loop() {
//Lese DIs
enable_lueft_trock = !digitalRead(DI_02); //Enable Lüften bzw. Trocknen (schließer)
dispbelein = !digitalRead(DI_03); //Schalte Display Beleuchtung ein (schließer)
displive = digitalRead(DI_04); //Live Werte oder Min Max (schließer)
aus_f_t = !digitalRead(DI_05); //Alles aus für x [min] Trigger
/* -> Seit Rev. 1.6 Test nicht mehr jeden Zyklus Messen -> lt Datenblatt >2s vorgeschrieben
//Temp und Luftfeuchte lesen und in Speicher schreiben -> Aktualisiere Werte jeden Zyklus
h1 = dht1.readHumidity() + Korrektur_h_1; //Innenluftfeuchtigkeit auslesen und unter „h1“ speichern
t1 = dht1.readTemperature() + Korrektur_t_1; //Innentemperatur auslesen und unter „t1“ speichern
h2 = dht2.readHumidity() + Korrektur_h_2; //Außenluftfeuchtigkeit auslesen und unter „h2“ speichern
t2 = dht2.readTemperature() + Korrektur_t_2; //Außentemperatur auslesen und unter „t2“ speichern
*/
//Messintervall Taupunkte -als "Dämpfung" Taupuinkte nur alle x ms ausführen----------------------
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
//letzten Ausführungszeitpunkt speichern
previousMillis = currentMillis;
//Temp und Luftfeuchte lesen und in Speicher schreiben
h1 = dht1.readHumidity() + Korrektur_h_1; //Innenluftfeuchtigkeit auslesen und unter „h1“ speichern
t1 = dht1.readTemperature() + Korrektur_t_1; //Innentemperatur auslesen und unter „t1“ speichern
h2 = dht2.readHumidity() + Korrektur_h_2; //Außenluftfeuchtigkeit auslesen und unter „h2“ speichern
t2 = dht2.readTemperature() + Korrektur_t_2; //Außentemperatur auslesen und unter „t2“ speichern
//--------------------------------------------------------**** Taupunkte errechnen
Taupunkt_1 = taupunkt(t1, h1); //Berechne Taupunkt Innen mit t1 und h1
Taupunkt_2 = taupunkt(t2, h2); //Berechne Taupunkt Aussen mit t2 und h2
lcd.clear(); //Display leeren
//----------------------------------------------------Ende **** Taupunkte errechnen
}
//----------------------------------------------------------------Zyklische Werteausgabe auf dem I2C-Display
if (displive == true) { //Live Werte wenn Schalter auf "Live"
//Zeile 0
lcd.setCursor(0, 0);
lcd.print(F("I:"));
lcd.print(t1);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write(('C'));
lcd.setCursor(10, 0);
lcd.write((uint8_t)1); // Sonderzeichen |
lcd.print(h1);
lcd.print(F("%"));
//Zeile 1
lcd.setCursor(0, 1);
lcd.print(F("A:"));
lcd.print(t2);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write(('C'));
lcd.setCursor(10, 1);
lcd.write((uint8_t)1); // Sonderzeichen |
lcd.print(h2);
lcd.print(F("%"));
//Zeile 2
lcd.setCursor(0, 2);
lcd.print(F("I "));
lcd.print(Taupunkt_1);
lcd.setCursor(10, 2);
lcd.write((uint8_t)1); // Sonderzeichen |
lcd.setCursor(11, 2);
lcd.print(F("A "));
lcd.print(Taupunkt_2);
}
if (displive == false) { //MIN/MAX Werte wenn Schalter auf "Live"
lcd.backlight(); //Schalte Hintergrundbel Ein
disp_ontime = millis(); //Setzte Timer für Beleuchtung wieder aus
lcdbackltimer = true; //Setze Merker für Timer
if (b1s == true) {
//Zeile 0
lcd.setCursor(0, 0);
lcd.print(F("-I"));
lcd.print(t1_min);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write(('C'));
lcd.setCursor(10, 0);
lcd.write((uint8_t)1); // Sonderzeichen |
lcd.print(h1_min);
lcd.print(F("%"));
//Zeile 1
lcd.setCursor(0, 1);
lcd.print(F("-A"));
lcd.print(t2_min);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write(('C'));
lcd.setCursor(10, 1);
lcd.write((uint8_t)1); // Sonderzeichen |
lcd.print(h2_min);
lcd.print(F("%"));
//Zeile 2
lcd.setCursor(0, 2);
lcd.print(F("-I"));
lcd.print(TPI_min);
lcd.setCursor(10, 2);
lcd.write((uint8_t)1); // Sonderzeichen |
lcd.setCursor(11, 2);
lcd.print(F("-A"));
lcd.print(TPA_min);
}
if (b1s == false) {
//Zeile 0
lcd.setCursor(0, 0);
lcd.print(F("+I"));
lcd.print(t1_max);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write(('C'));
lcd.setCursor(10, 0);
lcd.write((uint8_t)1); // Sonderzeichen |
lcd.print(h1_max);
lcd.print(F("%"));
//Zeile 1
lcd.setCursor(0, 1);
lcd.print(F("+A"));
lcd.print(t2_max);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write(('C'));
lcd.setCursor(10, 1);
lcd.write((uint8_t)1); // Sonderzeichen |
lcd.print(h2_max);
lcd.print(F("%"));
//Zeile 2
lcd.setCursor(0, 2);
lcd.print(F("+I"));
lcd.print(TPI_max);
lcd.setCursor(10, 2);
lcd.write((uint8_t)1); // Sonderzeichen |
lcd.setCursor(11, 2);
lcd.print(F("+A"));
lcd.print(TPA_max);
}
}
//----------------------------------------------------------------Ende Zyklische Werteausgabe auf dem I2C-Display
//Berechne Taupunkt Differenz DeltaTP
float DeltaTP = Taupunkt_1 - Taupunkt_2; //Taupunkt Differenz berechnen
//-----------------------------------------------------------------Logik für "trocknen"
//Keller ist feucht? -> keller_feucht -> true / false
if (Taupunkt_1 > (TPI_soll + TPI_soll_hyst) )keller_feucht = true;
if (Taupunkt_1 < (TPI_soll - TPI_soll_hyst) )keller_feucht = false;
//Trocknen mit Aussenluft ist möglich? -> trocknen -> true / false
if (DeltaTP > (SCHALTmin + HYSTERESE) )trocknen = true;
if (DeltaTP < (SCHALTmin - HYSTERESE) )trocknen = false;
//Untertemperatur Abschaltung? -> trocknen -> false
if (t1 < TEMP1_min )trocknen = false;
if (t2 < TEMP2_min )trocknen = false;
//Wenn Lüften -> Lueftung true, Entfeuchter false
if (enable_lueft_trock == true && trocknen == true && keller_feucht == true && fehler == false && AUS_AUF_ZEIT == false)
{
Lueftung = true; //Lueftung ein
Entfeuchter = false; //Entfeucher aus
}
else
{
Lueftung = false; // Lueftung aus
}
//Wenn Entfeuchten -> Entfeuchter true
if ((keller_feucht == true && Lueftung == false && AUS_AUF_ZEIT == false) || (keller_feucht == true && enable_lueft_trock == false && AUS_AUF_ZEIT == false)) //Wenn notwendig schalte Luftentfeuchter ein
{
Entfeuchter = true; //Entfeuchter ein
}
else
{
Entfeuchter = false; // Entfeuchter aus
}
//-----------------------------------------------------------------Ende Logik für "trocknen"
//----------------------------LCD Logik
if (trocknen == true )
{
lcd.setCursor(19, 1);
lcd.print("<"); //Cursor Anzeigen bei Innen
}
if (trocknen == false )
{
lcd.setCursor(19, 0);
lcd.print("<"); //Cursor Anzeigen bei AUssen
}
//Logik für Status Anzeige am LCD Display
if (Entfeuchter == true ) {
lcd.setCursor(8, 3);
lcd.write((uint8_t)1); // Sonderzeichen |
lcd.setCursor(11, 3);
lcd.print(F("ENTF"));
}
if (Entfeuchter == false ) {
lcd.setCursor(8, 3);
lcd.write((uint8_t)1); // Sonderzeichen |
lcd.setCursor(11, 3);
lcd.print(F(" "));
}
if (Lueftung == true ) {
lcd.setCursor(16, 3);
lcd.print(F("LUEF"));
}
if (Lueftung == false ) {
lcd.setCursor(16, 3);
lcd.print(F(" "));
}
if (keller_feucht == true ) {
lcd.setCursor(15, 3);
lcd.print(F("*"));
}
if (keller_feucht == false ) {
lcd.setCursor(15, 3);
lcd.print(F(" "));
}
if (AUS_AUF_ZEIT == true ) {
lcd.setCursor(9, 3);
//lcd.print(F("X"));
lcd.print(Sekunden);
}
if (AUS_AUF_ZEIT == false ) {
lcd.setCursor(9, 3);
lcd.print(F(" "));
}
pumpen(); //Funktions Aufruf Kondensat abpumpen
//-------------------------------------Funktion Starte DHT21 solange "fehler==false" neu wenn keine plausiblen Werte
//Restart Sensor "Innen" bei IO/BAD
if ((fehler == false) && (fehler_ch1 == false) && (isnan(h1) || isnan(t1) || h1 > h_max || h1 < h_min || t1 < t_min || t1 > t_max )) {
digitalWrite(DO_08, LOW);
delay(500);
digitalWrite(DO_08, HIGH);
}
//Restart Sensor "Außen" bei IO/BAD
if ((fehler == false) && (fehler_ch2 == false) && (isnan(h2) || isnan(t2) || h2 > h_max || h2 < h_min || t2 < t_min || t2 > t_max )) {
digitalWrite(DO_09, LOW);
delay(500);
digitalWrite(DO_09, HIGH);
}
//-------------------------------------Ende Starte DHT21 einmal neu wenn keine plausiblen Werte
//-------------------------------------Funktion Check IO-Bad------------------------------------
//CHKIOBAD -> wenn IO-Bad oder Berechnungsfehler setzte Fehler flag ch1
if ((fehler_ch1 == false) && (isnan(h1) || isnan(t1) || h1 > h_max || h1 < h_min || t1 < t_min || t1 > t_max )) { //IOBAD SENSOR 1
//Serial.println(F("Live Fehler beim Auslesen vom 1. Sensor!"));
//fehler = true;
fehler_ch1 = true;
fehler_chxtime = millis(); //millis bei dem der Fehler auftritt
}
//CHKIOBAD -> wenn kein IO-Bad oder Berechnungsfehler setzte Fehler flag ch1 zurück
if ((fehler_ch1 == true) && ( !isnan(h1) && !isnan(t1) && h1 < h_max && h1 > h_min && t1 > t_min && t1 < t_max )) { //IOBAD SENSOR 1
//Serial.println(F("Fehler ch1 behoben"));
//fehler = true;
fehler_ch1 = false;
}
//CHKIOBAD -> wenn IO-Bad oder Berechnungsfehler setzte Fehler flag ch2
if ((fehler_ch2 == false) && (isnan(h2) || isnan(t2) || h2 > h_max || h2 < h_min || t2 < t_min || t2 > t_max)) { //IOBAD SENSOR 2
//Serial.println(F("Live Fehler beim Auslesen vom 2. Sensor!"));
//fehler = true;
fehler_ch2 = true;
fehler_chxtime = millis(); //millis bei dem der Fehler auftritt
}
//CHKIOBAD -> wenn kein IO-Bad oder Berechnungsfehler setzte Fehler flag ch2 zurück
if ((fehler_ch2 == true) && ( !isnan(h2) && !isnan(t2) && h2 < h_max && h2 > h_min && t2 > t_min && t2 < t_max )) { //IOBAD SENSOR 1
//Serial.println(F("Fehler ch2 behoben"));
//fehler = true;
fehler_ch2 = false;
}
//_____________________________________________________________________________________________________________________________
//
//CHKIOBAD -> wenn Fehler flag ch1 oder ch2 für länger als timout aktiv setze fehler
if ((fehler_ch1 == true || fehler_ch2 == true) && millis() - fehler_chxtime > fehler_timeout) {
fehler = true;
}
//-------------------------------------Ende Funktion Check IO-Bad------------------------------------
//---------------------------------------------------------Logik um Displaybeleuchtung ein und wieder auszuschalten
unsigned long currentMillisDISP = millis();
if ((currentMillisDISP - disp_ontime >= disp_off_interv) && lcdbackltimer == true ) //wenn Hintergrundbeleuchtung länger ein als soll
{
disp_ontime = currentMillisDISP; //ontime Rücksetzten
lcd.noBacklight();
lcdbackltimer = false; //Hintergrundbeleuchtung AUS
}
if (dispbelein == true) //Wenn Taster gedrückt schalte bel ein
{
lcd.backlight(); //Schalte Hintergrundbel Ein
disp_ontime = millis();
lcdbackltimer = true; //Setzte Startzeit Disp EIN
}
//---------------------------------------------------------Ende Logik um Displaybeleuchtung ein und wieder auszuschalten
//---------------------------------------------------------Logik für Ausschalten auf Zeit durch Taster
unsigned long currentMillis_aus_f_t = millis();
if (currentMillis_aus_f_t - aus_f_t_start >= aus_f_t_interv) //Wenn Aus Zeit abgelaufen
{
aus_f_t_start = currentMillis_aus_f_t; //Zeit Rücksetzten
AUS_AUF_ZEIT = false; //Aus auf Zeit Flag=AUS
lcd.noBacklight(); //LCD Backlight aus
}
Sekunden = ((aus_f_t_interv - (currentMillis_aus_f_t - aus_f_t_start)) / 1000 / 60); //Anzeige in [Mintuen] "übrig bis EIN"
if (aus_f_t == true) //Wenn Taster gedrückt...
{
lcd.backlight(); //Schalte Hintergrundbel Ein
//disp_ontime = millis(); //Setzte Startzeit Disp EIN -> V1.6 Display bleibt ein bis "Aus auf Zeit" abgelaufen
aus_f_t_start = millis(); //Aus auf Zeit Zeit=Start
AUS_AUF_ZEIT = true; //Aus auf Zeit Flag=EIN
}
if (AUS_AUF_ZEIT == true && dispbelein == true) //Wenn aus auf Zeit läuft abbruch durch Tast "DISP-EIN"
{
aus_f_t_start = currentMillis_aus_f_t; //Zeit Rücksetzten
AUS_AUF_ZEIT = false; //Aus auf Zeit Flag=AUS
}
//---------------------------------------------------------Ende Logik Logik für Ausschalten auf Zeit durch Taster
//---------------------------------------------------------Logik für MIN_MAX Werte Speichern
// wenn (aktueller_wert < minwert)
// {
// minwert=aktueller_wert;
// }
if (t1 < t1_min ) { //Minimum Innentemperatur
t1_min = t1;
}
if (t1 > t1_max ) { //Maximum Innentemperatur
t1_max = t1;
}
if (h1 < h1_min ) { //Minimum Innenluftfeuchte
h1_min = h1;
}
if (h1 > h1_max ) { //Maximum Innenluftfeuchte
h1_max = h1;
}
if (t2 < t2_min ) { //Minimum Außentemperatur
t2_min = t2;
}
if (t2 > t2_max ) { //Maximum Außentemperatur
t2_max = t2;
}
if (h2 < h2_min ) { //Minimum Außenluftfeuchte
h2_min = h2;
}
if (h2 > h2_max ) { //Maximum Außenluftfeuchte
h2_max = h2;
}
//&& Taupunkt_1 != 0 weil während der berechn. Zyklen der TP auf 0 geht
if ((Taupunkt_1 < TPI_min) && (Taupunkt_1 != 0.00) ) { //Minimum Innentaupunkt
TPI_min = Taupunkt_1;
}
if ((Taupunkt_1 > TPI_max) && (Taupunkt_1 != 0.00) ) { //Maximum Innentaupunkt
TPI_max = Taupunkt_1;
}
if ((Taupunkt_2 < TPA_min) && (Taupunkt_2 != 0.00) ) { //Minimum Außentaupunkt
TPA_min = Taupunkt_2;
}
if ((Taupunkt_2 > TPA_max) && (Taupunkt_2 != 0.00) ) { //Maximum Außentaupunkt
TPA_max = Taupunkt_2;
}
//---------------------------------------------------------Ende Logik für MIN_MAX Werte Speichern
//---------------------------------------------------------Blinktakt Merker für MIN/MAX Anzeige umschalten
if (b1s == false) {
if ((millis() - b1s_ontime) >= 8000 ) {
b1s = true;
digitalWrite(LED_BUILTIN, b1s);
b1s_ontime = millis();
}
} else {
if ((millis() - b1s_ontime) >= 4000) {
b1s = false;
digitalWrite(LED_BUILTIN, b1s);
}
}
//---------------------------------------------------------Ende Blinktakt Merker für MIN/MAX Anzeige umschalten
//IO-Fehler handling -> Wenn Fehler true -> Lueftung aus, Fehler LED Ein, Displaybel. ein
if (fehler == true) {
bool Lueftung = false; //Lueftung ist AUS
digitalWrite(DO_06, RELAIS_EIN); //Fehler LED Relais an
lcd.backlight(); //LCD Beleuchtung ein
}
//------------------ Logik zum Schalten der Ausgänge: Lueftung Entfeuchter ---------
//Lüftung ein: Klappe Auf, Relais ein über Timer
if (Lueftung == true ) //Lüftung EIN
{
digitalWrite(DO_04, RELAIS_EIN); //Klappe Zuluft Zu
klappe_zuluft_srv.write(90); //Klappe Zuluft Auf
if (starte_timer_knat == true) //Einschaltverzögerung Lüfter
{
klappe_nach_auf_t.start();
starte_timer_knat = false;
}
klappe_nach_auf_t.update(); //Ruft Funktion "Relais Lüfter EIN" nach Verzögerung auf
starte_timer_kzs = true; //setze Bit für Timer "Lüftung aus dann Klappe zu"
}
//Lüftung aus: Relais aus, Klappe zu über Timer
if (Lueftung == false ) //Lüftung AUS
{
digitalWrite(DO_00, RELAIS_AUS); //Lüftung Aus
digitalWrite(DO_01, RELAIS_AUS);
digitalWrite(DO_02, RELAIS_AUS);
if (starte_timer_kzs == true) //Ausschakltverzögerung Klappe zu
{
auslauf_luefter_t.start();
starte_timer_kzs = false;
}
auslauf_luefter_t.update(); //Ruft Funktion "Klappe zu" nach Verzögerung auf
starte_timer_knat = true; //setze Bit für Timer "Klappe auf dann Lüftung ein"
}
//Entfeuchter
if (Entfeuchter == true)
{
digitalWrite(DO_03, RELAIS_EIN); //Relais Entfeuchter EIN
}
else
{
digitalWrite(DO_03, RELAIS_AUS); //Relais Entfeuchter AUS
}
//------------------ Ende Logik zum Schalten der Ausgänge: Lueftung Entfeuchter ---------
//dispbelein = false; //Rücksetzen dispbelein
delay(200); //Mindestzykluszeit 200ms
}//----------------------------------------------------------LOOP ENDE------------------------------------------------------------------------
//---------------------------------------------Funktion zur Taupunkt-Berechnung--------------------------------------------------------------
float taupunkt(float t, float r) {
float a, b;
if (t >= 0) {
a = 7.5;
b = 237.3;
} else if (t < 0) {
a = 7.6;
b = 240.7;
}
// Sättigungsdampfdruck in hPa
float sdd = 6.1078 * pow(10, (a * t) / (b + t));
// Dampfdruck in hPa
float dd = sdd * (r / 100);
// v-Parameter
float v = log10(dd / 6.1078);
// Taupunkttemperatur (°C)
float tt = (b * v) / (a - v);
return { tt };
}
//---------------------------------------------Ende Funktion zur Taupunkt-Berechnung----------------------------------
//---------------------------------------------Funktion Kondensat Auspumpen--------------------------------------------------------------
void pumpen() //definiere Funktion Pumpen
{
bool NIVEAU_HOCH = digitalRead(DI_00); // INPUT Schwimmer Oben
bool NIVEAU_NIEDR = digitalRead(DI_01); // INPUT Schwimmer Unten
static byte StatePump = 0; // Status der Statemachine Pumpen, Lokale Variable, static - Arduino-Referenz
static long timeout = 60000; // ms Lokale Variable <----- Max. mögliche Pumpzeit
static long StartZeit = 0;
switch (StatePump) {
case 0:
lcd.setCursor(0, 3);
lcd.print(F("NL P-AUS")); // Init: Voll? Wenn ja Pumpe EIN und springe nach 1
if (NIVEAU_HOCH && NIVEAU_NIEDR) { // wenn oberer Pegel erreicht
digitalWrite(DO_07, RELAIS_EIN); // Pumpe ein
StartZeit = millis(); // Zeit merken
StatePump = 1; lcd.setCursor(0, 3);
lcd.backlight();
lcd.print(F("NH P-EIN"));
// nächster State: 1
}
break; // break
case 1:
lcd.backlight();
lcd.setCursor(0, 3);
lcd.print(F("NH P-EIN")); // Pumpen: Pumpe ist EIN, warte auf Niveau_Niedrig LOW
if (!NIVEAU_HOCH && !NIVEAU_NIEDR) { // wenn unterer Pegel erreicht
digitalWrite(DO_07, RELAIS_AUS); // Pumpe aus
StatePump = 0;
lcd.setCursor(0, 3);
lcd.print(F("NL P-AUS"));
if (AUS_AUF_ZEIT == false) { // Wenn "aus auf Zeit" nicht aktiv ist soll dispbel wieder ausgeschl. w.
lcd.noBacklight();
}
// nächster State: Init
}
if (millis() - StartZeit > timeout) { // Wenn Timeout, setze Fehler case
digitalWrite(DO_07, RELAIS_AUS); // Pumpe aus
digitalWrite(DO_06, RELAIS_EIN); // Fehler LED an
StatePump = 2; // nächster Status: Fehler
}
break; // break
case 2:
lcd.backlight(); // LCD Beleuchtung ein
lcd.setCursor(0, 3);
lcd.print(F("!! P-AUS")); // in Fehler gehen
}
}// end switch
//---------------------------------------------Ende Funktion Kondensat Auspumpen--------------------------------------------------------------
//---------------------------------------------Funktion Verzögerungen------------------------------------------------------------------------
void Lueftung_Relais_EIN() //Wird durch Timer aufgerufen "Einschaltverzögerung"
{
digitalWrite(DO_00, RELAIS_EIN); //Lüftung Ein
digitalWrite(DO_01, RELAIS_EIN);
digitalWrite(DO_02, RELAIS_EIN);
lcd.setCursor(16, 3); //Debug
lcd.print(F("nEIN")); //Debug
}
void Klappe_ZU() //Wird durch Timer aufgerufen "Schließverzögerung"
{
digitalWrite(DO_04, RELAIS_AUS); //Klappe Zuluft Zu
klappe_zuluft_srv.write(0); //Klappe Zuluft Zu
lcd.setCursor(16, 3); //Debug
lcd.print(F("kLZU")); //Debug
}
//---------------------------------------------Funktion Verzögerungen------------------------------------------------------------------------
//Ende sketch