#include #include "DHT.h" #include #include #include "Adafruit_CCS811.h" // --- LCD Setup --- // Initialisierung des LCDs mit den Pins aus deinem Schaltplan // RS = 7, E = 8, D4 = 9, D5 = 10, D6 = 11, D7 = 12 LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // --- DHT11 Setup --- #define DHTPIN 2 // Der DHT11 Daten-Pin ist an Pin 2 angeschlossen #define DHTTYPE DHT11 // Sensortyp festlegen DHT dht(DHTPIN, DHTTYPE); // --- CJMCU-811 (CCS811) Setup --- // I2C: SDA = A4, SCL = A5 (Arduino Uno). Der WAK-Pin des Moduls muss an GND liegen. // Standardadresse 0x5A (ADDR an GND), alternativ 0x5B. Adafruit_CCS811 ccs; bool ccsOk = false; // --- 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; void setup() { // Serial Monitor (9600 Baud) zur Kontrolle der Messwerte Serial.begin(9600); // LCD initialisieren (16 Spalten, 2 Zeilen) lcd.begin(16, 2); // DHT Sensor starten dht.begin(); // CCS811 starten: erst 0x5A (ADDR an GND), dann 0x5B (ADDR an VCC) ccsOk = ccs.begin(0x5A) || ccs.begin(0x5B); if (ccsOk) { baselineLaden(); } // Kurze Startnachricht lcd.setCursor(0, 0); lcd.print("Sensor startet.."); // Der DHT11 braucht nach dem Start einen Moment delay(2000); lcd.clear(); } void loop() { // WICHTIG: Der DHT11 ist ein langsamer Sensor. // Er benötigt ca. 2 Sekunden Pause zwischen den Messungen. delay(2000); // Werte für Luftfeuchtigkeit und Temperatur auslesen float h = dht.readHumidity(); float t = dht.readTemperature(); // Überprüfen, ob das Auslesen fehlgeschlagen ist (z.B. Kabel locker) if (isnan(h) || isnan(t)) { lcd.clear(); lcd.setCursor(0, 0); lcd.print("Sensor Fehler!"); return; // Loop hier abbrechen und von vorne starten } // --- Seite 2: CO2 und TVOC vom CCS811 --- if (zeigeLuftqualitaet) { zeigeLuftqualitaet = false; lcd.clear(); if (!ccsOk) { lcd.setCursor(0, 0); lcd.print("CCS811 Fehler!"); return; } // Temperatur/Feuchte zur Kompensation an den CCS811 geben ccs.setEnvironmentalData(h, t); if (ccs.available() && !ccs.readData()) { lcd.setCursor(0, 0); lcd.print("CO2: "); lcd.print(ccs.geteCO2()); lcd.print(" ppm"); lcd.setCursor(0, 1); 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 { lcd.setCursor(0, 0); lcd.print("CCS811 wartet.."); } return; } // --- Seite 1: Ausgabe auf dem LCD Display --- zeigeLuftqualitaet = true; // Zeile 1: Temperatur lcd.setCursor(0, 0); // Spalte 0, Zeile 0 lcd.print("Temp: "); lcd.print(t, 1); // Die ", 1" sorgt dafür, dass nur eine Nachkommastelle gezeigt wird lcd.print(" C "); // Leerzeichen am Ende überschreiben eventuelle alte Zeichen // Zeile 2: Luftfeuchtigkeit lcd.setCursor(0, 1); // Spalte 0, Zeile 1 lcd.print("Luft: "); lcd.print(h, 1); lcd.print(" % "); }