===== Klimamessbox - Außenbereich mit Feinstaubmessung=====
* NOCH nicht aktualisiert - Nur noch BME280, kein DHT22 mehr...
* Die Bilder liegen noch nicht im WWW-Bereich und fehlen somit bei fehlender Anmeldung
{{:info:arduino:esp8266-wemos-d1-mini-pinout-gpio-pin-2.png?300|}}{{:info:platinen:sds011-dust-sensor-pinout-diagram.jpg?300|}}
^ Sensor ^ Pin (GPIO) ^ Anschluss ^ Besonderheit ^
| MH-Z19B | GPIO12/14 | D6 / D5 | Spannungsteiler für D6; SoftwareSerial |
| SDS011 | GPIO13/15 | D7 / D8 | Spannungsteiler für D7 darf NICHT eingebaut werden, der SDS sendet bereits mit 3,3V Logik; SoftwareSerial |
| BMP180 | GPIO4/5 | D2 / D1 | I²C (fest: SDA=SDA, SCL=SCL) |
| LDR | ADC0 | A0 | analog |
| DHT22 | GPIO3 | RX | **Nur nach Upload einstecken!** |
==== Di-mini-Platine ====
ACHTUNG: Für den SDS011 KEINEN Spannungsteiler verwenden, er sendet bereits mit 3,3 V Logik
{{:info:platinen:platine-klimamessbox-d1-mini.png?300|}}
{{:info:platinen:platine-klimamessbox-d1-mini-2d-unten.png?200|}}
{{:info:platinen:platine-klimamessbox-d1-mini-2d-oben.png?200|}}
{{:info:platinen:platine-klimamessbox-d1-mini-3d-unten.png?200|}}
{{:info:platinen:platine-klimamessbox-d1-mini-3d-oben.png?200|}}
==== Sensorplatine ====
{{:info:platinen:platine-klimamessbox-sensoren.png?300|}}
{{:info:platinen:platine-klimamessbox-sensoren-2d-unten.png?200|}}
{{:info:platinen:platine-klimamessbox-sensoren-2d-oben.png?200|}}
{{:info:platinen:platine-klimamessbox-sensoren-3d-unten.png?200|}}
{{:info:platinen:platine-klimamessbox-sensoren-3d-oben.png?200|}}
===== TESTCODE KLIMABOX BME, MHZ und SDS=====
==== BME280 ====
#include
#include
#define BME280_ADDRESS 0x76 // ggf. 0x77 testen
Adafruit_BME280 bme;
void setup() {
Serial.begin(115200);
delay(200);
Serial.println("\nBME280 Test");
Wire.begin(4, 5); // SDA = GPIO4, SCL = GPIO5
if (!bme.begin(BME280_ADDRESS)) {
Serial.println("BME280 nicht gefunden, Adresse oder Verkabelung prüfen!");
while (1) delay(100);
}
Serial.println("BME280 gefunden.");
}
void loop() {
float t = bme.readTemperature();
float h = bme.readHumidity();
float p = bme.readPressure() / 100.0; // hPa
Serial.print("Temp: "); Serial.print(t); Serial.println(" °C");
Serial.print("Feuchte: "); Serial.print(h); Serial.println(" %");
Serial.print("Druck: "); Serial.print(p); Serial.println(" hPa");
Serial.println("----");
delay(2000);
}
18:11:23.194 -> ----
18:11:25.191 -> Temp: 22.28 °C
18:11:25.191 -> Feuchte: 35.97 %
18:11:25.191 -> Druck: 1008.70 hPa
18:11:25.191 -> ----
==== MHZ-19B ====
#include
SoftwareSerial mhzSerial(12, 14); // RX = GPIO12, TX = GPIO14
byte cmdReadCO2[] = {0xFF, 0x01, 0x86, 0, 0, 0, 0, 0, 0x79};
bool readMHZ19B(int &ppm, int &tempC) {
while (mhzSerial.available()) mhzSerial.read();
mhzSerial.write(cmdReadCO2, 9);
uint8_t resp[9];
int i = 0;
uint32_t start = millis();
while (millis() - start < 200) {
if (mhzSerial.available()) {
resp[i++] = mhzSerial.read();
if (i == 9) break;
}
}
if (i != 9) return false;
if (resp[0] != 0xFF || resp[1] != 0x86) return false;
uint8_t sum = 0;
for (int k = 1; k < 8; k++) sum += resp[k];
sum = 0xFF - sum + 1;
if (sum != resp[8]) return false;
ppm = resp[2] * 256 + resp[3];
tempC = resp[4] - 40;
return true;
}
void setup() {
Serial.begin(115200);
delay(200);
Serial.println("\nMH-Z19B Test");
mhzSerial.begin(9600);
Serial.println("Sensor heizt auf (ca. 3 Minuten)...");
}
void loop() {
int ppm, t;
if (readMHZ19B(ppm, t)) {
Serial.print("CO2: ");
Serial.print(ppm);
Serial.print(" ppm, T-Sensor: ");
Serial.print(t);
Serial.println(" °C");
} else {
Serial.println("Fehler beim Lesen (noch am Aufwärmen?)");
}
delay(2000);
}
18:10:07.806 -> CO2: 674 ppm, T-Sensor: 24 °C
18:10:09.844 -> CO2: 675 ppm, T-Sensor: 24 °C
==== SDS011 ====
#include
SoftwareSerial sdsSerial(13, 15); // RX = GPIO13, TX = GPIO15
void setup() {
Serial.begin(115200);
delay(200);
Serial.println("\nSDS011 Test");
sdsSerial.begin(9600);
}
bool readSDS011(float &pm25, float &pm10) {
uint8_t buf[10];
int idx = 0;
uint32_t start = millis();
while (millis() - start < 2000) {
if (sdsSerial.available()) {
uint8_t b = sdsSerial.read();
if (idx == 0 && b != 0xAA) continue;
buf[idx++] = b;
if (idx == 10) {
if (buf[0] == 0xAA && buf[1] == 0xC0 && buf[9] == 0xAB) {
pm25 = (buf[2] + 256 * buf[3]) / 10.0;
pm10 = (buf[4] + 256 * buf[5]) / 10.0;
return true;
} else {
idx = 0;
}
}
}
}
return false;
}
void loop() {
float pm25, pm10;
if (readSDS011(pm25, pm10)) {
Serial.print("PM2.5: ");
Serial.print(pm25);
Serial.print(" µg/m³, PM10: ");
Serial.print(pm10);
Serial.println(" µg/m³");
} else {
Serial.println("Kein gültiges SDS011 Paket empfangen.");
}
delay(2000);
}
18:29:09.513 -> PM2.5: 4.60 µg/m³, PM10: 8.10 µg/m³
18:29:11.513 -> PM2.5: 4.60 µg/m³, PM10: 8.00 µg/m³
==== Alle drei Sensoren ====
#include
#include
#include
// BME280 an I2C: SDA = GPIO4 (D2), SCL = GPIO5 (D1)
#define BME280_ADDRESS 0x76
Adafruit_BME280 bme;
// MH-Z19B an GPIO12/14
SoftwareSerial mhzSerial(12, 14); // RX = 12, TX = 14
byte cmdReadCO2[] = {0xFF, 0x01, 0x86, 0, 0, 0, 0, 0, 0x79};
// SDS011 an GPIO13/15
SoftwareSerial sdsSerial(13, 15); // RX = 13, TX = 15
byte sds011_sleep[] = {0xAA, 0xB4, 0x06, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0x05, 0xAB};
byte sds011_wakeup[] = {0xAA, 0xB4, 0x06, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0x06, 0xAB};
// ---- Hilfsfunktionen ----
bool readMHZ19B(int &ppm, int &tempC) {
while (mhzSerial.available()) mhzSerial.read();
mhzSerial.write(cmdReadCO2, 9);
uint8_t resp[9];
int i = 0;
uint32_t start = millis();
while (millis() - start < 200) {
if (mhzSerial.available()) {
resp[i++] = mhzSerial.read();
if (i == 9) break;
}
}
if (i != 9) return false;
if (resp[0] != 0xFF || resp[1] != 0x86) return false;
uint8_t sum = 0;
for (int k = 1; k < 8; k++) sum += resp[k];
sum = 0xFF - sum + 1;
if (sum != resp[8]) return false;
ppm = resp[2] * 256 + resp[3];
tempC = resp[4] - 40;
return true;
}
bool readSDS011(float &pm25, float &pm10) {
uint8_t buf[10];
int idx = 0;
uint32_t start = millis();
while (millis() - start < 2000) {
if (sdsSerial.available()) {
uint8_t b = sdsSerial.read();
if (idx == 0 && b != 0xAA) continue;
buf[idx++] = b;
if (idx == 10) {
if (buf[0] == 0xAA && buf[1] == 0xC0 && buf[9] == 0xAB) {
pm25 = (buf[2] + 256 * buf[3]) / 10.0;
pm10 = (buf[4] + 256 * buf[5]) / 10.0;
return true;
} else {
idx = 0;
}
}
}
}
return false;
}
void setSDS011Sleep(bool sleep) {
if (sleep) {
sdsSerial.write(sds011_sleep, sizeof(sds011_sleep));
} else {
sdsSerial.write(sds011_wakeup, sizeof(sds011_wakeup));
}
delay(100);
}
// ---- Setup & Loop ----
void setup() {
Serial.begin(115200);
delay(200);
Serial.println("\nGesamttest: BME280 + MH-Z19B + SDS011");
// BME280
Wire.begin(4, 5); // SDA, SCL
if (!bme.begin(BME280_ADDRESS)) {
Serial.println("BME280 nicht gefunden!");
while (1) delay(100);
}
Serial.println("BME280 OK.");
// MH-Z19B
mhzSerial.begin(9600);
Serial.println("MH-Z19B UART gestartet (9600 Baud).");
// SDS011
sdsSerial.begin(9600);
setSDS011Sleep(false);
Serial.println("SDS011 aufgeweckt, Lüfter sollte laufen.");
}
void loop() {
Serial.println("\n--- neuer Messzyklus ---");
// BME280
bme.takeForcedMeasurement();
float t = bme.readTemperature();
float h = bme.readHumidity();
float p = bme.readPressure() / 100.0;
Serial.print("BME280: ");
Serial.print(t); Serial.print(" °C, ");
Serial.print(h); Serial.print(" %, ");
Serial.print(p); Serial.println(" hPa");
// MH-Z19B
int ppm, tco2;
if (readMHZ19B(ppm, tco2)) {
Serial.print("MH-Z19B: ");
Serial.print(ppm); Serial.print(" ppm, ");
Serial.print(tco2); Serial.println(" °C (Sensorsensor)");
} else {
Serial.println("MH-Z19B: kein gültiges Paket.");
}
// SDS011
float pm25, pm10;
if (readSDS011(pm25, pm10)) {
Serial.print("SDS011: PM2.5=");
Serial.print(pm25);
Serial.print(" µg/m³, PM10=");
Serial.print(pm10);
Serial.println(" µg/m³");
} else {
Serial.println("SDS011: kein gültiges Paket.");
}
delay(10000);
}
18:33:44.196 -> --- neuer Messzyklus ---
18:33:44.196 -> BME280: 21.54 °C, 37.46 %, 1008.72 hPa
18:33:44.259 -> MH-Z19B: 673 ppm, 22 °C (Sensorsensor)
18:33:44.259 -> SDS011: PM2.5=4.20 µg/m³, PM10=7.20 µg/m³