Inhaltsverzeichnis

CO$_2$ – Kohlenstoffdioxid in der Luft

Kohlenstoffdioxid, auch Kohlendioxid oder CO$_2$

  1. farbloses, nicht brennbares und geruchloses Gas,
  2. schwerer als Luft
  3. natürlicher Bestandteile der Atmosphäre (neben Stickstoff N$_2$, Sauerstoff O$_2$ und den Edelgasen)
  4. wichtig für das Leben auf der Erde (Photosynthese)
  5. 6 CO$_2$ + 6 H$_2$O + Lichtenergie ⇌ C$_2$H$_{12}$O$_6$ + 6 O$_2$
  6. Treibhausgas: trägt wesentlich zur Erderwärmung bei
  7. Eine zu hohe Kohlenstoffdioxidkonzentration in Innenräumen führt zu Kopfschmerzen, Schläfrigkeit, Unaufmerksamkeit,

Entstehung von Kohlenstoffdioxid:

  1. Entsteht bei der Zellatmung
  2. Zerfall toter Organismen
  3. Vulkangas
  4. Verbrennung kohlenstoffhaltiger Energieträger (Holz, Kohle, Gas oder Öl)

Die CO2-Konzentration wird in parts per million (Anteile pro Million), kurz ppm angegeben.

CO2 Gehalt im ppm Beschreibung
400 - 800 Normalwert in der Außenluft
800 - 1.000 Normalwert in Innenräumen
1.000 - 1.400 Erhöhte Werte im Innenraum
1.400 – 2.000 Problematischer Wert
> 2.000 Gesundheitsgefahr

Messprinzip

Kohlendioxid führt Schwingungen aus. Die unsymmetrischen Schwingungen werden durch Infrarotlicht (1 bis 40 µm; Mikrometer = $10^{-6}$ m) angeregt. Die entsprechende Längenwelle des Lichtes wird dadurch absorbiert, dieses befindet sich bei 4.3 und 15.3 µm. Diese beiden Werte sind für CO$_2$ charakteristisch.

Messvorrichtung: Die Öffnungen am Gehäuse ermöglichen, das Luft durchströmen kann. Von der Infrarotlichtquelle wird durch das Gehäuse auf den Lichtdetektor am gegenüberliegenden Ende ein Lichtstrahl geschickt, wobei ein Filter, nur Licht einer für CO2 charakteristisches Wellenlänge durchlässt.

Die Menge des absorbierten Infrarotlichts ist proportional Konzentration von CO$_2$ im Gehäuse. Die Intensität des detektieren Lichtstrahls wird mit einer Referenz verglichen und daraus die CO$_2$-Konzentration in Teilen pro Million (ppm) berechnet.

Die Übermittlung des Messwertes vom Sensor zum Mikrocontroller erfolgt seriell. Die Baudrate (9600 Baud) gibt an, wie viele Pegelwechsel pro Sekunde möglich sind. Da pro Pegeländerung jeweils ein Bit übertragen wird, wird pro 1/9600 Sekunde ein Bit übertragen. Die Bits werden immer blockweise (8Bit = 1 Byte) übertragen und anschließend eine Pause gemacht, sonst könnte es zwischen Sender und Empfänger Problem in der Synchronisation geben. Die Pause sollte, um nicht mit einer Übertragung von lauter gleichen Bits verwechselt zu werden, mindestens 9 Bit lang sein. Außerdem wird zu Beginn eines Blockes ein Startbit gesendet und ein Stoppbit.

Zur Kommunikation gibt es zwei Leitungen: RX (Receiver, Empfänger) und TX (Transmitter, Sender). Dies sind über kreuz verkabelt. Tx –> Rx und Rx –> Tx, so dass die Kommunikation in beider Richtungen möglich ist.

Abfrage des Sensors (MH-Z16)

Datenblatt: mh-z16.pdf

Internetquellen:

Um den Sensor abzufragen, sendet man ihm einen Datenstring, bestehend aus 9 Byte zu. Wobei nur ein Byte (Byte Nr. 3) den eigentlichen Steuerbefehl enthält:

Befehl 0x86 To read CO2 concentration
Befehl 0x87 To calibrate Zero Point (ZERO)
Befehl 0x88 To calibrate Span Point (SPAN)
Befehl 0x79 To Turn ON/OFF self-calibration function
5000 ppm range: 0x99 0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x13, 0x88, 0xCB
2000 ppm range: 0x99 0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x07, 0xD0, 0x8F

