Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
| www-messdatenerfassung-sas:platinenschaltung [2026/09/12 13:33] – angelegt biebl | www-messdatenerfassung-sas:platinenschaltung [2026/09/12 16:09] (aktuell) – biebl | ||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| + | ====== WWW: Platinen mit TESTCODE====== | ||
| + | |||
| + | * [[platinenschaltung-Außenbox|WWW: | ||
| ^ Seite ^ Inhalt | ^ Seite ^ Inhalt | ||
| Zeile 10: | Zeile 13: | ||
| | [[Unterrichtseinsatz|Schule]] | | [[Unterrichtseinsatz|Schule]] | ||
| | [[Sonstiges|Sonstiges]]| dies und das....| | | [[Sonstiges|Sonstiges]]| dies und das....| | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | * [[https:// | ||
| + | * Nach Erstellung benötigt die günstigste " | ||
| + | * Bei unseren Platinen kostete eine Platine 1,5 Euro | ||
| + | |||
| + | * [[https:// | ||
| + | |||
| + | |||
| + | * [[lehrer: | ||
| + | |||
| + | * [[info: | ||
| + | |||
| + | ===== Raumklima - Messbox ===== | ||
| + | |||
| + | * [[info: | ||
| + | * [[lehrer: | ||
| + | |||
| + | {{: | ||
| + | |||
| + | |||
| + | ^ Sensor | ||
| + | | DHT22 | D7 | 13 | ||
| + | | MH-Z19B | ||
| + | | BMP180 | ||
| + | | LED | D4 | 2 | | ✅ | | ||
| + | | LDR | A0 | A0 | analogRead | ||
| + | |||
| + | ==== D1-mini ==== | ||
| + | |||
| + | * Inzwischen wird der DHT22 mit BMP180 bei neueren Messboxen durch den BME280 ersetzt, was den Aufbau und den Code nochmalig vereinfacht. | ||
| + | * Der MHZ19B wird inzwischen **ohne Spannungsteiler** betrieben - Der D1-mini ist 5V tolerant! | ||
| + | * Bei einem ESP32 wäre es nicht ratsam, da dieser nicht 5V tolerant ist... | ||
| + | |||
| + | {{: | ||
| + | |||
| + | {{: | ||
| + | |||
| + | |||
| + | ==== Bestückung ==== | ||
| + | === Materialliste === | ||
| + | |||
| + | * auf Vollständigkeit prüfen | ||
| + | |||
| + | {{: | ||
| + | |||
| + | === 1. Drahtbrücke === | ||
| + | |||
| + | * überstehende Reste entfernen | ||
| + | |||
| + | |||
| + | |||
| + | {{: | ||
| + | === 2. Winkelstifte LED und BMP === | ||
| + | |||
| + | * ACHTUNG: auf die genaue Position achten | ||
| + | |||
| + | {{: | ||
| + | === 3. 3er Stifte DHT22 === | ||
| + | |||
| + | * auf senkrechte Montage achten | ||
| + | |||
| + | {{: | ||
| + | === 4. 8er Buchsen D1-mini == | ||
| + | |||
| + | * auf senkrechte Montage achten | ||
| + | * Reste nach dem Löten entfernen | ||
| + | |||
| + | {{: | ||
| + | === 5. 4er- und 5er-Buchse MHZ19B === | ||
| + | |||
| + | * auf senkrechte Montage achten | ||
| + | * Reste nach dem Löten entfernen | ||
| + | |||
| + | {{: | ||
| + | === 6. Widerstand 470kΩ === | ||
| + | |||
| + | * Reste nach dem Löten entfernen | ||
| + | |||
| + | {{: | ||
| + | === 7. 2er-Buchse LDR === | ||
| + | |||
| + | * auf senkrechte Montage achten | ||
| + | * Reste nach dem Löten entfernen | ||
| + | |||
| + | |||
| + | {{: | ||
| + | === 8. Externe Sensoren === | ||
| + | |||
| + | {{: | ||
| + | === 9. fertiges Modul === | ||
| + | |||
| + | |||
| + | {{: | ||
| + | |||
| + | |||
| + | |||
| + | ====== Testcode - Raumklima ====== | ||
| + | |||
| + | [[lehrer: | ||
| + | |||
| + | ===== BMP180 ===== | ||
| + | |||
| + | < | ||
| + | / | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | #define ALTITUDE 42.0 // Höhe über Meeresspiegel in Metern (anpassen!) | ||
| + | |||
| + | SFE_BMP180 pressure; | ||
| + | |||
| + | void setup() { | ||
| + | Serial.begin(115200); | ||
| + | delay(500); | ||
| + | Serial.println(" | ||
| + | | ||
| + | // I2C initialisieren (Standard-Pins D1=SCL, D2=SDA) | ||
| + | Wire.begin(); | ||
| + | | ||
| + | if (pressure.begin()) { | ||
| + | Serial.println(" | ||
| + | } else { | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | while(1) delay(10); | ||
| + | } | ||
| + | | ||
| + | Serial.println(" | ||
| + | } | ||
| + | |||
| + | void loop() { | ||
| + | char status; | ||
| + | double T, P, p0; | ||
| + | | ||
| + | // 1. Temperatur messen | ||
| + | status = pressure.startTemperature(); | ||
| + | if (status != 0) { | ||
| + | delay(status); | ||
| + | | ||
| + | status = pressure.getTemperature(T); | ||
| + | if (status != 0) { | ||
| + | Serial.print(" | ||
| + | Serial.print(T, | ||
| + | Serial.println(" | ||
| + | | ||
| + | // 2. Luftdruck messen (benötigt Temperatur) | ||
| + | status = pressure.startPressure(3); | ||
| + | if (status != 0) { | ||
| + | delay(status); | ||
| + | | ||
| + | status = pressure.getPressure(P, | ||
| + | if (status != 0) { | ||
| + | Serial.print(" | ||
| + | Serial.print(P, | ||
| + | Serial.println(" | ||
| + | | ||
| + | // 3. Auf Meereshöhe korrigierter Druck | ||
| + | p0 = pressure.sealevel(P, | ||
| + | Serial.print(" | ||
| + | Serial.print(p0, | ||
| + | Serial.println(" | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | } else { | ||
| + | Serial.println(" | ||
| + | } | ||
| + | | ||
| + | Serial.println(" | ||
| + | delay(2000); | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | 18: | ||
| + | 18: | ||
| + | 18: | ||
| + | 18: | ||
| + | 18: | ||
| + | </ | ||
| + | ===== DHT22 ===== | ||
| + | < | ||
| + | / | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | #include " | ||
| + | |||
| + | #define DHTPIN 13 // D7 | ||
| + | #define DHTTYPE DHT22 | ||
| + | |||
| + | DHT dht(DHTPIN, DHTTYPE); | ||
| + | |||
| + | void setup() { | ||
| + | Serial.begin(115200); | ||
| + | delay(500); | ||
| + | Serial.println(" | ||
| + | | ||
| + | dht.begin(); | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | | ||
| + | delay(2000); | ||
| + | } | ||
| + | |||
| + | void loop() { | ||
| + | // Luftfeuchtigkeit und Temperatur auslesen | ||
| + | float humidity = dht.readHumidity(); | ||
| + | float temperature = dht.readTemperature(); | ||
| + | | ||
| + | // Prüfen ob Messung erfolgreich | ||
| + | if (isnan(humidity) || isnan(temperature)) { | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | } else { | ||
| + | Serial.print(" | ||
| + | Serial.print(humidity, | ||
| + | Serial.println(" | ||
| + | | ||
| + | Serial.print(" | ||
| + | Serial.print(temperature, | ||
| + | Serial.println(" | ||
| + | | ||
| + | // Taupunkt berechnen (optional) | ||
| + | float dewPoint = temperature - ((100 - humidity) / 5.0); | ||
| + | Serial.print(" | ||
| + | Serial.print(dewPoint, | ||
| + | Serial.println(" | ||
| + | } | ||
| + | | ||
| + | Serial.println(" | ||
| + | delay(2500); | ||
| + | } | ||
| + | </ | ||
| + | < | ||
| + | 18: | ||
| + | 18: | ||
| + | 18: | ||
| + | 18: | ||
| + | 18: | ||
| + | </ | ||
| + | |||
| + | ===== MHZ19B ===== | ||
| + | < | ||
| + | / | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | #include < | ||
| + | |||
| + | // Software Serial: RX=D6 (GPIO12), TX=D5 (GPIO14) | ||
| + | SoftwareSerial mhzSerial(12, | ||
| + | |||
| + | // Kommando zum Auslesen der CO₂-Konzentration | ||
| + | byte cmdReadCO2[] = {0xFF, 0x01, 0x86, 0, 0, 0, 0, 0, 0x79}; | ||
| + | |||
| + | void setup() { | ||
| + | Serial.begin(115200); | ||
| + | delay(500); | ||
| + | Serial.println(" | ||
| + | | ||
| + | mhzSerial.begin(9600); | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | | ||
| + | delay(2000); | ||
| + | } | ||
| + | |||
| + | void loop() { | ||
| + | int ppm = -1; | ||
| + | int temp = -999; | ||
| + | | ||
| + | if (readMHZ19B(ppm, | ||
| + | Serial.print(" | ||
| + | Serial.print(ppm); | ||
| + | Serial.print(" | ||
| + | | ||
| + | // Bewertung | ||
| + | if (ppm < 700) { | ||
| + | Serial.print(" | ||
| + | } else if (ppm < 1000) { | ||
| + | Serial.print(" | ||
| + | } else if (ppm < 1500) { | ||
| + | Serial.print(" | ||
| + | } else if (ppm < 2000) { | ||
| + | Serial.print(" | ||
| + | } else { | ||
| + | Serial.print(" | ||
| + | } | ||
| + | Serial.println(); | ||
| + | | ||
| + | Serial.print(" | ||
| + | Serial.print(temp); | ||
| + | Serial.println(" | ||
| + | | ||
| + | } else { | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | } | ||
| + | | ||
| + | Serial.println(" | ||
| + | delay(5000); | ||
| + | } | ||
| + | |||
| + | // MH-Z19B auslesen mit Checksummen-Prüfung | ||
| + | bool readMHZ19B(int &ppm, int &tempC) { | ||
| + | // Puffer leeren (alte Daten verwerfen) | ||
| + | while (mhzSerial.available()) { | ||
| + | mhzSerial.read(); | ||
| + | } | ||
| + | | ||
| + | // Kommando senden | ||
| + | mhzSerial.write(cmdReadCO2, | ||
| + | | ||
| + | // Antwort lesen (9 Bytes, max. 200ms warten) | ||
| + | byte response[9]; | ||
| + | int bytesRead = 0; | ||
| + | unsigned long startTime = millis(); | ||
| + | | ||
| + | while (bytesRead < 9 && millis() - startTime < 200) { | ||
| + | if (mhzSerial.available()) { | ||
| + | response[bytesRead++] = mhzSerial.read(); | ||
| + | } | ||
| + | delay(1); | ||
| + | } | ||
| + | | ||
| + | // Prüfen ob vollständiges Paket empfangen | ||
| + | if (bytesRead != 9) { | ||
| + | Serial.print(" | ||
| + | Serial.print(bytesRead); | ||
| + | Serial.println(" | ||
| + | return false; | ||
| + | } | ||
| + | | ||
| + | // Header prüfen (sollte 0xFF 0x86 sein) | ||
| + | if (response[0] != 0xFF || response[1] != 0x86) { | ||
| + | Serial.print(" | ||
| + | Serial.print(response[0], | ||
| + | Serial.print(" | ||
| + | Serial.println(response[1], | ||
| + | return false; | ||
| + | } | ||
| + | | ||
| + | // Checksumme berechnen und prüfen | ||
| + | byte checksum = 0; | ||
| + | for (int i = 1; i < 8; i++) { | ||
| + | checksum += response[i]; | ||
| + | } | ||
| + | checksum = 0xFF - checksum + 1; | ||
| + | | ||
| + | if (checksum != response[8]) { | ||
| + | Serial.print(" | ||
| + | Serial.print(checksum, | ||
| + | Serial.print(" | ||
| + | Serial.println(response[8], | ||
| + | return false; | ||
| + | } | ||
| + | | ||
| + | // Werte extrahieren | ||
| + | ppm = response[2] * 256 + response[3]; | ||
| + | tempC = response[4] - 40; // Temperatur ist offset um 40°C | ||
| + | | ||
| + | // Plausibilitätsprüfung | ||
| + | if (ppm < 0 || ppm > 5000) { | ||
| + | Serial.print(" | ||
| + | Serial.println(ppm); | ||
| + | return false; | ||
| + | } | ||
| + | | ||
| + | return true; | ||
| + | } | ||
| + | </ | ||
| + | < | ||
| + | 18: | ||
| + | 18: | ||
| + | 18: | ||
| + | 18: | ||
| + | </ | ||
| + | |||
| + | ==== Kalibrierung ==== | ||
| + | |||
| + | Falls der MHZ-19B falsche Werte anzeigt hilft vielleicht eine Kalibrierung an der frischen Luft ;-) | ||
| + | |||
| + | ⚡ Start → ABC wird sofort ausgeschaltet | ||
| + | ⏱️ 20 Minuten → Sensor stabilisiert sich in Frischluft (zeigt Countdown) | ||
| + | 🎯 Kalibrierung → Zero Point Calibration auf Frischluft | ||
| + | 📊 Messbetrieb → Kontinuierliche Messung alle 10 Sekunden | ||
| + | |||
| + | Vorgehensweise: | ||
| + | |||
| + | * Code auf den D1 mini hochladen | ||
| + | * Sofort mit Powerbank vor die Tür legen (wichtig: nicht erst drinnen testen!) | ||
| + | * 20 Minuten warten (Sie sehen den Countdown am seriellen Monitor) | ||
| + | * Nach Kalibrierung können Sie das Gerät wieder reinholen | ||
| + | * Fertig - der Sensor zeigt jetzt korrekte Werte! | ||
| + | |||
| + | < | ||
| + | / | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | #include < | ||
| + | |||
| + | / | ||
| + | | ||
| + | | ||
| + | |||
| + | // Serielle Schnittstelle für MH-Z19B (Software Serial) | ||
| + | #define MHZ_RX_PIN D6 // D1 mini D6 → MH-Z19B TX | ||
| + | #define MHZ_TX_PIN D5 // D1 mini D5 → MH-Z19B RX | ||
| + | |||
| + | // Zeitsteuerung | ||
| + | const unsigned long WARTEZEIT_MS = 20UL * 60UL * 1000UL; | ||
| + | const unsigned long MESS_INTERVALL = 10000; | ||
| + | |||
| + | / | ||
| + | | ||
| + | | ||
| + | |||
| + | SoftwareSerial mhzSerial(MHZ_RX_PIN, | ||
| + | |||
| + | // Status-Flags | ||
| + | bool abcDeaktiviert = false; | ||
| + | bool kalibriert = false; | ||
| + | unsigned long startzeit = 0; | ||
| + | |||
| + | / | ||
| + | | ||
| + | | ||
| + | |||
| + | // Befehl: CO2-Wert lesen | ||
| + | byte cmdReadCO2[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; | ||
| + | |||
| + | // Befehl: ABC ausschalten | ||
| + | byte cmdABCoff[9] = {0xFF, 0x01, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86}; | ||
| + | |||
| + | // Befehl: Zero Point Calibration (Frischluft-Kalibrierung) | ||
| + | byte cmdCalibrate[9] = {0xFF, 0x01, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78}; | ||
| + | |||
| + | / | ||
| + | | ||
| + | | ||
| + | void setup() { | ||
| + | // Serielle Schnittstelle zum PC starten | ||
| + | Serial.begin(115200); | ||
| + | delay(200); | ||
| + | | ||
| + | Serial.println(); | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(); | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(); | ||
| + | | ||
| + | // Serielle Schnittstelle zum MH-Z19B starten (9600 Baud) | ||
| + | mhzSerial.begin(9600); | ||
| + | delay(500); | ||
| + | | ||
| + | // SCHRITT 1: ABC ausschalten | ||
| + | Serial.println(" | ||
| + | mhzSerial.write(cmdABCoff, | ||
| + | delay(1000); | ||
| + | abcDeaktiviert = true; | ||
| + | Serial.println(" | ||
| + | Serial.println(); | ||
| + | | ||
| + | // Startzeit merken | ||
| + | startzeit = millis(); | ||
| + | | ||
| + | // Berechne Kalibrierungszeitpunkt | ||
| + | unsigned long minuten = WARTEZEIT_MS / 60000; | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.printf(" | ||
| + | Serial.println(); | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(); | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(); | ||
| + | } | ||
| + | |||
| + | / | ||
| + | | ||
| + | | ||
| + | void loop() { | ||
| + | unsigned long jetzt = millis(); | ||
| + | unsigned long vergangen = jetzt - startzeit; | ||
| + | | ||
| + | // CO2-Wert auslesen | ||
| + | int co2 = leseCO2(); | ||
| + | | ||
| + | // ========== VOR DER KALIBRIERUNG ========== | ||
| + | if (!kalibriert && vergangen < WARTEZEIT_MS) { | ||
| + | // Zeit bis zur Kalibrierung berechnen | ||
| + | unsigned long verbleibend = WARTEZEIT_MS - vergangen; | ||
| + | unsigned long minutenVerbleibend = verbleibend / 60000; | ||
| + | unsigned long sekundenVerbleibend = (verbleibend % 60000) / 1000; | ||
| + | | ||
| + | // Fortschritt anzeigen | ||
| + | Serial.print(" | ||
| + | Serial.printf(" | ||
| + | Serial.print(" | ||
| + | | ||
| + | if (co2 > 0) { | ||
| + | Serial.print(co2); | ||
| + | Serial.println(" | ||
| + | } else { | ||
| + | Serial.println(" | ||
| + | } | ||
| + | | ||
| + | // Warte 10 Sekunden bis zur nächsten Messung | ||
| + | delay(MESS_INTERVALL); | ||
| + | } | ||
| + | | ||
| + | // ========== KALIBRIERUNG DURCHFÜHREN ========== | ||
| + | else if (!kalibriert && vergangen >= WARTEZEIT_MS) { | ||
| + | Serial.println(); | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(); | ||
| + | | ||
| + | // Aktuellen Wert vor Kalibrierung anzeigen | ||
| + | Serial.print(" | ||
| + | if (co2 > 0) { | ||
| + | Serial.print(co2); | ||
| + | Serial.println(" | ||
| + | } else { | ||
| + | Serial.println(" | ||
| + | } | ||
| + | Serial.println(); | ||
| + | | ||
| + | // Kalibrierungs-Befehl senden | ||
| + | Serial.println(" | ||
| + | mhzSerial.write(cmdCalibrate, | ||
| + | delay(2000); | ||
| + | | ||
| + | Serial.println(" | ||
| + | Serial.println(); | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(); | ||
| + | | ||
| + | kalibriert = true; | ||
| + | | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(); | ||
| + | Serial.println(" | ||
| + | Serial.println(); | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(); | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | Serial.println(); | ||
| + | } | ||
| + | | ||
| + | // ========== NORMALER MESSBETRIEB ========== | ||
| + | else if (kalibriert) { | ||
| + | // Betriebszeit berechnen | ||
| + | unsigned long betriebszeit = (jetzt - startzeit) / 1000; // in Sekunden | ||
| + | unsigned long stunden = betriebszeit / 3600; | ||
| + | unsigned long minuten = (betriebszeit % 3600) / 60; | ||
| + | unsigned long sekunden = betriebszeit % 60; | ||
| + | | ||
| + | // Messwert anzeigen | ||
| + | Serial.printf(" | ||
| + | Serial.print(" | ||
| + | | ||
| + | if (co2 > 0) { | ||
| + | Serial.print(co2); | ||
| + | Serial.print(" | ||
| + | | ||
| + | // Bewertung hinzufügen | ||
| + | if (co2 < 600) { | ||
| + | Serial.println(" | ||
| + | } else if (co2 < 1000) { | ||
| + | Serial.println(" | ||
| + | } else if (co2 < 1500) { | ||
| + | Serial.println(" | ||
| + | } else { | ||
| + | Serial.println(" | ||
| + | } | ||
| + | } else { | ||
| + | Serial.println(" | ||
| + | } | ||
| + | | ||
| + | delay(MESS_INTERVALL); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | / | ||
| + | | ||
| + | | ||
| + | |||
| + | /** | ||
| + | * Liest den CO2-Wert vom MH-Z19B Sensor | ||
| + | * @return CO2-Wert in ppm (0 bei Fehler) | ||
| + | */ | ||
| + | int leseCO2() { | ||
| + | // Puffer leeren | ||
| + | while (mhzSerial.available()) { | ||
| + | mhzSerial.read(); | ||
| + | } | ||
| + | | ||
| + | // Read-Befehl senden | ||
| + | mhzSerial.write(cmdReadCO2, | ||
| + | | ||
| + | // Auf Antwort warten (max. 1 Sekunde) | ||
| + | unsigned long timeout = millis() + 1000; | ||
| + | while (mhzSerial.available() < 9 && millis() < timeout) { | ||
| + | delay(10); | ||
| + | } | ||
| + | | ||
| + | // Prüfen, ob genug Daten empfangen wurden | ||
| + | if (mhzSerial.available() < 9) { | ||
| + | return 0; // Timeout | ||
| + | } | ||
| + | | ||
| + | // 9 Bytes lesen | ||
| + | byte response[9]; | ||
| + | for (int i = 0; i < 9; i++) { | ||
| + | response[i] = mhzSerial.read(); | ||
| + | } | ||
| + | | ||
| + | // Prüfen, ob Antwort gültig ist | ||
| + | if (response[0] != 0xFF || response[1] != 0x86) { | ||
| + | return 0; // Ungültige Antwort | ||
| + | } | ||
| + | | ||
| + | // Checksum überprüfen (optional, für mehr Zuverlässigkeit) | ||
| + | byte checksum = 0; | ||
| + | for (int i = 1; i < 8; i++) { | ||
| + | checksum += response[i]; | ||
| + | } | ||
| + | checksum = 0xFF - checksum + 1; | ||
| + | | ||
| + | if (checksum != response[8]) { | ||
| + | return 0; // Checksum-Fehler | ||
| + | } | ||
| + | | ||
| + | // CO2-Wert aus Bytes 2 und 3 extrahieren | ||
| + | int co2 = (response[2] << 8) | response[3]; | ||
| + | | ||
| + | return co2; | ||
| + | } | ||
| + | |||
| + | / | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | </ | ||
| + | ===== LDR ===== | ||
| + | < | ||
| + | / | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | #define LDR_PIN A0 | ||
| + | |||
| + | void setup() { | ||
| + | Serial.begin(115200); | ||
| + | delay(500); | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | | ||
| + | pinMode(LDR_PIN, | ||
| + | | ||
| + | delay(1000); | ||
| + | } | ||
| + | |||
| + | void loop() { | ||
| + | // Rohwert auslesen (0-1023) | ||
| + | int rawValue = analogRead(LDR_PIN); | ||
| + | | ||
| + | // Invertiert wie im Hauptcode (450 - raw) | ||
| + | // → hell wird zu kleinem Wert, dunkel zu großem Wert | ||
| + | int inverted = 450 - rawValue; | ||
| + | | ||
| + | // Bargraph für Rohwert erstellen | ||
| + | Serial.print(" | ||
| + | printBar(rawValue, | ||
| + | Serial.print(" | ||
| + | Serial.print(rawValue); | ||
| + | Serial.print(" | ||
| + | | ||
| + | // Interpretation | ||
| + | if (rawValue > 800) { | ||
| + | Serial.print(" | ||
| + | } else if (rawValue > 500) { | ||
| + | Serial.print(" | ||
| + | } else if (rawValue > 200) { | ||
| + | Serial.print(" | ||
| + | } else if (rawValue > 50) { | ||
| + | Serial.print(" | ||
| + | } else { | ||
| + | Serial.print(" | ||
| + | } | ||
| + | Serial.println(); | ||
| + | | ||
| + | // Invertierter Wert (wie er an EmonCMS gesendet wird) | ||
| + | Serial.print(" | ||
| + | Serial.println(inverted); | ||
| + | | ||
| + | Serial.println(" | ||
| + | delay(500); | ||
| + | } | ||
| + | |||
| + | // Hilfsfunktion: | ||
| + | void printBar(int value, int maxValue) { | ||
| + | int barLength = map(value, 0, maxValue, 0, 40); | ||
| + | Serial.print(" | ||
| + | for (int i = 0; i < 40; i++) { | ||
| + | if (i < barLength) { | ||
| + | Serial.print(" | ||
| + | } else { | ||
| + | Serial.print(" | ||
| + | } | ||
| + | } | ||
| + | Serial.print(" | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | <code | ||
| + | 18: | ||
| + | 18: | ||
| + | 18: | ||
| + | 18: | ||
| + | </ | ||
| + | |||
| + | ===== LED-Band ===== | ||
| + | ===== LED-Band ===== | ||
| + | < | ||
| + | / | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | #include < | ||
| + | |||
| + | #define LED_PIN | ||
| + | #define NUM_LEDS | ||
| + | |||
| + | Adafruit_NeoPixel strip(NUM_LEDS, | ||
| + | |||
| + | void setup() { | ||
| + | Serial.begin(115200); | ||
| + | delay(500); | ||
| + | Serial.println(" | ||
| + | Serial.println(" | ||
| + | | ||
| + | strip.begin(); | ||
| + | strip.show(); | ||
| + | | ||
| + | Serial.println(" | ||
| + | } | ||
| + | |||
| + | void loop() { | ||
| + | // 1. Einzelne LEDs durchgehen (Rot) | ||
| + | Serial.println(" | ||
| + | strip.clear(); | ||
| + | for (int i = 0; i < NUM_LEDS; i++) { | ||
| + | strip.setPixelColor(i, | ||
| + | strip.show(); | ||
| + | delay(300); | ||
| + | } | ||
| + | delay(1000); | ||
| + | | ||
| + | // 2. Alle LEDs in verschiedenen Farben | ||
| + | Serial.println(" | ||
| + | | ||
| + | Serial.println(" | ||
| + | strip.fill(strip.Color(255, | ||
| + | strip.show(); | ||
| + | delay(1000); | ||
| + | | ||
| + | Serial.println(" | ||
| + | strip.fill(strip.Color(0, | ||
| + | strip.show(); | ||
| + | delay(1000); | ||
| + | | ||
| + | Serial.println(" | ||
| + | strip.fill(strip.Color(0, | ||
| + | strip.show(); | ||
| + | delay(1000); | ||
| + | | ||
| + | Serial.println(" | ||
| + | strip.fill(strip.Color(255, | ||
| + | strip.show(); | ||
| + | delay(1000); | ||
| + | | ||
| + | Serial.println(" | ||
| + | strip.fill(strip.Color(255, | ||
| + | strip.show(); | ||
| + | delay(1000); | ||
| + | | ||
| + | // 3. CO₂-Ampel Simulation (wie im Hauptcode) | ||
| + | Serial.println(" | ||
| + | | ||
| + | Serial.println(" | ||
| + | setCO2Color(600); | ||
| + | delay(2000); | ||
| + | | ||
| + | Serial.println(" | ||
| + | setCO2Color(900); | ||
| + | delay(2000); | ||
| + | | ||
| + | Serial.println(" | ||
| + | setCO2Color(1400); | ||
| + | delay(2000); | ||
| + | | ||
| + | Serial.println(" | ||
| + | setCO2Color(2000); | ||
| + | delay(2000); | ||
| + | | ||
| + | Serial.println(" | ||
| + | setCO2Color(2600); | ||
| + | delay(3000); | ||
| + | | ||
| + | // 4. Helligkeitstest | ||
| + | Serial.println(" | ||
| + | for (int brightness = 0; brightness <= 255; brightness += 25) { | ||
| + | Serial.print(" | ||
| + | Serial.println(brightness); | ||
| + | strip.setBrightness(brightness); | ||
| + | strip.fill(strip.Color(255, | ||
| + | strip.show(); | ||
| + | delay(500); | ||
| + | } | ||
| + | | ||
| + | // 5. Regenbogen-Effekt | ||
| + | Serial.println(" | ||
| + | rainbowCycle(5); | ||
| + | | ||
| + | Serial.println(" | ||
| + | delay(2000); | ||
| + | } | ||
| + | |||
| + | // CO₂-Ampel Funktion (aus Hauptcode übernommen) | ||
| + | void setCO2Color(int co2) { | ||
| + | if (co2 < 700) { | ||
| + | strip.setBrightness(2); | ||
| + | strip.fill(strip.Color(0, | ||
| + | } else if (co2 < 1100) { | ||
| + | strip.setBrightness(3); | ||
| + | strip.fill(strip.Color(0, | ||
| + | } else if (co2 < 1800) { | ||
| + | strip.setBrightness(4); | ||
| + | strip.fill(strip.Color(255, | ||
| + | } else if (co2 < 2500) { | ||
| + | strip.setBrightness(120); | ||
| + | strip.fill(strip.Color(255, | ||
| + | } else { | ||
| + | // Alarm: Rot-Weiß blitzen | ||
| + | for (int i = 0; i < 5; i++) { | ||
| + | strip.setBrightness(255); | ||
| + | strip.fill(strip.Color(255, | ||
| + | strip.show(); | ||
| + | delay(200); | ||
| + | strip.fill(strip.Color(255, | ||
| + | strip.show(); | ||
| + | delay(200); | ||
| + | strip.clear(); | ||
| + | strip.show(); | ||
| + | delay(200); | ||
| + | } | ||
| + | strip.setBrightness(120); | ||
| + | strip.fill(strip.Color(255, | ||
| + | strip.show(); | ||
| + | return; | ||
| + | } | ||
| + | strip.show(); | ||
| + | } | ||
| + | |||
| + | // Regenbogen-Effekt | ||
| + | void rainbowCycle(int cycles) { | ||
| + | for (int j = 0; j < 256 * cycles; j++) { | ||
| + | for (int i = 0; i < NUM_LEDS; i++) { | ||
| + | strip.setPixelColor(i, | ||
| + | } | ||
| + | strip.show(); | ||
| + | delay(5); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // Hilfsfunktion für Regenbogen (Farbrad) | ||
| + | uint32_t Wheel(byte WheelPos) { | ||
| + | WheelPos = 255 - WheelPos; | ||
| + | if (WheelPos < 85) { | ||
| + | return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3); | ||
| + | } | ||
| + | if (WheelPos < 170) { | ||
| + | WheelPos -= 85; | ||
| + | return strip.Color(0, | ||
| + | } | ||
| + | WheelPos -= 170; | ||
| + | return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0); | ||
| + | } | ||
| + | </ | ||