Da lag ich ja bis auf die Klammern schonmal richtig - und hätte mich totgesucht wenn ich es auf der HW ausprobiert hätte und nix geht
Das "schon auf" oder "schon zu" nicht geprüft wird ist nicht schick, aber es läuft - und macht mir als Anfänger alles übersichtlicher.
Die Feinheiten kommen so nach und nach ins Hirn
Das mit dem Überlauf soll nach ca. 50 Tagen passieren. Dann stimmen halt worst case einmal die 10 Minuten nicht. Das steht tatsächlich ein paar Seiten im Thread weiter oben.
Das Gesamtprogramm falls es wer haben möchte :
// (c)Rolf Kowalsky 02.01.2021 / Kellerfenstersteuerung_V3
// Änderung zu Version Kellefenstersteuerung :
// 1)Einfügung einer Hysterese bei der Entscheidung Fenster öffnen oder Fenster schließen
// durch rechnen mit INTEGER. Dadurch werden sehr kleine Änderungen ignoriert. Das soll
// vermeiden das bei Wettersituationen im Grenzbereich das Fenster mehrmals kurz hintreinander
// auf- und zu fährt.
// 2)Berichtigung, so dass Fenster öffnen per Hand auch funktioniert,
// wenn Aussentemperatur kleiner Innentenperatur
// 3)Funktionsroutinen hinter Hauptprogramm geschoben
// Änderung zu Version Kellefenstersteuerung_V2 :
// 1)Verzögerung um "VerzAuf" ms beim automatischen öffen des Fensters.
// Dadurch soll das Fenster erst geöffnet werden nach Ablauf der Zeit "VerzAuf". Dadurch soll bei
// Wetteränderungen abgewartet werden bis sich Temperatur und Luftfeuchtigkeit stabilisiert haben.
// VerzAuf in Millisekunden.
// Verzögerung eingebaut in Funktion "fenster_oeffnen_auto ()"
//
//*************** HW Pinbelegung Leonardo Micro ***************************
//Pin 2 - I2C SDA
//Pin 3 - I2C SCL
//Pin 4 - OneWire Data (mit PullUp 4k7 an Vcc)
//Pin 5 - ZylAus_O Output für Signal Zylinder ausfahren (Relais oder SSR für Ausfahrmotor [oder Drehrichtung 1]
//Pin 6 - ZylEin_O Output für Signal Zylinder einfahren (Relais oder SSR für Einfahrmotor [oder Drehrichtung 2]
//Pin 7 - ZylAus_I Input für Signal Zylinder ausgefahren (Endschalter Endposition belegt)
//Pin 8 - ZylEin_I Input für Signal Zylinder eingefahren (Endschalter Anfangsposition belegt)
//Pin 9 - Hand_Auf Input für Schalter-Signal Fenster manuell öffnen
//Pin10 - Hand_Zu Input für Schalter-Signal Fenster manuell schliessen
// ************* Libraries **************************
#include <OneWire.h> // für Dallas 18B20 Temp.-Chip
#include <DallasTemperature.h> // für Dallas 18B20 Temp.-Chip
#include "Wire.h" // für SHT31 Temp./RH-Chip
#include "SHT31.h" // für SHT31 Temp./RH-Chip
OneWire oneWire(4); // Data Pin von Sensor am Pin 4 angeschlossen (4)
DallasTemperature sensors(&oneWire); // Library starten
SHT31 sht; // Library starten
// ************* Variablen ******************************
float gradC_I; // Innentemperatur in Grad Celsius
float gradC_A; // Aussentemperatur in Grad C
float humid_RH; // Relative Luftfeuchtigkeit
float tp; // Taupunkt in Grad C
unsigned long altMillis = 0; // Speichert alten millis Wert
unsigned long neuMillis = 0; // Speichert aktuellen millis Wert
const long VerzAuf = 600000; // Verzögerungszeit für Fenster öffen in Automatikbetrieb im ms (600.000 = 10 minuten)
int ZylAus_O = 5; // Output für Signal Zylinder ausfahren
int ZylEin_O = 6; // Output für Signal Zylinder einfahren
int ZylAus_I = 7; // Input für Signal Zylinder ausgefahren (hinter Endschalter Endposition)
int ZylEin_I = 8; // Input für Signal Zylinder eingefahren (hinter Endschalter Anfangsposition)
int Hand_Auf = 9; // Input für Signal Fenster manuell öffnen
int Hand_Zu = 10; // Input für Signal Fenster manuell schliessen
int gradC_Ii = 0; // Integerwert gradC_I
int gradC_Ai = 0; // Integerwert gradC_A
int tpi = 0; // Integerwert für Taupunkt in Grad C
// ************* Setup ******************************
void setup()
{
Serial.begin (9600); // UART Kommunikation initialisieren und auf 9600 Baud
sensors.begin(); // Dallas 18B20 initialisieren
Wire.begin(); // I2C Initialisieren
sht.begin(0x44); // SHT31 initialisieren
Wire.setClock(1000); // I2C Geschwindigkeit auf 1000 setzen
// ************* Pinzuweisungen I/O *****************
pinMode(ZylAus_O, OUTPUT);
pinMode(ZylEin_O, OUTPUT);
pinMode(ZylAus_I, INPUT);
pinMode(ZylEin_I, INPUT);
pinMode(Hand_Auf, INPUT);
pinMode(Hand_Zu, INPUT);
digitalWrite(ZylAus_O,LOW); //Bei Programmstart Ausgänge für Zylindermotoren auf LOW setzen
digitalWrite(ZylEin_O,LOW);
}
// ************* Hauptprogramm ***********************
void loop()
{
werte_einlesen(); //Sensorwerte einlesen
taupunkt_berechnen(); //Routine taupunkt_berechnen anspringen
tpi = (int)tp; // Umwandeln von tp in Integerwert. Verhindert öffnen/schließen bei minimalen Änderungen
gradC_Ii = (int)gradC_I; // Umwandeln von gradC_I in Integerwert. Verhindert öffnen/schließen bei minimalen Änderungen
gradC_Ai = (int)gradC_A; // Umwandeln von gradC_A in Integerwert. Verhindert öffnen/schließen bei minimalen Änderungen
// --- Prüfung Hand- oder Automatikbetrieb ---
if(digitalRead(Hand_Auf) == HIGH)
{ //WENN "Handbetrieb öffnen" dann Routine fenster_oeffnen anspringen
fenster_oeffnen(); //Routine fenster_oeffnen anspringen
Serial.println("Handbetrieb(öffnen)"); //Statusmeldung "Handbetrieb(öffnen)" auf UART ausgeben
}
else if(digitalRead(Hand_Zu) == HIGH)
{ //SONST1, wenn "Handbetrieb schliessen" dann Routine fenster_schliessen anspringen
fenster_schliessen(); //Routine fenster_schliessen anspringen
Serial.println("Handbetrieb(schliessen)"); //Statusmeldung "Handbetrieb(schliessen)" auf UART ausgeben
} //SONST2, wenn kein Handbetrieb ausgewählt, dann Automatikmodus
else if(tpi > gradC_Ii) //Vergleich mit Integerwerten um öffnen/schließen bei kleinsten Aänderungen zu vermeiden
{ //SONST3, wenn Taupunkt über Innentemperatur, dann Routine fenster_schliessen anspringen
Serial.println("Automatik schliessen TP>I");//Statusmeldung "Automatik schliessen TP>I" auf UART ausgeben
fenster_schliessen(); //Routine fenster_schliessen anspringen
}
else if(tpi < gradC_Ii) //Vergleich mit Integerwerten um öffnen/schließen bei kleinsten Aänderungen zu vermeiden
{ //SONST4, wenn Taupunkt unter unter Innentemperatur, dann Routine fenster_oeffnen anspringen
Serial.println("Automatik öffnen TP<I"); //Statusmeldung "Automatik öffnen TP<I" auf UART ausgeben
fenster_oeffnen_auto(); //Routine fenster_oeffnen anspringen
}
}
// ***************FUNKTIONSROUTINEN *****************
//void fenster_oeffnen() // Funktion Fenster öffnen
//void fenster_schliessen() // Funktion Fenster schliessen
//void fenster_oeffnen_auto() // Funktion Fenster öffnen mit vorheriger Prüfung ob Aussentemperatur über Innentemperatur
// und Verzögerung um "VerzAuf" ms
//float werte_einlesen() // Funktion Sensoren ausesen
// ************* Routinen für öffnen und schliessen *****
// ******** öffnen Handbetrieb *******************
void fenster_oeffnen() // Starten der Funktion Fenster öffnen (Zylinder Eingefahren = fenster auf)
{
digitalWrite(ZylAus_O,LOW); // Sicherstellen, dass nie beide Zylindermotoren gleichzeitig laufen
digitalWrite(ZylEin_O, HIGH); // Zylinder ausfahren über Pin ZylEin_O (Pin6)
while(digitalRead(ZylEin_I) == HIGH) // Solange Endschalter nicht belegt, bleibt ZylEin_O = HIGH, sonst ZylEin_O zurücksetzen
{
digitalWrite(ZylEin_O, HIGH);
}
digitalWrite(ZylEin_O, LOW);
}
// ******* öffnen Automatikbetrieb *******
void fenster_oeffnen_auto () // Starten der Funktion Fenster öffnen NUR wenn Aussen wärmer als Innen (Zylinder Eingefahren = fenster auf)
{
if(gradC_Ai < gradC_Ii) // wenn Aussentemperatur kleiner Innentemperatur (Integerwerte) dann Fenster schließen
{
fenster_schliessen(); // Routine fenster_schliessen anspringen
}
else // sonst prüfen ob Zeit "VerzAuf" vergangen ist und dann fenster öffnen
{
neuMillis = millis(); // beim allerersten Programmdurchlauf ist altMillis = 0 wegen Deklaration
if ((neuMillis - altMillis) >= VerzAuf) // vor öffnen prüfen ob Verzögrungszeit "VerzAuf" in ms vergangen ist
{ // wenn das der Fall ist...
fenster_oeffnen(); // Routine fenster_oeffnen anspringen
} // sonst zurück zum Hauptprogramm springen aber vorher noch
altMillis = neuMillis; // altMillis auf neuMillis hochsetzen
}
}
// ******** schließen ***************
void fenster_schliessen()
{
digitalWrite(ZylEin_O,LOW);
digitalWrite(ZylAus_O, HIGH);
while(digitalRead(ZylAus_I) == HIGH)
{
digitalWrite(ZylAus_O, HIGH);
}
digitalWrite(ZylAus_O, LOW);
}
// ************* Ende Routinen für öffnen und schliessen *****
// *************Routine Werte aus Sensoren einlesen***********
float werte_einlesen()
{
// --- Messwerte aus Sensoren einlesen ---
// Anfang Messung Innentemperatur ( gradC ) vom Dallas Temperatursensor
sensors.requestTemperatures(); // Temperaturmessung starten
gradC_I=sensors.getTempCByIndex(0); // gemessene Temperatur der Variablen gradC_I zuweisen
gradC_I=gradC_I-3; // KORREKTURWERT minus 3 Grad Celsius für Innentemperatur,(Meßaufbau mißt zu hohe Innentemperatur weil nicht direkt am Boden gemessen wird)
//Ende Messung Innentemperatur vom Dallas Temperatursensor. Temperatur nun in der Variable gradC_I
// Anfang Messung Aussentemperatur (gradC_A) und Feuchte (humid_RH) vom SGT31 Sensor
sht.read(); //SHT31 Messung starten
gradC_A=sht.getTemperature(), 1; //SHT31 Temperaturwert in Variable gradC_A speichern
humid_RH=sht.getHumidity(), 1; //SHT31 Feuchtewert in Variable humid_RH speichern
// Ende Messung Aussentemperatur (gradC_A) und Feuchte (humid_RH) vom SGT31 Sensor
// --- Messwerte sind eingelesen ---
}
// ************** Routine Taupunktberechnung ****************
float taupunkt_berechnen()
{
// verwendete Variablen :
// float gradC_I; // Innentemperatur in Grad Celsius
// float gradC_A; // Aussentemperatur in Grad C
// float humid_RH; // Aussenfeuchte in %RH
// float tp; // Taupunkt in Grad C
//--- Formel für Taupunktberechnung ---------------------
tp = 243.12*((17.62*gradC_A)/(243.12+gradC_A)+log(humid_RH/100))/((17.62*243.12)/(243.12+gradC_A)-log(humid_RH/100));
// *************Ende Routine Taupunktberechnung***********
// --- Messwerte ausgeben ---
Serial.print("Innentemperatur: ");
Serial.println (gradC_I); // Variable gradC_I auf UART ausgeben
Serial.print("Aussentemperatur: ");
Serial.println(gradC_A); // Variable gradC_A auf UART ausgeben
Serial.print("Aussenfeuchte RH: ");
Serial.println(humid_RH); // Variable humid_RH auf UART ausgeben
Serial.print("Taupunkt: ");
Serial.println(tp);
delay(1000);
// --- Messwerte sind ausgegeben ---
// *************Ende Routine Werte aus Sensoren einlesen***********
}