byte abfrage[] = { 0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79 }; ( Befehl zur Abfrage des CO2 Sensors)

Antwort255 134 1 200 70 0 29 0 78
Bedeutung Startbit Wiederholung des Befehls (hier 134 für 0x86) HighByte LowByte Temperatur + 40 - - - Checksumme

Die CO2 - Konzentration berechnet man aus dem 3. und 4. Byte: 1*256 + 200 = 456ppm.

Die Checksumme (hexadezimal oder dezimal) wird berechnet (hier vom Abfragebefehl:

  1. Berechne die Summe von Byte 1 bis Byte 7: 0x01 + 0x86 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 = 0x87
  2. Subtrahiere das Ergebnis von 255 (FF) : 0xFF - 0x87 = 0x78
  3. Addiere nochmals eine 1:0x78 + 0x01 = 0x79

Abfrage über UART ohne Bibliothek


#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <Arduino.h>
#include <SoftwareSerial.h>
   

SoftwareSerial softwareSerial(D7, D8);
byte abfrage[] = { 0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79 }; // Befehl zur Abfrage des CO2 Sensors
char antwort[9];


void setup() {
  Serial.begin(9600);
  softwareSerial.begin(9600);
} // ende setup


void loop() {
 delay(10000);
 Serial.println(" ");
 softwareSerial.write(abfrage, 9);
 softwareSerial.readBytes(antwort, 9);
 int resHigh = (int) antwort[2];
 int resLow  = (int) antwort[3];
 int CO2_ppm = (256*resHigh)+resLow;
 Serial.print(CO2_ppm);
 Serial.println(" CO2 ppm");
 Serial.println("einzelne Werte: ");  
  for(int i=0; i<9 ; i++){
    Serial.print((int)antwort[i]);
    Serial.print("   ");
  }
  Serial.println(" "); 
  if(antwort[0]!=255){
    Serial.println("RESET .........................................................................................................................");
    delay(500);
    ESP.restart();
  }
} // ende loop

PWM - Methode


const int pwmPin = 7; // 
  

void setup() {
  Serial.begin(115200);
  pinMode(pwmPin, INPUT);
}
  
void loop(){
 int wert = getCO2PWM();
 Serial.println(wert);
 delay(2000);
}


unsigned int getCO2PWM(){
  unsigned long highPeriod = 0;
  unsigned long lowPeriod = 0;
  unsigned long startTime = 0;
  unsigned int ppmCO2 = 0;
  
  while(digitalRead(pwmPin)){}  // solange Signal auf 1
  while(!digitalRead(pwmPin)){}  //solange Signal auf 0
  startTime = millis();
  while(digitalRead(pwmPin)){}   //solange Signal auf 1
  highPeriod = millis() - startTime;
  startTime = millis(); 
  while(!digitalRead(pwmPin)){} //solange Signal auf 0
  lowPeriod = millis() - startTime;
  
  ppmCO2 = 2000*(highPeriod - 2)/(highPeriod + lowPeriod - 4); 
  return ppmCO2; 
}

https://wolles-elektronikkiste.de/mh-z14-und-mh-z19-co2-sensoren

Serielle Abfrage

https://github.com/malokhvii-eduard/arduino-mhz19

// Bibliothek von Eduard Malokhvii
#include <Arduino.h>
#include <Mhz19.h>
#include <SoftwareSerial.h>

SoftwareSerial softwareSerial(D7, D8);
Mhz19 sensor;

void setup() {
  Serial.begin(9600);
  softwareSerial.begin(9600);

  sensor.begin(&softwareSerial);
  sensor.setMeasuringRange(Mhz19MeasuringRange::Ppm_5000);
  sensor.enableAutoBaseCalibration();

  Serial.println("Preheating...");  // Preheating, 3 minutes
  while (!sensor.isReady()) {
    delay(100);
    Serial.print(".");
  }

  Serial.println("Ready...");
  delay(50);
}

void loop() {
  
  auto carbonDioxide = sensor.getCarbonDioxide();
  if (carbonDioxide >= 0) {
    Serial.println(String(carbonDioxide) + " ppm");
  }
 
  delay(20000);
}