Kohlendioxid Warngerät mit Arduino selbst erstellen

Dieses Projekt besteht aus drei Teile und soll die CO2 Belastung messen und Anzeigen, so das ein Zimmer rechtzeitig gelüftet werden kann.


Hier im ersten Teil, wird gezeigt, wie mit einem Kohlendioxid Co2 Sensor SCD30 von Sensirion an einem Arduino Nano, ein Warngerät erstellt wird.

Ein CO2-Messgerät ist ein Messgerät mit einem Gassensor, das zur Anzeige des Gehalts an Kohlenstoffdioxid (abgekürzt CO2) in der Luft dient. CO2-Messgeräte zeigen die Höhe des Kohlenstoffdioxidgehalts meist in der Hilfsmaßeinheit Parts per million oder/und in Form einer Ampel mit verschiedenen Farben an. In Abgrenzung hierzu dienen CO2-Melder nur zur Signalisierung des Überschreitens eines vorgegebenen Schwellenwerts

Wikipedia


In dieser Lösung ist zu sehen, wie der Testaufbau mit farbig leuchtenden Licht anzeigt, wie gut die Luftqualität im jeweiligen Raum ist.
Zu dem ist zu sehen, was vorab unternommen werden muss, um den Sensor optimal zu Kalibrieren.
Da die CO2-Werte jährlich steigen, kann hier der aktuelle ppm-Wert abgelesen werden: https://gml.noaa.gov

Benötigt wird:
Sensirion SCD30
Arduino Nano
Wenn das im Teil 3 vorgestellte Gehäuse verwendet wird ein NeoPixel Ring mit 8 LED vom Typ WS2812b

Datenblätter:
SCD30 Datenblatt
NeoPixel Datasheet

Arduino IDE Quellcode:

// Verfügbare Einstellungen für den SCD30
#include <Adafruit_SCD30.h>
#include <Adafruit_NeoPixel.h>

Adafruit_SCD30  scd30;
#define PIN 9 // Pin des WS2812b 
 Adafruit_NeoPixel strip = Adafruit_NeoPixel(8, PIN, NEO_GRB + NEO_KHZ800);
 int NUM_LEDS = strip.numPixels();
  
void setup(void) {
  strip.begin();
  strip.setBrightness(10); //Einstellung Helligkeit
  strip.show(); 

  Serial.begin(115200);
  while (!Serial) delay(10);     // will pause Zero, Leonardo, etc until serial console opens

  Serial.println("Adafruit SCD30 Sensor adjustment test!");

  // Try to initialize!
  if (!scd30.begin()) {
    Serial.println("Failed to find SCD30 chip");
    while (1) { delay(10); }
  }
  Serial.println("SCD30 Found!");

  /***
   * Der folgende Code zeigt die aktuellen Einstellungen für jede der
   * Einstellungen, die geändert werden können. Um zu sehen, wie sie funktionieren, deaktivieren Sie die Einstellung
   * Code über einer Statusmeldung und Anpassen des Werts
   *
   * **Note:** Da die automatische Selbstkalibrierung oder die erzwungene Neukalibrierung immer wieder
   * den Referenzwert überschreibt, sollten Sie nur das eine oder das andere setzen
  ***/


  /*** Passen Sie die Geschwindigkeit, mit der Messungen durchgeführt werden, von 2-1800 Sekunden an */
  // if (!scd30.setMeasurementInterval(5)) {
  //   Serial.println("Failed to set measurement interval");
  //   while(1){ delay(10);}
  // }
  Serial.print("Measurement interval: ");
  Serial.print(scd30.getMeasurementInterval());
  Serial.println(" seconds");


  /*** Starten Sie die kontinuierliche Messung mit einem Druckversatz von 700 bis 1400 Millibar neu.
   * Wenn Sie kein Argument anführen oder den Offset auf 0 setzen, wird die Offsetkorrektur deaktiviert
   */
  // if (!scd30.startContinuousMeasurement(15)){
  //   Serial.println("Failed to set ambient pressure offset");
  //   while(1){ delay(10);}
  // }
  Serial.print("Ambient pressure offset: ");
  Serial.print(scd30.getAmbientPressureOffset());
  Serial.println(" mBar");


  /*** Legen Sie einen Höhenversatz in Metern über dem Meeresspiegel fest
   * Offset-Wert, der im nichtflüchtigen Speicher von SCD30 gespeichert ist.
   * Wenn Sie einen Höhenversatz festlegen, wird jeder Druckversatz überschrieben.
   */
  // if (!scd30.setAltitudeOffset(110)){
  //   Serial.println("Failed to set altitude offset");
  //   while(1){ delay(10);}
  // }
  Serial.print("Altitude offset: ");
  Serial.print(scd30.getAltitudeOffset());
  Serial.println(" meters");


  /*** Stellen Sie einen Temperaturversatz in Hundertste Grad Celsius ein.
   * Offset-Wert, der im nichtflüchtigen Speicher von SCD30 gespeichert ist.
   */
  // if (!scd30.setTemperatureOffset(1984)){ // 19.84 degrees celcius
  //   Serial.println("Failed to set temperature offset");
  //   while(1){ delay(10);}
  // }
  Serial.print("Temperature offset: ");
  Serial.print((float)scd30.getTemperatureOffset()/100.0);
  Serial.println(" degrees C");


  /*** Zwingen Sie den Sensor, mit dem angegebenen Referenzwert von 400-2000 ppm neu zu kalibrieren. Durch das Schreiben einer Neukalibrierungsreferenz werden alle vorherigen Selbstkalibrierungswerte überschrieben.
   * Reference value stored in non-volatile memory of SCD30.
   */
  // if (!scd30.forceRecalibrationWithReference(400)){
  //   Serial.println("Failed to force recalibration with reference");
  //   while(1) { delay(10); }
  // }
  Serial.print("Forced Recalibration reference: ");
  Serial.print(scd30.getForcedCalibrationReference());
  Serial.println(" ppm");


  /*** Aktivieren oder deaktivieren Sie die automatische Selbstkalibrierung (ASC).    
   *  Parameter, der im nichtflüchtigen Speicher von SCD30 gespeichert ist.   
   *  Durch aktivierende Selbstkalibrierung werden alle zuvor festgelegten erzwungenen Kalibrierungswerte überschrieben
   *  ASC benötigt Dauerbetrieb mit mindestens 1 Stunde 400ppm CO2-Konzentration täglich.
   */
  // if (!scd30.selfCalibrationEnabled(true)){
  //   Serial.println("Failed to enable or disable self calibration");
  //   while(1) { delay(10); }
  // }
  if (scd30.selfCalibrationEnabled()) {
    Serial.print("Self calibration enabled");
  } else {
    Serial.print("Self calibration disabled");
  }

  Serial.println("\n\n");
}

