From a6984488797928aae572d9ffae2909e4dc06781d Mon Sep 17 00:00:00 2001 From: 3020772 <3020772@stud.hs-mannheim.de> Date: Thu, 15 Oct 2026 11:17:09 +0200 Subject: [PATCH] wifi module --- firmware/dht11_lcd/dht11_lcd.ino | 123 ++++++++++++++++--------------- 1 file changed, 62 insertions(+), 61 deletions(-) diff --git a/firmware/dht11_lcd/dht11_lcd.ino b/firmware/dht11_lcd/dht11_lcd.ino index 0672b74..957e3ba 100644 --- a/firmware/dht11_lcd/dht11_lcd.ino +++ b/firmware/dht11_lcd/dht11_lcd.ino @@ -1,6 +1,7 @@ #include #include "DHT.h" #include +#include #include "Adafruit_CCS811.h" // --- LCD Setup --- @@ -18,33 +19,58 @@ DHT dht(DHTPIN, DHTTYPE); // Standardadresse 0x5A (ADDR an GND), alternativ 0x5B. Adafruit_CCS811 ccs; bool ccsOk = false; -uint8_t ccsAdresse = 0; + +// --- CCS811-Baseline im EEPROM --- +// Die Baseline ist der Kalibrierwert des Sensors. Wird sie nach einem Neustart +// wieder gesetzt, ist der eCO2/TVOC-Wert sofort deutlich stabiler. +// Gespeichert wird erst nach 20 Minuten Laufzeit, danach stündlich. +// Das EEPROM hält ca. 100.000 Schreibzyklen, stündliches Speichern reicht Jahre. +const unsigned long BASELINE_AUFWAERMZEIT = 20UL * 60UL * 1000UL; +const unsigned long BASELINE_INTERVALL = 60UL * 60UL * 1000UL; +const uint8_t BASELINE_MAGIC = 0xC5; // Kennung für "EEPROM enthält eine Baseline" +const int BASELINE_ADRESSE = 0; +unsigned long naechsteBaselineSicherung = BASELINE_AUFWAERMZEIT; + +struct BaselineSpeicher { + uint8_t magic; + uint16_t baseline; + uint8_t pruefsumme; +}; + +uint8_t baselinePruefsumme(uint16_t baseline) { + return (baseline >> 8) ^ (baseline & 0xFF) ^ BASELINE_MAGIC; +} + +// Stellt die gespeicherte Baseline wieder her (falls vorhanden und gültig) +void baselineLaden() { + BaselineSpeicher b; + EEPROM.get(BASELINE_ADRESSE, b); + if (b.magic == BASELINE_MAGIC && b.pruefsumme == baselinePruefsumme(b.baseline)) { + ccs.setBaseline(b.baseline); + Serial.print("Baseline geladen: "); + Serial.println(b.baseline); + } else { + Serial.println("Keine gueltige Baseline im EEPROM"); + } +} + +// Speichert die aktuelle Baseline (EEPROM.put schreibt nur geänderte Bytes) +void baselineSpeichern() { + BaselineSpeicher b; + b.magic = BASELINE_MAGIC; + b.baseline = ccs.getBaseline(); + b.pruefsumme = baselinePruefsumme(b.baseline); + EEPROM.put(BASELINE_ADRESSE, b); + Serial.print("Baseline gespeichert: "); + Serial.println(b.baseline); +} // Anzeige wechselt zwischen zwei Seiten, da das LCD nur 2 Zeilen hat bool zeigeLuftqualitaet = false; -// Debug: sucht alle Geräte am I2C-Bus und gibt die Adressen im Serial Monitor aus. -// Der CCS811 muss bei 0x5A oder 0x5B auftauchen. -void scanneI2C() { - Serial.println(F("I2C-Scan...")); - uint8_t gefunden = 0; - for (uint8_t adr = 1; adr < 127; adr++) { - Wire.beginTransmission(adr); - if (Wire.endTransmission() == 0) { - Serial.print(F(" Geraet bei 0x")); - Serial.println(adr, HEX); - gefunden++; - } - } - if (gefunden == 0) { - Serial.println(F(" KEIN Geraet gefunden -> SDA/SCL, GND, VCC, Loetstellen pruefen")); - } -} - void setup() { - // Serial Monitor (9600 Baud) für Debug-Ausgaben + // Serial Monitor (9600 Baud) zur Kontrolle der Messwerte Serial.begin(9600); - Serial.println(F("--- Start ---")); // LCD initialisieren (16 Spalten, 2 Zeilen) lcd.begin(16, 2); @@ -52,35 +78,15 @@ void setup() { // DHT Sensor starten dht.begin(); - // I2C-Bus durchsuchen (nur zum Debuggen) - Wire.begin(); - scanneI2C(); - // CCS811 starten: erst 0x5A (ADDR an GND), dann 0x5B (ADDR an VCC) - ccsOk = ccs.begin(0x5A); + ccsOk = ccs.begin(0x5A) || ccs.begin(0x5B); if (ccsOk) { - ccsAdresse = 0x5A; - } else if (ccs.begin(0x5B)) { - ccsOk = true; - ccsAdresse = 0x5B; - } - if (ccsOk) { - Serial.print(F("CCS811 OK bei 0x")); - Serial.println(ccsAdresse, HEX); - } else { - Serial.println(F("CCS811 begin() fehlgeschlagen (0x5A und 0x5B)")); + baselineLaden(); } // Kurze Startnachricht lcd.setCursor(0, 0); lcd.print("Sensor startet.."); - lcd.setCursor(0, 1); - if (ccsOk) { - lcd.print("CCS811 @0x"); - lcd.print(ccsAdresse, HEX); - } else { - lcd.print("CCS811 nicht da"); - } // Der DHT11 braucht nach dem Start einen Moment delay(2000); @@ -97,14 +103,7 @@ void loop() { float t = dht.readTemperature(); // Überprüfen, ob das Auslesen fehlgeschlagen ist (z.B. Kabel locker) - Serial.print(F("DHT11: T=")); - Serial.print(t, 1); - Serial.print(F(" C, H=")); - Serial.print(h, 1); - Serial.println(F(" %")); - if (isnan(h) || isnan(t)) { - Serial.println(F("DHT11 FEHLER: NaN -> Daten-Pin 2, VCC/GND, Pull-up pruefen")); lcd.clear(); lcd.setCursor(0, 0); lcd.print("Sensor Fehler!"); @@ -117,7 +116,6 @@ void loop() { lcd.clear(); if (!ccsOk) { - Serial.println(F("CCS811: nicht initialisiert")); lcd.setCursor(0, 0); lcd.print("CCS811 Fehler!"); return; @@ -126,14 +124,7 @@ void loop() { // Temperatur/Feuchte zur Kompensation an den CCS811 geben ccs.setEnvironmentalData(h, t); - bool bereit = ccs.available(); - bool lesefehler = bereit ? ccs.readData() : false; - if (bereit && !lesefehler) { - Serial.print(F("CCS811: eCO2=")); - Serial.print(ccs.geteCO2()); - Serial.print(F(" ppm, TVOC=")); - Serial.print(ccs.getTVOC()); - Serial.println(F(" ppb")); + if (ccs.available() && !ccs.readData()) { lcd.setCursor(0, 0); lcd.print("CO2: "); lcd.print(ccs.geteCO2()); @@ -143,9 +134,19 @@ void loop() { lcd.print("TVOC: "); lcd.print(ccs.getTVOC()); lcd.print(" ppb"); + + Serial.print("eCO2: "); + Serial.print(ccs.geteCO2()); + Serial.print(" ppm TVOC: "); + Serial.print(ccs.getTVOC()); + Serial.println(" ppb"); + + // Baseline regelmäßig sichern (Vergleich überlaufsicher für millis()) + if ((long)(millis() - naechsteBaselineSicherung) >= 0) { + baselineSpeichern(); + naechsteBaselineSicherung = millis() + BASELINE_INTERVALL; + } } else { - Serial.println(bereit ? F("CCS811: Lesefehler") - : F("CCS811: noch keine Daten (Aufwaermphase)")); lcd.setCursor(0, 0); lcd.print("CCS811 wartet.."); }