CO2-Ampel

Entwicklung einer CO2-Ampel um die Gefahr einer CoVid-Ansteckungen in geschlossenen Räumen zu minimieren – Stand 20.9.2020 – Projektversion 0.32b.
Für Fehler wird nicht gehaftet ! Insbesondere solange wir nicht Version 1.0 erreicht haben.
Das ganze wird weiterentwickelt. Besuchen Sie uns bald wieder.

Was hat Co2 mit CoVid zu tun?

Durch das Ausatmen wird CO2 an den Raum abgegeben.
Ein CoVid Infizierte (und noch nicht erkrankte) Person atmet auch Aerosole aus welche durch Viren belastet sein könnten.

Je höher somit der CO2-Gehalt im Raum ist desto höher ist auch eine eventuelle Virenbelastung durch einen eventuell im Raum befindlichen infizierten.

Der CO2-Gehalt zeigt ausserdem die Qualität der Luft im Raum an … ein niedriger CO2-Gehalt bedeutet eine gute Qualität und somit (im Beispiel Schule) bessere Konzentration der Schüler.
Es hilft somit beim lernen.

Die CO2-Ampeln im Handel (zertifiziert, geeicht etc..) kosten aber, je nach Qualität, um die 200 Euro. (unter 100 Euro ist die Qualität eher als zweifelhaft anzunehmen – Stand September 2020)
Um die Schüler, Lehrer sowie in folge natürlich die Familien im Hintergrund aber vor einer Ansteckung in der Schule bestmöglich zu schützen habe ich ein einfaches, effektives und gleichzeitig sehr kostengünstiges CO2-„Messgerät“ entwickelt.

Das Ziel war die Kosten so gering wie möglich zu halten und der Zusammenbau so einfach wie möglich zu gestalten um es sogar als Projektarbeit im Werkunterricht bauen zu können.
Der Lehrer baut für die Klasse, die Schüler für Zuhause.

In dem Schulbeispiel ist ja keine genaue Messung nötig sondern eine Abschätzung der Qualität der Luft um somit den optimalen Zeitpunkt für das lüften zu finden.
Somit den Lehrer in der Abschätzung der Luftqualität zu unterstützen.
Nicht mehr und nicht weniger.

Man benötigt:
– CO2-Sensor. MH-Z19b (16-26 Euro)
Einkaufen bei Reichelt.at
– Je nach Ausführung sind dann auch „Header“ nötig
Einkaufen bei semaf.at
– eine Arduino-kompatible Elektronik – zb. nodemcu ESP8266 (V2)
Produktinfo von Joy-it
– eine RGB-LED um die Überschreitung der Grenzwerte anzuzeigen. (1-2 Euro)
Einkaufen bei AZ-Delivery
– 9 Kabeln female-female
Einkaufen bei Conrad

Optional:
– OLED-Bildschirm (SSD 1306-Kompatibel)
Einkaufen bei AZ-Delivery
– weitere 4 Kabeln female-female

Ich hab keine Vorteile bei den Händlern… bekomme keine Provision oder sonstiges. Daher hab ich auch verschiedene Händler bzw. Hersteller genommen – es kann jeder selbst entscheiden wo er kaufen will… Absichtlich auch keine exotischen Shops verlinkt…
Denkt daran: Nach Möglichkeit fahr nicht fort – kauf im Ort.

Dazu einen Computer um das Programm auf die Elektronik zu übertragen.

Je nach gekaufter Menge und Ort der Bestellung ist mit Hardwarekosten von etwa 40 Euro zu rechnen. (Direktimport aus China etwa 20 Euro)

Ich muss darauf hinweisen das ich selbst nur wenige Tage testen konnte und nicht garantieren kann das die Sensordaten über lange Zeit stabil bleiben.
Meine Tests ergaben innerhalb 3 Tagen gute Messwerte die ich mit einem Profigerät verglichen hatte.
Es ist daher zu empfehlen das gebaute Gerät des öfteren mit einem geeichten Gerät zu testen und zu vergleichen.

Die Elektronik wird folgendermaßen zusammengebaut.

Manche MH-z189b Sensoren haben keine Steckerleiste.
Mit etwas Geschick und einem Lötkolben ist das auch keine Hexerei.
Je nach Altersklasse eventuell beim bestellen darauf achten.
Kann aber auch ein Teil der Werkübung sein.

Ihnen Gefällt das Projekt?
Dann unterstützen Sie uns doch mit einer Spende:

Und die Software dazu:

//################################################
//#
//# CO2-Ampel gegen Virenbelastete Luft in
//# Innenräumen zb. Klassenräumen in Schulen
//#
//# Bei Rot sollte spätestens gelüftet werden.
//#
//# V.: 0.321 (25.9.2020)
//#
//################################################
//#
//# (c) 2020 Robert Gehringer
//# Donation-Ware = gefällt es euch dann spendet eine kleinigekit - Danke.
//# Ihr habt Verbesserungen? nur her damit.
//# http://www.schwarzarbeiter.info/co2-ampel/
//#
//################################################
//#
//# 0.32: Wifi + Webserver hinzufügen
//# 0.31: Grundfunktion 
//# 0.31: Farben der LED verbessert
//# Todo:
//# API-Übertragung an HTML-Script auf einem Server 
//# und / oder MSQL-Speicherung der Daten


#include <ESP8266WiFi.h>
#include <SoftwareSerial.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

#include <brzo_i2c.h> // Only needed for Arduino 1.6.5 and earlier
#include "SSD1306Brzo.h"
#include "SH1106Brzo.h"

#include <MHZ.h>
#include <RGBLED.h>
RGBLED rgbLed(4,5,16,COMMON_CATHODE);


//################################################
//#
//#  Hier die WLAN-Zugangsdaten eintragen
//#
//################################################

#ifndef STASSID
  #define STASSID "your-ssid"
  #define STAPSK  "your-password"
#endif

const char* ssid = STASSID;
const char* password = STAPSK;

// pin for pwm reading
#define CO2_IN 15

// pin for uart reading
#define MH_Z19_RX D7  // D7
#define MH_Z19_TX D6  // D6

MHZ co2(MH_Z19_RX, MH_Z19_TX, CO2_IN, MHZ19B);



// Grenzwerte
int green = 600; // 600
int yellow = 800; // 800
int red = 1000;  // 1000

String CO2text;
int co2_Wert;
int temperature;


// Display
SSD1306Brzo display(0x3c, D3, D4);

// Webserver
ESP8266WebServer server(80);

//################################################
//#
//#  Webserver Ausgabe
//#
//################################################

void handleRoot() {
  // Webserverausgabe
  String Message = "";
  Message += "CO2-Ampel\n";
  Message += "\n";
  Message += "Aktuelle Laufzeit: "+String (millis() / 1000 / 60 ) + " Minuten\n";
  Message += "\n";
  Message += "Aktueller CO2-Wert:"+String(co2_Wert)+"\n";
  Message += "Temp: " + String(temperature);
  Message += char(176);
  Message += "C\n";
  Message += "\n";
  Message += "Weitere Infos unter:\n";
  Message += "http://www.schwarzarbeiter.info/co2-ampel/\n";
  Message += "\n";
  Message += "\n";
  Message += "\n";
  Message += "Press reload in about 5 seconds...\n";

  
  server.send(200, "text/plain", Message );
}

void setup() {

  display.init();
  display.flipScreenVertically();
  display.setFont(ArialMT_Plain_16);

  Serial.begin(9600);
    delay(100);
  Serial.println("");
  Serial.println("Start");
  
  pinMode(CO2_IN, INPUT);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  if (WiFi.waitForConnectResult() != WL_CONNECTED) {
//    Serial.println("WiFi Connect Failed! Rebooting...");
//    display.clear();
//    display.display();
//    display.drawString(0, 26, "WiFi Connect Failed! Rebooting...");
//    display.display();
        
//    delay(1000);
//    ESP.restart();
  } else {
    Serial.print("WiFi Connected: ");
    Serial.println( WiFi.localIP());
    display.clear();
    display.display();
    display.drawString(0, 26, "WiFi Connected: "+ WiFi.localIP());
    display.display();
    delay(2000);
  }


  delay(100);
  Serial.println("MHZ 19B");


  server.on("/", handleRoot);
  server.on("/inline", []() {
    server.send(200, "text/plain", "this works as well" );
  });
  server.begin();


  // enable debug to get addition information
  //co2.setDebug(true);

  display.setFont(ArialMT_Plain_16);


  if (co2.isPreHeating()) {
    Serial.print("Preheating");
    while (co2.isPreHeating()) {
      Serial.print(".");

      display.clear();
      display.display();
      rgbLed.writeRGB(0,0,0);
      display.drawString(0, 26, "Aufwärmen " + String(181 - millis() / 1000));
      display.display();
      delay(1000);

      display.clear();
      display.display();
      // Grün
      rgbLed.writeRGB(0,255,0);
      display.drawString(0, 26, " Aufwärmen " + String(181 - millis() / 1000));
      display.display();
      delay(1000);

      display.clear();
      display.display();
      rgbLed.writeRGB(0,0,0);
      
      display.drawString(0, 26, "Aufwärmen " + String(181 - millis() / 1000));
      display.display();
      delay(1000);

      display.clear();
      display.display();
      // Gelb
      rgbLed.writeRGB(245,250,0);
      display.drawString(0, 26, "   Aufwärmen " + String(181 - millis() / 1000));
      display.display();
      delay(1000);

      display.clear();
      display.display();
      rgbLed.writeRGB(0,0,0);
      display.drawString(0, 26, "  Aufwärmen " + String(181 - millis() / 1000));
      display.display();
      delay(1000);

      display.clear();
      display.display();
      // orange
      rgbLed.writeRGB(255,64,0);
      display.drawString(0, 26, " Aufwärmen " + String(180 - millis() / 1000));
      display.display();
      delay(1000);

      display.clear();
      display.display();
      rgbLed.writeRGB(0,0,0);
      display.drawString(0, 26, " Aufwärmen " + String(181 - millis() / 1000));
      display.display();
      delay(1000);

      display.clear();
      display.display();
      // Rot
      rgbLed.writeRGB(255,0,0);
      display.drawString(0, 26, "  Aufwärmen " + String(181 - millis() / 1000));
      display.display();
      delay(1000);


    }
    Serial.println();
  }
}


//################################################
//#
//#  die eigentliche Schleife
//#
//################################################

void loop() {

  int co2_Wert_UART = co2.readCO2UART();
  co2_Wert = co2.readCO2PWM();

  temperature = co2.getLastTemperature();

//################################################
//#
//#  Werte ausgeben auf Serial-Monitor + auf Display
//#
//################################################

//#  Serial-Monitor

  Serial.print("\n----- Time from start: ");
  Serial.print(millis() / 1000);
  Serial.println(" s");

  Serial.println("");
  
  Serial.print("CO2: ");
  if (co2_Wert > 0) {
    Serial.print(co2_Wert);
  } else {
    Serial.print("n/a");
  }
  Serial.println(" ppm");
  
  Serial.print("Temp: ");

  if (temperature > 0) {
    Serial.print(temperature);
    Serial.println("°C");
  } else {
    Serial.print("n/a");
  }
  Serial.print("IP: ");
  Serial.println( WiFi.localIP());


//#  Display

  display.clear();
  display.display();
  display.setFont(ArialMT_Plain_16);
  display.drawString(0, 8, "CO2: " + String(co2_Wert) + " ppm" ); //+" ppm Co2");
  display.drawString(0, 24, "Temp: " + String(temperature) + "°C" ); //+" ppm Co2");

  display.setFont(ArialMT_Plain_16);
  display.drawString(0, 48, WiFi.localIP().toString() );
  display.display();

  rgbLed.writeRGB(0,0,0);

//################################################
//#
//#  Ampelschaltung auf Grund des gemessenen Wert
//#
//################################################


  if (co2_Wert <= green)
  {
//# Grün
    Serial.println("Grün");
    rgbLed.writeRGB(0,255,0);
  }

//# Gelb  !
  if (co2_Wert > green && co2_Wert <= yellow)
  {
    Serial.println("Gelb");
    rgbLed.writeRGB(245,250,0);
  }

//# Orange !!!
if (co2_Wert > yellow && co2_Wert <= red)
  {
    Serial.println("Orange");
    rgbLed.writeRGB(255,64,0);
  }

//# Rot !!! !!! !!!
  if (co2_Wert > red)
  {
    Serial.println("Rot !!!!!!");
    rgbLed.writeRGB(255,0,0);
  }

//################################################
//#
//#  5 Sekunden Pause -> und dabei Webserver bedienen
//#
  Serial.println("\n------------------------------");
  for (int i = 0; i <= 50; i++) {
    server.handleClient();
    delay(100);
  }
//#
//################################################

}

Ich hab auch noch einen Monitor dazu programmiert.
Wer Lust hat die Werte direkt abzulesen, kann diesen noch dazu anschliessen.
(+ca. 7 Euro)

Ihnen Gefällt das Projekt?
Dann unterstützen Sie uns doch mit einer Spende:


Die Installation

… ist einfacher als man denkt.
Installiere die Arduino-IDE: Download (Mac, Windows, Linux)
Starte ein neues Projekt und kopiere den Quellcode rein.
Installiere die folgenden Bibliotheken (siehe Screenshot) + die RGBLED-Master von der AZ-Delivery-Webseite.
(einfach in das Arbeitsverzeichnis unter Library… Am MAC ist das: —/Dokumente/Arduino/libraries)

Passe nun den Code an deine Bedürfnisse an.
Insbesondere kann auch ein Webserver gestartet werden
Dazu sind die WLAN-Zugangsdaten einzutragen. (relativ weit oben im Quellcode)
Dann wird auch eine IP-Adresse ausgegeben unter der man den aktuellen Wert ablesen kann.
Restliche Änderungen nur wenn man weiss was man tut.

Schliesse das Mikorcontrollerboard per USB-Kabel (hohe Qualität und nicht länger als 1m) an den Computer und übertrage die Software.
Du kannst dabei mit dem „Seriellen Monitor“ auch schauen was den die Elektronik grad tut… stelle Baudrate 9600 ein und beobachte.

Der Sensor muss erst mal „aufwärmen“ und sollte dann nach 180 Sekunden die ersten Werte ausgehen.

Auf meinem MAC sieht das dann so aus:

Fenster weit geöffnet und Frischluft pur im Büro…

Ihnen Gefällt das Projekt?
Dann unterstützen Sie uns doch mit einer Spende:

Dazu noch ein 3D-Gehäuse.

Keine Schrauben nötig – ausgenommen man will den Monitor besser sichern kann man dies mit m2-Schrauben und Muttern erledigen

Elektronikteile vorsichtig in die vorgesehen Stellen einrasten lassen.
Ich habe an meinem MH-Z19-Sensor die Anschlüssen nach oben aufgelötet – andere Version ist noch in Planung.