Sensors:
MH-Z19
MH-Z19 Pinout Cable
Pin |
Function |
1 |
HD |
2 |
Analog Output Vo |
3 |
Negative Pole(GND) |
4 |
Positive Pole(Vin) |
5 |
UART(RXD)TTL Level data input |
6 |
UART(TXD)TTL Level data output |
7 |
PWM |
BME 280
AZDelivery 5V RGB LED Ring WS2812B
AZDelivery 0,96 Zoll OLED Display I2C
Boards:
ESP-32 Dev Kit C V2
Sketch (click to download) – ESP-32 Dev Kit C V2, Arduino 2.0-beta, WebServer, Adafruit NeoPixel, BME 280, MH-Z19
/* CO2-Messung mit dem Sensor MH-Z19B
* per Pulsweitenmodulation (PWM)
*
* Anzeige der Messwerte als CO2-Ampel
*
*/
// NodeMCU Wroom -> Board: DOIT ESP32 DEVKIT V1 https://dl.espressif.com/dl/package_esp32_index.json (ESP32 by Espressif Systems)
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <WiFiClient.h>
#include <WebServer.h>
String float2string(float f);
const char* ssid = "MyWLAN";
const char* password = "MyPAss";
WebServer server(80);
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme; // I2C
#include <Adafruit_NeoPixel.h>
int leds = 12; //Anzahl der LEDs
int ledPin = 4; //
//NeoPixel als "pixels" instanziieren
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(leds, ledPin, NEO_GRB + NEO_KHZ800);
#define red 0xFF0000
#define green 0x00FF00
#define yellow 0XFFFF00
#define orange 0XFFA500
#define blue 0x0000FF
#define black 0x000000
#define magenta 0xFF00FF
/* ------------------------------------------------------------
* MH-Z19B
* ------------------------------------------------------------ */
#include <Arduino.h>
#include <MHZ19.h>
// Nutzung der Schnittstelle UART2 an den Default-Pins RX 16, TX 17
//#define RX2 16
//#define TX2 17
#define RX2 16
#define TX2 17
#define MHZ19_BAUDRATE 9600
#define MHZ19_PROTOCOL SERIAL_8N1
#define MHZ19_RANGE 5000 // Obergrenze des Messbereichs des Sensors
#define MHZ19_PWM_PIN 14
#define INTERVALL 997 // Standard: 1004
MHZ19 mhz19b; // Sensor-Objekt
void setup(void) {
int i;
bool error = false;
char mhz19_version[4];
pinMode (ledPin, OUTPUT);
pixels.begin();
pixels.setBrightness(100); //Helligkeit: 0 (aus) - 255
// Übertragungsrate zum seriellen Monitor setzen
Serial.begin(MHZ19_BAUDRATE);
Serial2.begin(MHZ19_BAUDRATE, MHZ19_PROTOCOL, RX2, TX2);
mhz19b.begin(Serial2); // MH-Z19B-Sensor eine Schnittstelle zuweisen
// ein paar Daten der Sensor-Konfiguration ausgeben
mhz19b.getVersion(mhz19_version);
Serial.print("--------------------\nMH-Z19B Firmware Version: ");
for(i = 0; i < 4; i++) {
Serial.print(mhz19_version[i]);
if(i == 1)
Serial.print(".");
}
Serial.print("\nMH-Z19B Messbereich: ");
Serial.println(mhz19b.getRange());
mhz19b.autoCalibration(true);
mhz19b.calibrate();
Serial.print("MH-Z19B Autokalibrierung (ABC): ");
mhz19b.getABC() ? Serial.println("AN") : Serial.println("AUS");
Serial.println("--------------------");
// im Fehlerfall Programm nicht fortsetzen (leere Dauerschleife))
if(error) {
for(;;);
}
//testscrolltext();
// Connect to WiFi network
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.print("\n\r \n\rWorking to connect");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
server.on("/", handle_root);
server.on("/temp", [](){
server.send(200, "text/plain", float2string(bme.readTemperature()));
});
server.on("/hum", [](){
server.send(200, "text/plain", float2string(bme.readHumidity()));
});
server.on("/press", [](){
server.send(200, "text/plain", float2string(bme.readPressure()/100.0));
});
server.on("/allvalues", allvalues);
server.begin();
Serial.println("HTTP server started");
if (!bme.begin(0x76)) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
}
void loop() {
int ppm;
// Verwendung der einfachen Formel; allerdings wird - sofern
// bekannt - mit dem Wert von INTERVALL die tatsächliche
// Intervalllänge des Sensors berücksichtigt
ppm = (pulseIn(MHZ19_PWM_PIN, HIGH, 2200000UL) / 1000 - 2) * MHZ19_RANGE / (INTERVALL - 4);
// Ausgabe des CO2-Werts in ppm im seriellen Monitor
Serial.print("PPM CO2: ");
Serial.println(ppm);
// je nach Wert die passende LED an- und die anderen
// beiden ausschalten
if (ppm < 800) {
for (int i = 0; i < 12; i++) {
pixels.setPixelColor(i, green);
pixels.show();
//delay(200);
}
Serial.print("Ampel green\n");
}
else if ( (ppm <= 800) && (ppm <= 1000) ) {
for (int i = 0; i < 12; i++) {
pixels.setPixelColor(i, yellow);
pixels.show();
//delay(200);
}
Serial.print("Ampel gelb\n");
}
else if ( (ppm <= 1000) && (ppm <= 1400) ) {
for (int i = 0; i < 12; i++) {
pixels.setPixelColor(i, orange);
pixels.show();
//delay(500);
}
Serial.print("Ampel orange\n");
}
else if (ppm > 1400) {
for (int i = 0; i < 12; i++) {
pixels.setPixelColor(i, red);
pixels.show();
//delay(500);
}
Serial.print("Ampel rot *** ALARM ***\n");
}
server.handleClient();
delay(2500); // vor der nächsten Messung etwas warten
}
void handle_root() {
Serial.print("\n\r \n\rHandle root");
int ppm;
// Verwendung der einfachen Formel; allerdings wird - sofern
// bekannt - mit dem Wert von INTERVALL die tatsächliche
// Intervalllänge des Sensors berücksichtigt
ppm = (pulseIn(MHZ19_PWM_PIN, HIGH, 2200000UL) / 1000 - 2) * MHZ19_RANGE / (INTERVALL - 4);
// Ausgabe des CO2-Werts in ppm im seriellen Monitor
Serial.print("PPM CO2: ");
Serial.println(ppm);
String reply = "";
reply += "Temperature: " + float2string(bme.readTemperature()) + " *C\n";
reply += "Humidity: " + float2string(bme.readHumidity()) + " %\n";
reply += "Pressure: " + float2string(bme.readPressure()/100.0) + " hPa\n";
reply += "PPM CO2: " + float2string(ppm);
server.send(200, "text/plain", reply);
delay(100);
}
void allvalues() {
Serial.print("\n\r \n\rHandle root");
int ppm;
// Verwendung der einfachen Formel; allerdings wird - sofern
// bekannt - mit dem Wert von INTERVALL die tatsächliche
// Intervalllänge des Sensors berücksichtigt
ppm = (pulseIn(MHZ19_PWM_PIN, HIGH, 2200000UL) / 1000 - 2) * MHZ19_RANGE / (INTERVALL - 4);
// Ausgabe des CO2-Werts in ppm im seriellen Monitor
Serial.print("PPM CO2: ");
Serial.println(ppm);
String reply = "";
reply += float2string(bme.readTemperature())+"\n";
reply += float2string(bme.readHumidity())+"\n";
reply += float2string(bme.readPressure()/100.0)+"\n";
reply += float2string(ppm);
server.send(200, "text/plain", reply);
delay(100);
}
String float2string(float f) {
int ipart = (int) f;
int fpart = ((int)(fabs(f)*10)) % 10;
return String(ipart) + "." + String(fpart);
}
Wiring- ESP-32 Dev Kit C V2, Arduino 2.0-beta, WebServer, Adafruit NeoPixel, BME 280, MH-Z19
ESP-32 Dev Kit |
BME 280 |
GPIO22 |
SCL |
GPIO21 |
SDA |
GND |
GND |
+5V |
VIN |
ESP-32 Dev Kit |
MH-Z19 |
GND |
GND |
+5V |
VIN |
GPIO14 |
PWM |
GPIO16 |
RX |
GPIO17 |
TX |
ESP-32 Dev Kit |
RGB LED Ring |
GND |
GND |
+5V |
VCC |
GPIO4 |
IN |
ESP-32 Dev Kit |
Oled Display |
GND |
GND |
+5V |
VCC |
GPIO22 |
SCL |
GPIO21 |
SDA |
Einiges übernommer von
https://unsinnsbasis.de/.
Ampel – von verbrauchter bis unverbrauchter Luft.