void loop() {
  if (scd30.dataReady()) {
    
    if (!scd30.read()){ 
      Serial.println("Error reading sensor data"); 
      return; 
    }

    Serial.print("Temperature: ");
    Serial.print(scd30.temperature);
    Serial.println(" degrees C");
    
    Serial.print("Relative Humidity: ");
    Serial.print(scd30.relative_humidity);
    Serial.println(" %");
    
    Serial.print("CO2: ");
    Serial.print(scd30.CO2, 3);
    Serial.println(" ppm");
    Serial.println("");
  }
if (scd30.CO2<800){ 
setNeoPixel(0, 255, 0);
}
else
{
  if (scd30.CO2<1200){ 
setNeoPixel(255, 255, 0);
}
else
{ 
setNeoPixel(255, 0, 0);
}
}

  delay(100);
}
void setNeoPixel(int r, int g, int b){
    // Walk through each Neopixel
    for(int i=0; i<NUM_LEDS; i++) { // For each pixel...
      // pixels.Color() takes RGB values, from 0,0,0 up to 255,255,255
      strip.setPixelColor(i, strip.Color(r, g, b));
      strip.show();   // Send the updated pixel colors to the hardware.
    } 
  }

Info:
Vorherige Tests mit einem CO2-Sensor MH-Z19b, bei denen keine zuverlässigen Daten ausgeben wurden, haben sich nach Internet Recherchen, wohl als Fake-Sensoren entpuppt. Die Original Sensoren vom Hersteller Winsen, sind bisweilen optisch an der Platinenfarbe und dem Gehäuse zu erkennen.

Nähere Details hier auf dieser Niederländischen Seite: https://revspace.nl/MH-Z19B
Ich habe den Online Händler Amazon davon unterrichtet. Die Ware wurde zurück genommen und erstattet.

Der Teil 2 und der Teil 3 dieser Reihe sind hier zu finden:
Kohlendioxid CO2 Warngerät – Teil2. Jetzt erweitert mit Display und Alarm
Kohlendiocid CO2 Warngerät – Teil 3. Wie das Gehäuse mit AutoDesk Fusion 360 erstellt wird


Update:
Habe im Frühjahr 2024 das Modul CO2-Sensor MH-Z19c von Winsen mit diesem Sketch getestet und es hat gute verwendbare Werte geliefert:

// Pinbelegung bei einem Arduino Uno: 5V, GND, PWM=Pin6
int DataPin = 6;

// Definiere den Messbereich des Sensors in ppm
int ppmrange = 5000;

// Variablen zur Speicherung der Messwerte
unsigned long pwmtime;
int PPM = 0;
float pulsepercent=0;

void setup() {
  // Setze den Datenpin als Eingang
  pinMode(DataPin,  INPUT);

  // Starte die serielle Kommunikation mit einer Baudrate von 115200
  Serial.begin(115200);
}

void loop() {
  // Lese das PWM-Signal vom Sensor und teile es durch 1000, um es in Millisekunden umzurechnen
  pwmtime = pulseIn(DataPin,  HIGH,  2000000)  / 1000;

  // Berechne den Prozentsatz des PWM-Signals
  pulsepercent = pwmtime / 1004.0;

  // Berechne die CO2-Konzentration in ppm
  PPM = ppmrange * pulsepercent;

  // Gebe die CO2-Konzentration auf der seriellen Schnittstelle aus
  Serial.print("CO2 Konzentration in der Luft in PPM: ");
  Serial.println(PPM);

  // Warte 5 Sekunden bis zur nächsten Messung
  delay(5000);
}

Der MH-Z19C ist ein Infrarot CO2 Gasmessmodul, das auf dem Prinzip der nichtdispersiven Infrarottechnik (NDIR) basiert.
Es misst die Konzentration von CO2 in der Luft durch die Absorption von infrarotem Licht. Je mehr CO2 in der Luft vorhanden ist, desto mehr IR-Strahlung wird absorbiert und entsprechend weniger erreicht den Detektor.

Herstellerdatenblatt: winsen-sensor.com

, ,