wifi module
parent
017fac3d2b
commit
a698448879
|
|
@ -1,6 +1,7 @@
|
|||
#include <LiquidCrystal.h>
|
||||
#include "DHT.h"
|
||||
#include <Wire.h>
|
||||
#include <EEPROM.h>
|
||||
#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..");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue