Compare commits

..

3 Commits

Author SHA1 Message Date
Matias Mas Viehl a698448879 wifi module 2026-10-15 11:17:09 +02:00
Matias Mas Viehl 017fac3d2b CCS811: Adresserkennung, Serial-Debug und eigener Testsketch
- dht11_lcd: CCS811 an 0x5A und 0x5B probieren, I2C-Scan und
  Serial-Ausgabe zum Debuggen
- ccs811_test: eigener Sketch nur für den CCS811 mit Konsolenausgabe

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-13 11:19:49 +02:00
Matias Mas Viehl a7964b9ca9 dht11 und CJMCU-811 anbindung 2026-10-08 11:16:17 +02:00
2 changed files with 245 additions and 0 deletions

View File

@ -0,0 +1,75 @@
#include <Wire.h>
#include "Adafruit_CCS811.h"
// Reiner CCS811-Test (CJMCU-811) ohne LCD und DHT11. Ausgabe im Serial Monitor (9600 Baud).
// I2C: SDA = A4, SCL = A5 (Arduino Uno). WAK und ADD des Moduls an GND -> Adresse 0x5A.
// Mit ADD an VCC lautet die Adresse 0x5B.
Adafruit_CCS811 ccs;
bool ccsOk = false;
// Sucht alle Geräte am I2C-Bus. 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, WAK, Loetstellen pruefen"));
}
}
void setup() {
Serial.begin(9600);
Serial.println(F("--- CCS811-Test ---"));
Wire.begin();
scanneI2C();
// Erst 0x5A (ADD an GND), dann 0x5B (ADD an VCC)
uint8_t adresse = 0x5A;
ccsOk = ccs.begin(0x5A);
if (!ccsOk) {
adresse = 0x5B;
ccsOk = ccs.begin(0x5B);
}
if (ccsOk) {
Serial.print(F("CCS811 OK bei 0x"));
Serial.println(adresse, HEX);
Serial.println(F("Aufwaermphase: die ersten Werte sind oft 400 ppm / 0 ppb."));
} else {
Serial.println(F("CCS811 begin() fehlgeschlagen (0x5A und 0x5B)"));
}
}
void loop() {
delay(1000);
if (!ccsOk) {
Serial.println(F("CCS811: nicht initialisiert"));
return;
}
if (!ccs.available()) {
Serial.println(F("CCS811: noch keine neuen Daten"));
return;
}
if (ccs.readData()) {
Serial.println(F("CCS811: Lesefehler"));
return;
}
Serial.print(F("eCO2: "));
Serial.print(ccs.geteCO2());
Serial.print(F(" ppm TVOC: "));
Serial.print(ccs.getTVOC());
Serial.println(F(" ppb"));
}

View File

@ -0,0 +1,170 @@
#include <LiquidCrystal.h>
#include "DHT.h"
#include <Wire.h>
#include <EEPROM.h>
#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(" % ");
}