Repository: MakeMagazinDE/Taupunktluefter
Branch: main
Commit: 1eb66246c64c
Files: 7
Total size: 30.2 KB
Directory structure:
gitextract_hoxqgct8/
├── Lochraster/
│ └── Lochraster.md
├── README.md
├── Taupunkt_Lueftung/
│ └── Taupunkt_Lueftung.ino
├── Taupunkt_Lueftung.ino
└── Taupunkt_Lueftung_Datenlogging_Version_2.13/
├── SD.ino
├── Taupunkt_Lueftung_Datenlogging_Version_2.13.ino
└── Zeit.ino
================================================
FILE CONTENTS
================================================
================================================
FILE: Lochraster/Lochraster.md
================================================
# Lochraster-Version des Taupunktlüfters
**von Patrick alias _resipat265_ im [heise-Forum](https://www.heise.de/forum/Make/Heft-Projekte/Artikelforum-Heft-1-2022/Re-Taupunkt-Lueftungssystem-Bastelfrage/posting-41215886/show/)**
Hier ein Bild vom Ergebnis von oben:

Zu den Nummern, welche die Anschlüsse durchnummerieren:
1 = Relais-Anschluss
2 = VCC/GND Zuleitung von 5V Netzteil
3 = Modusschalter
4 = Displayanschluss
5 = Reset-Taster. Hier habe ich einen Pin zuviel gelötet…
6 = DHT22 außen
7 = DHT22 innen
Hier ein Bild von unten:

Die drei [PDFs](./PDF) sind aus Fritzing exportiert, mit Gesamtschaltplan, Draufsicht und Sicht von unten. **Achtung**: Die Sicht von unten muss natürlich gespiegelt werden.
================================================
FILE: README.md
================================================

Maker Media GmbH
***
# Taupunktlüfter
**Lüften ist die beste und billigste Maßnahme gegen feuchte Keller – jedenfalls, wenn man es richtig macht und sich nicht von außen zusätzliche Nässe ins Gewölbe holt. Bei unserem Projekt behält ein Arduino Nano die aktuellen Taupunkte drinnen und draußen rund um die Uhr im Auge und legt durch gezieltes Lüften den Keller trocken.**

Hier gibt es den Arduino-Code zum Projekt des Taupunktlüfters sowohl in der Fassung ohne Datenlogger (Code im Ordner _Taupunkt_Lueftung_), wie in Make 1/22 beschrieben, als auch in der Fassung mit Datenlogger (Code im Ordner _Taupunkt_Lueftung_Datenlogging_Version_2.13_), die in Make 2/22 beschrieben wird. Diese Version zeigt auch der erweiterte Schaltplan:

Der im Schaltplan gezeigte _Modusschalter_ ist ein Schalter mit drei Schaltstellungen: links, Mitte, rechts. In der Mittelstellung sind alle Pole frei, bei rechts wird der mittlere Pol nach rechts verbunden und bei links der mittlere Pol nach links. Beschaltet wird dann beispielsweise so: linker Kontakt des Schalters auf GND (linke Stellung ist dann für **aus**), rechter Kontakt auf VCC (5V, rechte Stellung ist dann für **an**) und Mittelkontakt auf Arduino-IO-Pin 6 (Verbindung zum Relais, Mittelstellung ist dann für **Automatik**).
Die wichtigsten Fragen rund um den Taupunktlüfter beantwortet eine **[FAQ](https://heise.de/-6526328)**. Die vollständigen Artikel zum Projekt gibt es in der **[Make-Ausgabe 1/22 ab Seite 22](https://www.heise.de/select/make/2022/1/2135511212557842576)** und in der **[Make-Ausgabe 2/22 ab Seite 82](https://www.heise.de/select/make/2022/2/2204711461516715363)** zu lesen.
Dank Patrick alias _resipat265_ aus dem heise-Forum gibt es jetzt auch eine Vorlage für den Nachbau auf **[Lochraster-Platine](./Lochraster/Lochraster.md)**. Vielen Dank dafür!
================================================
FILE: Taupunkt_Lueftung/Taupunkt_Lueftung.ino
================================================
// Dieser Code benötigt zwingend die folgenden Libraries:
#include "DHT.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <avr/wdt.h>
#define RELAIPIN 6 // Anschluss des Lüfter-Relais
#define DHTPIN_1 5 // Datenleitung für den DHT-Sensor 1 (innen)
#define DHTPIN_2 4 // Datenleitung für den DHT-Sensor 2 (außen)
#define RELAIS_EIN LOW
#define RELAIS_AUS HIGH
bool rel;
#define DHTTYPE_1 DHT22 // DHT 22
#define DHTTYPE_2 DHT22 // DHT 22
// ******* Korrekturwerte der einzelnen Sensorwerte *******
#define Korrektur_t_1 -3 // Korrekturwert Innensensor Temperatur
#define Korrektur_t_2 -4 // Korrekturwert Außensensor Temperatur
#define Korrektur_h_1 0 // Korrekturwert Innensensor Luftfeuchtigkeit
#define Korrektur_h_2 0 // Korrekturwert Außensensor Luftfeuchtigkeit
//***********************************************************
#define SCHALTmin 5.0 // minimaler Taupunktunterschied, bei dem das Relais schaltet
#define HYSTERESE 1.0 // Abstand von Ein- und Ausschaltpunkt
#define TEMP1_min 10.0 // Minimale Innentemperatur, bei der die Lüftung aktiviert wird
#define TEMP2_min -10.0 // Minimale Außentemperatur, bei der die Lüftung aktiviert wird
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
bool fehler = true;
void setup() {
wdt_enable(WDTO_8S); // Watchdog timer auf 8 Sekunden stellen
pinMode(RELAIPIN, OUTPUT); // Relaispin als Output definieren
digitalWrite(RELAIPIN, RELAIS_AUS); // Relais ausschalten
Serial.begin(9600); // Serielle Ausgabe, falls noch kein LCD angeschlossen ist
Serial.println(F("Teste Sensoren.."));
lcd.init();
lcd.backlight();
lcd.setCursor(2,0);
lcd.print(F("Teste Sensoren.."));
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 senkrechter Strich definieren
lcd.createChar(1, Strich);
dht1.begin(); // Sensoren starten
dht2.begin();
}
void loop() {
float h1 = dht1.readHumidity()+Korrektur_h_1; // Innenluftfeuchtigkeit auslesen und unter „h1“ speichern
float t1 = dht1.readTemperature()+ Korrektur_t_1; // Innentemperatur auslesen und unter „t1“ speichern
float h2 = dht2.readHumidity()+Korrektur_h_2; // Außenluftfeuchtigkeit auslesen und unter „h2“ speichern
float t2 = dht2.readTemperature()+ Korrektur_t_2; // Außentemperatur auslesen und unter „t2“ speichern
if (fehler == true) // Prüfen, ob gültige Werte von den Sensoren kommen
{
fehler = false;
if (isnan(h1) || isnan(t1) || h1 > 100 || h1 < 1 || t1 < -40 || t1 > 80 ) {
Serial.println(F("Fehler beim Auslesen vom 1. Sensor!"));
lcd.setCursor(0,1);
lcd.print(F("Fehler Sensor 1"));
fehler = true;
}else {
lcd.setCursor(0,1);
lcd.print(F("Sensor 1 in Ordnung"));
}
delay(2000); // Zeit um das Display zu lesen
if (isnan(h2) || isnan(t2) || h2 > 100 || h2 < 1 || t2 < -40 || t2 > 80) {
Serial.println(F("Fehler beim Auslesen vom 2. Sensor!"));
lcd.setCursor(0,2);
lcd.print(F("Fehler Sensor 2"));
fehler = true;
} else {
lcd.setCursor(0,2);
lcd.print(F("Sensor 2 in Ordnung"));
}
delay(2000); // Zeit um das Display zu lesen
}
if (isnan(h1) || isnan(t1) || isnan(h2) || isnan(t2)) fehler = true;
if (fehler == true) {
digitalWrite(RELAIPIN, RELAIS_AUS); // Relais ausschalten
lcd.setCursor(0,3);
lcd.print(F("CPU Neustart....."));
while (1); // Endlosschleife um das Display zu lesen und die CPU durch den Watchdog neu zu starten
}
wdt_reset(); // Watchdog zurücksetzen
//**** Taupunkte errechnen********
float Taupunkt_1 = taupunkt(t1, h1);
float Taupunkt_2 = taupunkt(t2, h2);
// Werteausgabe auf Serial Monitor
Serial.print(F("Sensor-1: " ));
Serial.print(F("Luftfeuchtigkeit: "));
Serial.print(h1);
Serial.print(F("% Temperatur: "));
Serial.print(t1);
Serial.print(F("°C "));
Serial.print(F(" Taupunkt: "));
Serial.print(Taupunkt_1);
Serial.println(F("°C "));
Serial.print("Sensor-2: " );
Serial.print(F("Luftfeuchtigkeit: "));
Serial.print(h2);
Serial.print(F("% Temperatur: "));
Serial.print(t2);
Serial.print(F("°C "));
Serial.print(F(" Taupunkt: "));
Serial.print(Taupunkt_2);
Serial.println(F("°C "));
Serial.println();
// Werteausgabe auf dem I2C-Display
lcd.clear();
lcd.setCursor(0,0);
lcd.print(F("S1: "));
lcd.print(t1);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write(('C'));
lcd.write((uint8_t)1); // Sonderzeichen |
lcd.print(h1);
lcd.print(F(" %"));
lcd.setCursor(0,1);
lcd.print(F("S2: "));
lcd.print(t2);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write(('C'));
lcd.write((uint8_t)1); // Sonderzeichen |
lcd.print(h2);
lcd.print(F(" %"));
lcd.setCursor(0,2);
lcd.print(F("Taupunkt 1: "));
lcd.print(Taupunkt_1);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write(('C'));
lcd.setCursor(0,3);
lcd.print(F("Taupunkt 2: "));
lcd.print(Taupunkt_2);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write(('C'));
delay(6000); // Zeit um das Display zu lesen
wdt_reset(); // Watchdog zurücksetzen
lcd.clear();
lcd.setCursor(0,0);
float DeltaTP = Taupunkt_1 - Taupunkt_2;
if (DeltaTP > (SCHALTmin + HYSTERESE))rel = true;
if (DeltaTP < (SCHALTmin))rel = false;
if (t1 < TEMP1_min )rel = false;
if (t2 < TEMP2_min )rel = false;
if (rel == true)
{
digitalWrite(RELAIPIN, RELAIS_EIN); // Relais einschalten
lcd.print(F("Lueftung AN"));
} else {
digitalWrite(RELAIPIN, RELAIS_AUS); // Relais ausschalten
lcd.print(F("Lueftung AUS"));
}
lcd.setCursor(0,1);
lcd.print("Delta TP: ");
lcd.print(DeltaTP);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write('C');
delay(4000); // Wartezeit zwischen zwei Messungen
wdt_reset(); // Watchdog zurücksetzen
}
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 };
}
void software_Reset() // Startet das Programm neu, nicht aber die Sensoren oder das LCD
{
asm volatile (" jmp 0");
}
================================================
FILE: Taupunkt_Lueftung.ino
================================================
// Dieser Code benötigt zwingend die folgenden Libraries:
#include "DHT.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <avr/wdt.h>
#define RELAIPIN 6 // Anschluss des Lüfter-Relais
#define DHTPIN_1 5 // Datenleitung für den DHT-Sensor 1 (innen)
#define DHTPIN_2 4 // Datenleitung für den DHT-Sensor 2 (außen)
#define RELAIS_EIN LOW
#define RELAIS_AUS HIGH
bool rel;
#define DHTTYPE_1 DHT22 // DHT 22
#define DHTTYPE_2 DHT22 // DHT 22
// ******* Korrekturwerte der einzelnen Sensorwerte *******
#define Korrektur_t_1 -3 // Korrekturwert Innensensor Temperatur
#define Korrektur_t_2 -4 // Korrekturwert Außensensor Temperatur
#define Korrektur_h_1 0 // Korrekturwert Innensensor Luftfeuchtigkeit
#define Korrektur_h_2 0 // Korrekturwert Außensensor Luftfeuchtigkeit
//***********************************************************
#define SCHALTmin 5.0 // minimaler Taupunktunterschied, bei dem das Relais schaltet
#define HYSTERESE 1.0 // Abstand von Ein- und Ausschaltpunkt
#define TEMP1_min 10.0 // Minimale Innentemperatur, bei der die Lüftung aktiviert wird
#define TEMP2_min -10.0 // Minimale Außentemperatur, bei der die Lüftung aktiviert wird
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
bool fehler = true;
void setup() {
wdt_enable(WDTO_8S); // Watchdog timer auf 8 Sekunden stellen
pinMode(RELAIPIN, OUTPUT); // Relaispin als Output definieren
digitalWrite(RELAIPIN, RELAIS_AUS); // Relais ausschalten
Serial.begin(9600); // Serielle Ausgabe, falls noch kein LCD angeschlossen ist
Serial.println(F("Teste Sensoren.."));
lcd.init();
lcd.backlight();
lcd.setCursor(2,0);
lcd.print(F("Teste Sensoren.."));
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 senkrechter Strich definieren
lcd.createChar(1, Strich);
dht1.begin(); // Sensoren starten
dht2.begin();
}
void loop() {
float h1 = dht1.readHumidity()+Korrektur_h_1; // Innenluftfeuchtigkeit auslesen und unter „h1“ speichern
float t1 = dht1.readTemperature()+ Korrektur_t_1; // Innentemperatur auslesen und unter „t1“ speichern
float h2 = dht2.readHumidity()+Korrektur_h_2; // Außenluftfeuchtigkeit auslesen und unter „h2“ speichern
float t2 = dht2.readTemperature()+ Korrektur_t_2; // Außentemperatur auslesen und unter „t2“ speichern
if (fehler == true) // Prüfen, ob gültige Werte von den Sensoren kommen
{
fehler = false;
if (isnan(h1) || isnan(t1) || h1 > 100 || h1 < 1 || t1 < -40 || t1 > 80 ) {
Serial.println(F("Fehler beim Auslesen vom 1. Sensor!"));
lcd.setCursor(0,1);
lcd.print(F("Fehler Sensor 1"));
fehler = true;
}else {
lcd.setCursor(0,1);
lcd.print(F("Sensor 1 in Ordnung"));
}
delay(2000); // Zeit um das Display zu lesen
if (isnan(h2) || isnan(t2) || h2 > 100 || h2 < 1 || t2 < -40 || t2 > 80) {
Serial.println(F("Fehler beim Auslesen vom 2. Sensor!"));
lcd.setCursor(0,2);
lcd.print(F("Fehler Sensor 2"));
fehler = true;
} else {
lcd.setCursor(0,2);
lcd.print(F("Sensor 2 in Ordnung"));
}
delay(2000); // Zeit um das Display zu lesen
}
if (isnan(h1) || isnan(t1) || isnan(h2) || isnan(t2)) fehler = true;
if (fehler == true) {
digitalWrite(RELAIPIN, RELAIS_AUS); // Relais ausschalten
lcd.setCursor(0,3);
lcd.print(F("CPU Neustart....."));
while (1); // Endlosschleife um das Display zu lesen und die CPU durch den Watchdog neu zu starten
}
wdt_reset(); // Watchdog zurücksetzen
//**** Taupunkte errechnen********
float Taupunkt_1 = taupunkt(t1, h1);
float Taupunkt_2 = taupunkt(t2, h2);
// Werteausgabe auf Serial Monitor
Serial.print(F("Sensor-1: " ));
Serial.print(F("Luftfeuchtigkeit: "));
Serial.print(h1);
Serial.print(F("% Temperatur: "));
Serial.print(t1);
Serial.print(F("°C "));
Serial.print(F(" Taupunkt: "));
Serial.print(Taupunkt_1);
Serial.println(F("°C "));
Serial.print("Sensor-2: " );
Serial.print(F("Luftfeuchtigkeit: "));
Serial.print(h2);
Serial.print(F("% Temperatur: "));
Serial.print(t2);
Serial.print(F("°C "));
Serial.print(F(" Taupunkt: "));
Serial.print(Taupunkt_2);
Serial.println(F("°C "));
Serial.println();
// Werteausgabe auf dem I2C-Display
lcd.clear();
lcd.setCursor(0,0);
lcd.print(F("S1: "));
lcd.print(t1);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write(('C'));
lcd.write((uint8_t)1); // Sonderzeichen |
lcd.print(h1);
lcd.print(F(" %"));
lcd.setCursor(0,1);
lcd.print(F("S2: "));
lcd.print(t2);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write(('C'));
lcd.write((uint8_t)1); // Sonderzeichen |
lcd.print(h2);
lcd.print(F(" %"));
lcd.setCursor(0,2);
lcd.print(F("Taupunkt 1: "));
lcd.print(Taupunkt_1);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write(('C'));
lcd.setCursor(0,3);
lcd.print(F("Taupunkt 2: "));
lcd.print(Taupunkt_2);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write(('C'));
delay(6000); // Zeit um das Display zu lesen
wdt_reset(); // Watchdog zurücksetzen
lcd.clear();
lcd.setCursor(0,0);
float DeltaTP = Taupunkt_1 - Taupunkt_2;
if (DeltaTP > (SCHALTmin + HYSTERESE))rel = true;
if (DeltaTP < (SCHALTmin))rel = false;
if (t1 < TEMP1_min )rel = false;
if (t2 < TEMP2_min )rel = false;
if (rel == true)
{
digitalWrite(RELAIPIN, RELAIS_EIN); // Relais einschalten
lcd.print(F("Lueftung AN"));
} else {
digitalWrite(RELAIPIN, RELAIS_AUS); // Relais ausschalten
lcd.print(F("Lueftung AUS"));
}
lcd.setCursor(0,1);
lcd.print("Delta TP: ");
lcd.print(DeltaTP);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write('C');
delay(4000); // Wartezeit zwischen zwei Messungen
wdt_reset(); // Watchdog zurücksetzen
}
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 };
}
void software_Reset() // Startet das Programm neu, nicht aber die Sensoren oder das LCD
{
asm volatile (" jmp 0");
}
================================================
FILE: Taupunkt_Lueftung_Datenlogging_Version_2.13/SD.ino
================================================
//////////////////////////////////////////////////////////////////////////////
// Das Taupunkt-Lüftungssystem
// mit Datenlogging
//
// Routinen zur Speicherung auf einer SD-Karte
//
// veröffentlicht in der MAKE 2/2022
//
// Ulrich Schmerold
// 3/2022
//////////////////////////////////////////////////////////////////////////////
File logFile; // Variable für die csv-Datei
#define CS_PIN 10 // An diesem Pin ist die CS-Leitung angeschlossen
unsigned long TimeDaten = 0; // zur Berechnung, wann wieder gespeichert wird
void test_SD(){
if (logging == true)
{
// --------- SD-Karte suchen -------------------
lcd.setCursor(0,0);
lcd.print(F("Suche SD Karte.."));
lcd.setCursor(2,1);
if (!SD.begin(CS_PIN)){
lcd.print(F("SD nicht gefunden!"));
logging = false;
} else {
lcd.print(F("SD gefunden"));
if (not SD.exists(logFileName) )
{
logFile = SD.open(logFileName, FILE_WRITE);
logFile.println(Headerzeile); // Header schreiben
logFile.close();
}
}
delay(3000); // Zeit um das Display zu lesen
wdt_reset(); // Watchdog zurücksetzen
}
}
void save_to_SD()
{
unsigned long t;
t = millis() / 60000;
if ( TimeDaten == 0 ) TimeDaten = t;
// ------------------------- Sensorenwerte abspeichern ----------------------
if (((TimeDaten + LogInterval) <= t) or ( Tageswechsel ))
{
TimeDaten = t;
Tageswechsel=false;
test_SD();
wdt_reset(); // Watchdog zurücksetzen
lcd.clear();
lcd.print(F("Speichere Datensatz"));
make_time_stamp();
File logFile = SD.open(logFileName, FILE_WRITE); // Oeffne Datei
// Serial.print( stamp); Serial.print( ';' + LogData ); Serial.println(Luefterzeit);
logFile.print (stamp);
logFile.println( ';' + LogData );
logFile.close();
delay(4000);
}
}
================================================
FILE: Taupunkt_Lueftung_Datenlogging_Version_2.13/Taupunkt_Lueftung_Datenlogging_Version_2.13.ino
================================================
//////////////////////////////////////////////////////////////////////////////
// Das Taupunkt-Lüftungssystem
// mit Datenlogging
//
// veröffentlicht in der MAKE 1/2022 und 2/2022
//
// Ulrich Schmerold
// 3/2022
//////////////////////////////////////////////////////////////////////////////
#define Software_version "Version: 2.13"
// Dieser Code benötig zwingend die folgenden Libraries:
#include "DHT.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <avr/wdt.h>
#include <DS1307RTC.h>
#include <SD.h>
#include <SPI.h>
tmElements_t tm;
#define RELAIPIN 6 // Anschluss des LüfterRelais
#define DHTPIN_1 5 // Datenleitung für den DHT Sensor 1 (innen)
#define DHTPIN_2 4 // Datenleitung für den DHT Sensor 2 (außen)
#define RELAIS_EIN LOW
#define RELAIS_AUS HIGH
bool rel;
bool fehler = true;
#define DHTTYPE_1 DHT22 // DHT 22
#define DHTTYPE_2 DHT22 // DHT 22
// *************************** Korrekturwerte der einzelnen Sensorwerten. ***************
#define Korrektur_t_1 -3 // Korrekturwert Innensensor Temperatur
#define Korrektur_t_2 -4 // Korrekturwert Außensensor Temperatur
#define Korrektur_h_1 0 // Korrekturwert Innensensor Luftfeuchtigkeit
#define Korrektur_h_2 0 // Korrekturwert Außensensor Luftfeuchtigkeit
//******************************************************************************************
#define SCHALTmin 5.0 // minimaler Taupuntunterschied, bei dem das Relais schaltet
#define HYSTERESE 1.0 // Abstand von Ein- und Ausschaltpunkt
#define TEMP1_min 10.0 // Minimale Innentemperatur, bei der die Lüftung aktiviert wird
#define TEMP2_min -10.0 // Minimale Außentemperatur, bei der die Lüftung aktiviert wird
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 Display I2C Addresse und Displaygröße setzen
//++++++++++++++++++++++++++++++++ Variablen für das Datenlogging ***************************************
#define Headerzeile F("Datum|Zeit;Temperatur_S1;Feuchte_H1;Taupunkt_1;Temperatur_S2;Feuchte_H2;Taupunkt_2;Luefter_Ein/Aus;Laufzeit_Luefter;")
#define logFileName F("Luefter1.csv") // Name der Datei zum Abspeichern der Daten (Dateinamen-Format: 8.3)!!!!
#define LogInterval 10 // Wie oft werden die Messwerte aufgezeichnet ( 5 = alle 5 Minuten)
bool logging = true; // Sollen die Daten überhaupt protokolliert werden?
String LogData = "" ; // Variable zum Zusammensetzen des Logging-Strings.
char stamp[17]; // Variable für den Zeitstempel.
unsigned int LuefterStart = 0; // Wann wurde der Lüfter eingeschaltet?
unsigned int LuefterLaufzeit = 0; // Wie lange lief der Lüfter?
char StrLuefterzeit[6]; // Lüfterlaufzeit als String zur weiteren Verwendung.
uint8_t Today = 0; // Das heutige Datum (nur Tag), zur Speicherung bei Tageswechsel.
bool Tageswechsel=false;
//********************************************************************************************************
void setup() {
wdt_enable(WDTO_8S); // Watchdog timer auf 8 Sekunden stellen
pinMode(RELAIPIN, OUTPUT); // Relaispin als Output definieren
digitalWrite(RELAIPIN, RELAIS_AUS); // Relais ausschalten
lcd.init();
lcd.backlight();
lcd.clear();
wdt_reset(); // Watchdog zurücksetzen
//--------------------- Logging ------------------------------------------------------------------------------------
if (logging == true)
{
lcd.setCursor(0,1);
lcd.print(Software_version); // Welche Softwareversion läuft gerade
RTC_start(); // RTC-Modul testen. Wenn Fehler, dann kein Logging
delay (4000); // Zeit um das Display zu lesen
lcd.clear();
wdt_reset(); // Watchdog zurücksetzen
test_SD(); // SD-Karte suchen. Wenn nicht gefunden, dann kein Logging ausführen
Today = tm.Day ;
//------------------------------------------------ Neustart aufzeichnen -------------------------------------
if (logging == true) // kann sich ja geändert haben wenn Fehler bei RTC oder SD
{
make_time_stamp();
File logFile = SD.open(logFileName, FILE_WRITE);
logFile.print(stamp);
logFile.println(F(": Neustart")); // Damit festgehalten wird, wie oft die Steuerung neu gestartet ist
logFile.close();
}
} //---------------------------------------------------------------------------------------------------------------------
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 senkrechter Strich definieren
lcd.createChar(1, Strich);
dht1.begin(); // Sensoren starten
dht2.begin();
}
void loop() {
RTC.read(tm);
float h1 = dht1.readHumidity()+Korrektur_h_1; // Innenluftfeuchtigkeit auslesen und unter „h1“ speichern
float t1 = dht1.readTemperature()+ Korrektur_t_1; // Innentemperatur auslesen und unter „t1“ speichern
float h2 = dht2.readHumidity()+Korrektur_h_2; // Außenluftfeuchtigkeit auslesen und unter „h2“ speichern
float t2 = dht2.readTemperature()+ Korrektur_t_2; // Außentemperatur auslesen und unter „t2“ speichern
if (fehler == true) // Prüfen, ob gültige Werte von den Sensoren kommen
{
lcd.clear();
lcd.setCursor(2,0);
lcd.print(F("Teste Sensoren.."));
fehler = false;
if (isnan(h1) || isnan(t1) || h1 > 100 || h1 < 1 || t1 < -40 || t1 > 80 ) {
// Serial.println(F("Fehler beim Auslesen vom 1. Sensor!"));
lcd.setCursor(0,1);
lcd.print(F("Fehler Sensor 1"));
fehler = true;
}else {
lcd.setCursor(0,1);
lcd.print(F("Sensor 1 in Ordnung"));
}
delay(2000); // Zeit um das Display zu lesen
if (isnan(h2) || isnan(t2) || h2 > 100 || h2 < 1 || t2 < -40 || t2 > 80) {
// Serial.println(F("Fehler beim Auslesen vom 2. Sensor!"));
lcd.setCursor(0,2);
lcd.print(F("Fehler Sensor 2"));
fehler = true;
} else {
lcd.setCursor(0,2);
lcd.print(F("Sensor 2 in Ordnung"));
}
delay(2000); // Zeit um das Display zu lesen
}
if (isnan(h1) || isnan(t1) || isnan(h2) || isnan(t2)) fehler = true;
if (fehler == true) {
digitalWrite(RELAIPIN, RELAIS_AUS); // Relais ausschalten
lcd.setCursor(0,3);
lcd.print(F("CPU Neustart....."));
while (1); // Endlosschleife um das Display zu lesen und die CPU durch den Watchdog neu zu starten
}
wdt_reset(); // Watchdog zurücksetzen
//**** Taupunkte errechnen********
float Taupunkt_1 = taupunkt(t1, h1);
float Taupunkt_2 = taupunkt(t2, h2);
// Werteausgabe auf dem I2C-Display
lcd.clear();
lcd.setCursor(0,0);
lcd.print(F("S1: "));
lcd.print(t1);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write(('C'));
lcd.write((uint8_t)1); // Sonderzeichen |
lcd.print(h1);
lcd.print(F(" %"));
lcd.setCursor(0,1);
lcd.print(F("S2: "));
lcd.print(t2);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write(('C'));
lcd.write((uint8_t)1); // Sonderzeichen |
lcd.print(h2);
lcd.print(F(" %"));
lcd.setCursor(0,2);
lcd.print(F("Taupunkt 1: "));
lcd.print(Taupunkt_1);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write(('C'));
lcd.setCursor(0,3);
lcd.print(F("Taupunkt 2: "));
lcd.print(Taupunkt_2);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write(('C'));
delay(5000); // Zeit um das Display zu lesen
wdt_reset(); // Watchdog zurücksetzen
lcd.clear();
lcd.setCursor(0,0);
float DeltaTP = Taupunkt_1 - Taupunkt_2;
if (DeltaTP > (SCHALTmin + HYSTERESE))rel = true;
if (DeltaTP < (SCHALTmin))rel = false;
if (t1 < TEMP1_min )rel = false;
if (t2 < TEMP2_min )rel = false;
if (rel == true)
{
digitalWrite(RELAIPIN, RELAIS_EIN); // Relais einschalten
lcd.print(F("Lueftung AN"));
if (LuefterStart <=0 && logging == true){ LuefterStart = tm.Hour*60 + tm.Minute;}
} else {
digitalWrite(RELAIPIN, RELAIS_AUS); // Relais ausschalten
lcd.print(F("Lueftung AUS"));
if( LuefterStart > 0 && logging == true){
LuefterLaufzeit += (tm.Hour*60 + tm.Minute - LuefterStart);
LuefterStart = 0;
}
}
lcd.setCursor(0,1);
lcd.print(F("Delta TP: "));
lcd.print(DeltaTP);
lcd.write((uint8_t)0); // Sonderzeichen °C
lcd.write('C');
make_time_stamp();
lcd.setCursor(0,3);
lcd.print(stamp);
lcd.setCursor(0,2);
if (logging == true)lcd.print(F("Logging AN")); else lcd.print(F("Logging AUS"));
delay(4000); // Wartezeit zwischen zwei Messungen
wdt_reset(); // Watchdog zurücksetzen
//--------------------------------------------logging-----------------------------------------------------
if (logging == true)
{
if ( Today != tm.Day) // Tageswechsel ==> Lüfterzeit abspeichern
{
Tageswechsel = true; // ==> Sofort speichern (siehe SD.ino) ==> Nicht erst wenn LogIntervall abgelaufen ist
if (LuefterStart > 0 ) LuefterLaufzeit += (1440 - LuefterStart); // ==>Lüfter läuft gerade
snprintf(StrLuefterzeit,sizeof(StrLuefterzeit),"%d;",LuefterLaufzeit);
Today = tm.Day;
LuefterLaufzeit = 0;
} else {
strcpy( StrLuefterzeit , "0;"); // Kein Tageswechsel, nur Platzhalter abspeichern
}
char buff[4];
LogData="";
dtostrf(t1, 2, 1, buff); LogData += buff ; LogData += ';';
dtostrf(h1, 2, 1, buff); LogData += buff ; LogData += ';';
dtostrf(Taupunkt_1, 2, 1, buff); LogData += buff ; LogData += ';';
dtostrf(t2, 2, 1, buff); LogData += buff ; LogData += ';';
dtostrf(h2, 2, 1, buff); LogData += buff;LogData += ';';
dtostrf(Taupunkt_2, 2, 1, buff); LogData += buff;LogData += ';';
if (rel == true) LogData +="1;"; else LogData += "0;";
LogData += StrLuefterzeit;
save_to_SD(); // Daten auf die SD Karte speichern
}
}
//--------------------------------------------------------------------------------------------------------
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 };
}
void software_Reset() // Startet das Programm neu, nicht aber die Sensoren oder das LCD
{
asm volatile (" jmp 0");
}
================================================
FILE: Taupunkt_Lueftung_Datenlogging_Version_2.13/Zeit.ino
================================================
//////////////////////////////////////////////////////////////////////////////
// Das Taupunkt-Lüftungssystem
// mit Datenlogging
//
// Routinen zur Erzeugung eines Zeitstempels
//
// veröffentlicht in der MAKE 2/2022
//
// Ulrich Schmerold
// 3/2022
//////////////////////////////////////////////////////////////////////////////
void make_time_stamp ()
{
RTC.read(tm);
snprintf(stamp,sizeof(stamp),"%02d.%02d.%d %02d:%02d",tm.Day,tm.Month,tmYearToCalendar(tm.Year),tm.Hour,tm.Minute);
}
bool RTC_start()
{
if (logging == true)
{
if (RTC.read(tm))
{
make_time_stamp ();
lcd.setCursor(2,0);
lcd.print(stamp);
} else {
if (RTC.chipPresent()) {
lcd.clear();
lcd.print(F("RTC hat keine Zeit"));
delay(2000);
} else {
lcd.clear();
lcd.print(F("Kein Signal vom RTC"));
delay(2000);
}
logging = false;
return(false);
}
}
}
gitextract_hoxqgct8/
├── Lochraster/
│ └── Lochraster.md
├── README.md
├── Taupunkt_Lueftung/
│ └── Taupunkt_Lueftung.ino
├── Taupunkt_Lueftung.ino
└── Taupunkt_Lueftung_Datenlogging_Version_2.13/
├── SD.ino
├── Taupunkt_Lueftung_Datenlogging_Version_2.13.ino
└── Zeit.ino
Condensed preview — 7 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (34K chars).
[
{
"path": "Lochraster/Lochraster.md",
"chars": 828,
"preview": "# Lochraster-Version des Taupunktlüfters\r\n\r\n**von Patrick alias _resipat265_ im [heise-Forum](https://www.heise.de/forum"
},
{
"path": "README.md",
"chars": 2007,
"preview": "\n\nMaker Media GmbH\n\n***\n\n# Taupunktlüfter\n\n**Lüften ist die "
},
{
"path": "Taupunkt_Lueftung/Taupunkt_Lueftung.ino",
"chars": 7034,
"preview": "// Dieser Code benötigt zwingend die folgenden Libraries:\r\n#include \"DHT.h\"\r\n#include <Wire.h> \r\n#include <LiquidCrystal"
},
{
"path": "Taupunkt_Lueftung.ino",
"chars": 7034,
"preview": "// Dieser Code benötigt zwingend die folgenden Libraries:\r\n#include \"DHT.h\"\r\n#include <Wire.h> \r\n#include <LiquidCrystal"
},
{
"path": "Taupunkt_Lueftung_Datenlogging_Version_2.13/SD.ino",
"chars": 1976,
"preview": "//////////////////////////////////////////////////////////////////////////////\r\n// Das Taupunkt-Lüftungssystem \r\n// mit "
},
{
"path": "Taupunkt_Lueftung_Datenlogging_Version_2.13/Taupunkt_Lueftung_Datenlogging_Version_2.13.ino",
"chars": 11131,
"preview": "//////////////////////////////////////////////////////////////////////////////\r\n// Das Taupunkt-Lüftungssystem \r\n// mit "
},
{
"path": "Taupunkt_Lueftung_Datenlogging_Version_2.13/Zeit.ino",
"chars": 960,
"preview": "//////////////////////////////////////////////////////////////////////////////\r\n// Das Taupunkt-Lüftungssystem \r\n// mit "
}
]
About this extraction
This page contains the full source code of the MakeMagazinDE/Taupunktluefter GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 7 files (30.2 KB), approximately 9.4k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.