MH-Z14 und MH-Z19 CO2 Sensoren

Über den Beitrag

In diesem Beitrag möchte ich mich mit CO2 Sensoren zur Überwachung der Raumluftqualität beschäftigen. Die meisten Sensoren dieser Art arbeiten entweder auf der Basis von Metalloxiden (MOx) oder mit Infrarottechnik (NDIR). Ich beschränke mich hier auf Letztere, und zwar die CO2 Sensoren der MH-Z-Reihe von Zhengzhou Winsen Electronics Technology.

Im Einzelnen behandele ich die folgenden Themen:

  • Das Messprinzip (NDIR)
  • Technische Eigenschaften der Sensoren
  • Kalibrierung
  • Messwertausgabe (analog, seriell, PWM)
  • Ansteuerung mit und ohne Bibliothek

Zum Schluss überprüfe ich dann noch die Messgenauigkeit der Sensoren. Dazu verwende ich eine selbst gebaute CO2 Messkammer und das CO2 Messgerät Technoline WL 1030. 

Vertreter der MH-Z14 und MH-Z19 CO2 Sensoren
Vertreter der MH-Z14 und MH-Z19 Reihe

NDIR Messprinzip der CO2 Sensoren

Nicht-dispersive Infrarotsensoren (NDIR) messen den CO2 Gehalt der Luft über die Absorption von infrarotem Licht. Dass CO2 infrarotes Licht absorbiert, kennt ihr vom Treibhauseffekt. Das Sonnenlicht dringt relativ ungehindert durch die Atmosphäre und das in ihr enthaltene CO2. Die aufgeheizte Erdoberfläche strahlt die Energie zum Teil in Form von infrarotem Licht, also Wärmestrahlung wieder ab. Nur leider wird diese Strahlung vom CO2 absorbiert, was dann zur Erwärmung der Atmosphäre führt.

Im NDIR Sensor gibt es eine IR Lampe und einen Detektor. Dazwischen befindet sich die zu messende Luft. Je mehr CO2 sie enthält, desto mehr IR Strahlung wird absorbiert und entsprechend weniger kommt am Detektor an. „Nicht-dispersiv“ heißt, dass man sich im Gegensatz zur Infrarotspektroskopie nicht die Mühe macht, das infrarote Licht in kleine Wellenlängenbereiche aufzuteilen. Eine gute Erklärung des Messprinzips findet ihr hier.

Ich habe einen MH-Z19 (ein Fake-Modell, dass leider nicht funktionierte) „seziert“. Die Fotos seht ihr unten. Die weißen, filzartigen Abdeckungen sorgen dafür, dass die CO2-haltige Luft eindringen kann, der Staub aber draußen bleibt. Entfernt sie also nicht. Unter der oberen Kappe befindet sich die Messkammer. Ihr seht die IR Lampe und den Sensor. Die IR Lampe ist so eingefasst, dass sie nur in eine Richtung abstrahlt. Die Strahlung wird an der gegenüber liegenden Gehäusewand reflektiert und dann über einen Spiegel auf den Detektor gelenkt. Durch den Umweg legt das IR Licht eine größere Strecke zurück. Dadurch wird mehr IR Licht absorbiert und das bewirkt eine höhere Empfindlichkeit. Unter der Messkammer befindet sich dann die Elektronik.

Innenansicht eines MH-Z19 (allerdings ein Fake Modell)

Technische Eigenschaften der MH-Z CO2 Sensoren

Die MH-Z14 Sensoren sind wesentlich größer als die Vertreter der MH-Z19 Reihe. Ansonsten sind sie hinsichtlich ihrer technischen Daten ziemlich ähnlich. Für einen MH-Z19 müsst ihr mit 20 bis 30 Euro rechnen, für den MH-Z14 ca. 10 Euro mehr. Wenn ihr ein wenig Zeit habt, dann empfehle ich einen Kauf bei AliExpress, denn da ist es deutlich günstiger.

Die folgenden Angaben habe ich den Datenblättern entnommen:

Übersicht der MH-Zxx CO2 Sensoren Familie (bitte Anmerkungen unten beachten!)

Immerhin gibt es Datenblätter, das ist ja nicht immer der Fall bei chinesischen Modulen. Eigentümlicherweise werden aber einige relevante Informationen darin unterschlagen. Es ist unter anderem nicht wirklich klar, welche Messbereiche wirklich eingestellt werden können. So konnte ich beim MH-Z14 nur den voreingestellten Bereich von 0 – 5000 ppm nutzen. Hingegen war die Einstellung des Messbereiches beim MH-Z19C kein Problem. In beiden Datenblättern wiederum ist der serielle Befehl für die Einstellung des Messbereiches nicht dokumentiert.

Zur Raumluftüberwachung braucht ihr eigentlich nur den Bereich bis 2000 ppm, da man bis zu diesem Wert längst gelüftet haben solltet. Allgemein übliche Bewertungen der Raumluft bezüglich der CO2 Konzentration sind:

CO2 Konzentration vs. Raumluftqualität

Einen ausgezeichneten Beitrag über den MH-Z19B habe ich hier gefunden. Ihr findet dort weitere Informationen über die Auswahl von Messwertbereichen, Kalibriermethoden, Fake-Modelle (Vorsicht, wenn die Platine schwarz und nicht grün ist!) und anderes.

Pinout

MH-Z14 – Reihe

Anschlüsse des MH-Z14
Anschlüsse des MH-Z14

Die MH-Z14 Sensoren geizen nicht mit Anschlüssen, aber die meisten von ihnen sind doppelt oder dreifach vorhanden. Die Anschlussleiste des MH-Z14B sieht ein wenig unterschiedlich aus, die Bezeichnungen und Funktionen sind aber dieselben. (siehe Tabelle).

MH-Z19 – Reihe

Anschlüsse des MH-Z19
Anschlüsse des MH-Z19

Die Anschlüsse innerhalb der MH-Z19 Reihe sind gleich. Manchmal ist der analoge Ausgang nicht beschriftet.

Pins der MH-Z CO2 Sensoren
Pins der MH-Z CO2 Sensoren (* V0 ist nicht unbedingt dokumentiert)

Kalibrierung der MH-Zxx CO2 Sensoren

Es gibt drei Kalibriermethoden für die MH-Zxx Sensoren:

  1. Nullpunktkalibrierung: dazu muss der Sensor 20 Minuten in einer gut gelüfteten Umgebung stehen. Der Sensor nimmt an, dass die CO2 Konzentration unter diesen Bedingungen bei 400 ppm liegt, was ungefähr dem aktuellen, globalen Mittel entspricht. Es gibt zwei Methoden, diese Art der Kalibrierung zu starten:
    • der HD Pin wird für mehr als 7 Sekunden mit GND verbunden
    • über eine serielle Anweisung (dazu kommen wir noch)
  2. Span Point Kalibrierung: Kalibrierung bei einer bestimmten CO2 Konzentration – das werden wohl die wenigsten realisieren können. Ich gehe deswegen auch nicht darauf ein und rate euch: spielt besser nicht damit herum.
  3. Hintergrundkalibrierung (Self-Calibration): Die Module können sich in einem 24-Stunden-Rhythmus selbst kalibrieren (beim MH-Z14 ohne Suffix bin ich mir diesbezüglich aber nicht sicher!). Sie nehmen, vereinfacht ausgedrückt, den über den Tag ermittelten, niedrigsten Wert als 400 ppm an. Das funktioniert natürlich nur dann, wenn das Gerät in einem Raum steht, der täglich effektiv gelüftet wird. Wenn das nicht der Fall ist, dann verschiebt sich euer Nullpunkt. Diese Kalibrierung ist voreingestellt aktiv. Über eine serielle Anweisung könnt ihr sie abschalten. Dann solltet ihr aber von Zeit zu Zeit eine manuelle Kalibrierung durchführen.

Ein Fehler bei den Kalibriermethoden 1 und 3 führt zu einem Offset der Messwerte. Ich komme darauf später zurück.

Messwertausgabe

Intern nehmen die MH-Z Sensoren ca. im Sekundentakt einen Messwert auf. Ihr erkennt das am regelmäßigen Leuchten. Auslesen könnt ihr die Messwerte der MH-Zxx CO2 Sensoren auf drei verschiedenen Weisen:

  • Berechnung aus dem analogen Spannungssignal
  • Über das PWM (Pulsweitenmodulation) Signal
  • Seriell (dazu kommen wir bei der seriellen Kommunikation)

Analoges Signal

Das analoge Signal ist ein Spannungswert V zwischen 0.4 und 2.0 Volt. Das bedeutet, dass der ausgewählte Messbereich (range) in diesem Spannungsbereich von 1.6 Volt abgebildet wird:

\text{CO2}\;[\text{ppm}] = \frac{(V -0.4)\cdot range}{1.6}

Diese Methode kann ich nicht empfehlen. Bei mir zeigte sie größere Abweichungen. Mit einem guten A/D Wandler wie dem ADS1115 mag es vielleicht besser gehen.

PWM Signal

Das Signal am PWM Pin hat eine Länge von 1004 Millisekunden (+/- 5% gem. Datenblatt). Je höher die CO2-Konzentration, desto länger das HIGH Signal TH gegenüber dem LOW Signal TL. Als weiterer Parameter muss der Messbereich mit einbezogen werden:

\text{CO2}\;[\text{ppm}] =\frac{T_H-2\text{ms}}{T_H+T_L-4\text{ms}}\cdot range

Für den Messbereich 0-2000 ppm sieht das folgendermaßen aus:

PWM Signal in Abhängigkeit von der CO2 Konzentration (Range 0...2000 ppm)
PWM Signal in Abhängigkeit von der CO2 Konzentration (Range 0…2000 ppm)

Ihr könnt das PWM Signal mit der pulseIn() Funktion auslesen.

Serielle Kommunikation

Serielle Befehle und Antworten der MH-Z CO2 Sensoren bestehen aus neun Bytes. Leider versteht nicht jedes MH-Zxx Modell jeden Befehl. Und leider sind Datenblätter diesbezüglich nicht verlässlich. An anderer Stelle habe ich gelesen, dass das nicht nur vom Modell, sondern auch von der Firmware Version abhängt.

Das Byte 0 ist grundsätzlich 0xFF. Das Byte 8 ist immer die Checksumme, die nach der folgenden Formel berechnet wird:

checksum = \text{0xFF}-\left( \sum_{i=1}^{7}{byte_i}\right) +1

Die Bytes 1 bis 7 werden zusammengezählt, dieser Wert von 255 abgezogen und dann 1 aufaddiert. Wenn die Summe der Bytes größer als 255 ist, dann wird der Überlauf einfach abgeschnitten.

Bei Befehlen ist das Byte 1 grundsätzlich 0x01. Das Byte 2 ist das eigentlich Steuerbyte. Der Wert der weiteren Bytes hängt von der Art des Befehls und den Parametern ab, die gegebenenfalls übergeben werden.

Die wichtigsten Einstellungen für die MH-Zxx CO2 Sensoren
Die wichtigsten Einstellungen für die MH-Zxx CO2 Sensoren

Für Byte 6 und Byte 7 gilt bei der Messbereichseinstellung:

LSB = range\; \&\; \text{0xFF} \;\;\;\; \text{und} \;\;\;\; MSB = range >>8

Das Byte 1 bei einer Antwort auf eine Messwertabfrage ist der Steuerbefehl 0x86. Das höherwertige Byte (MSB) des Messwertes ist Byte 2, das niederwertige Byte (LSB) ist Byte 3:

 \text{CO2 [ppm]} = MSB\cdot 256 + LSB =(MSB<<8) + LSB

Weitere serielle Einstellungen

Es gibt noch weitere, undokumentierte Befehle und Abfragen. Auch für diese gilt, dass die Anwendbarkeit vom Modell und der Firmware abhängig ist. Ihr findet eine gute Übersicht hier.

Ansteuerung der CO2 Sensoren mit dem Microcontroller

Verdrahtung

Die Verdrahtung ist für alle MH-Zxx CO2 Sensoren gleich:

  • VIN/GND: Anschluss an eine stabile Spannungsversorgung.
  • RX / TX: RX an TX und TX an RX, vorzugsweise über SoftwareSerial.
  • HD: falls ihr manuell kalibrieren wollt oder müsst, würde ich diesen Pin über einen Taster an GND verbinden oder mit einem I/O Pin verbinden. OUTPUT/LOW für >7 Sekunden startet die Kalibrierung.
  • PWM: kommt an einen beliebigen I/O Pin.
  • Analog Out: verbindet ihr mit einem analogen Eingang oder A/D-Wandler.

Ansteuerung mit Bibliothek

Für die MH-Zxx CO2 Sensoren stehen eine Reihe von Bibliotheken zur Auswahl. Allerdings ist die Auswahl für MH-Z14 Modelle kleiner. Zwei Bibliotheken habe ich ausprobiert.

Die Bibliothek MH-Z19 von Jonathan Dempsey wurde, wie ihr Name verrät, speziell für die MH-Z19 Sensoren geschrieben. Sie funktioniert sowohl mit der B- wie auch mit der C-Variante. Mein Versuch, damit auch den MH-Z14 anzusteuern, schlug fehl. Die MH-Z19 Bibliothek zeichnet sich dadurch aus, dass sie viele der versteckten Kommandos beherrscht, wie zum Beispiel die Abfrage der Range oder der Firmware Version. Dank der vielen Beispielsketche ist die Bedienung einfach. Ihr findet die Bibliothek hier auf Github oder ihr installiert sie direkt über die Bibliotheksverwaltung in der Arduino IDE.

Dann habe ich noch die Bibliothek MH-Z CO2 Sensors von Tobias Schürg ausprobiert. Auch sie ist sowohl auf GitHub (hier) wie auch in der Arduino Bibliotheksverwaltung zu finden. Die Bibliothek funktionierte sowohl mit dem MH-Z14 wie auch mit dem MH-Z19. Allerdings ging es bei mir erst nach einer kleinen Anpassung in MHZ.cpp. Wenn das bei  euch auch (noch) der Fall sein sollte, sucht dort nach der Zeile if (!isReady()) return STATUS_NOT_READY; und kommentiert sie heraus. Es ist im Moment Zeile 110. Ich hoffe, der Autor behebt das Problem. Es ist als Issue gemeldet. Für den MH-Z14 habe ich den Beispielsketch angepasst:

//#include <ESP8266WiFi.h>
#include <SoftwareSerial.h>
#include <MHZ.h>

// pin for pwm reading
#define CO2_IN 9

// pin for uart reading
#define MH_Z19_RX 10
#define MH_Z19_TX 11

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

void setup() {
  Serial.begin(9600);
  pinMode(CO2_IN, INPUT);
  delay(100);
  Serial.println("MHZ 14A");

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

//  if (co2.isPreHeating()) {
//    Serial.print("Preheating");
//    while (co2.isPreHeating()) {
//      Serial.print(".");
//      delay(5000);
//    }
//    Serial.println();
//  }
}

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

  int ppm_uart = co2.readCO2UART();
  Serial.print("PPMuart: ");

  if (ppm_uart > 0) {
    Serial.print(ppm_uart);
  } else {
    Serial.print("n/a");
  }

  int ppm_pwm = co2.readCO2PWM();
  Serial.print(", PPMpwm: ");
  Serial.print(ppm_pwm);

  int temperature = co2.getLastTemperature();
  Serial.print(", Temperature: ");

  if (temperature > 0) {
    Serial.println(temperature);
  } else {
    Serial.println("n/a");
  }

  Serial.println("\n------------------------------");
  delay(5000);
}

 

Ansteuerung ohne Bibliothek

Für die Ansteuerung ohne Bibliothek habe ich einen eigenen Sketch geschrieben. Ich habe ihn mit einem MH-Z14 und einem MH-Z19C erfolgreich getestet. Ihr müsst allerdings selbst Sorge dafür tragen, dass der von euch gewählte Messbereich auch tatsächlich einstellbar ist. Ihr erkennt, dass ein Messbereich nicht einstellbar ist, wenn die Werte, die ihr über PWM und die serielle Abfrage erhaltet, signifikant unterschiedlich sind. Und – wie schon erwähnt – funktionieren nicht alle Befehle mit jedem Modell.

Bei der PWM Abfrage habe ich mich gegen die schlanke pulseIn() Methode entschieden, da sie nur die HIGH Phase bestimmt. HIGH und LOW Phase umfassen zusammen 1004 Millisekunden. Laut Datenblatt kann dieser Wert aber um bis zu 5 % variieren. Eine Bestimmung von HIGH und LOW Phase sollte diesen Fehler ausgleichen.

SoftwareSerial habe ich auf die Pins 10 und 11 gelegt. Den PWM Pin habe ich an Pin 9 gehängt und den HD Pin für die Kalibrierung auf Pin 8. Das Auslesen des analogen Signals erfolgt über A0.

getCO2AndTemp() bekommt seine Parameter als Referenzen und gibt keinen Wert zurück. Das ist eine Lösung für das Problem, dass C++ keine zwei Werte zurückgeben kann.

Die 9 Byte umfassenden Befehle werden stückweise „zusammengebaut“ und in dem Byte Array „cmd“ gespeichert. Die Antworten der MH-Zxx Sensoren werden im Byte Array „message“ gespeichert.

Ansonsten hoffe ich, dass der Code einigermaßen verständlich ist.

#define RANGE_2000  0x07D0
#define RANGE_5000  0x1388
#define RANGE_10000 0x2710
#define TEMP_CORR 38  // seems to differ from module to module!

#include <SoftwareSerial.h>
const int pwmPin = 9;
const int hdPin = 7;
unsigned int rangeFactor = 5000; //not every range works for every MH-Zxx!

SoftwareSerial myMHZ(10, 11); // RX, TX

void setup(){
  pinMode(hdPin, OUTPUT);
  digitalWrite(hdPin, HIGH);
  pinMode(pwmPin, INPUT);
  Serial.begin(9600);
  myMHZ.begin(9600);
  while(!Serial){}
  while(!myMHZ){}
    
  setRange(RANGE_2000); 
  Serial.print("Range: ");
  Serial.println(getRange()); // does not work with all MH-Zxx sensors
  Serial.print("Firmware: ");
  Serial.println(getFirmwareVersion()); // does not work with all MH-Zxx sensors
  
  // for calibration your MH-Zxx needs to run in a 400 ppm CO2 environment for 20 min!!!
  // if the MH-Z module supports it, you can calibrate via serial commands
  // if not, choose the HD - method)
  // calibrateMHZ(); // calibration via serial command
  // calibrateMHZByHD(); // calibration via HD pin
  // activate/deacvtivate the permanent calibration which is happening in the background (if supported):
  // activateCalibrationMode(true);
  
  Serial.print("Self Calibration Mode: ");
  if(getSelfCalModeStatus()){ // does not work with all MH-Zxx sensors
    Serial.println("ON"); 
  }
  else Serial.println("OFF");
}

void loop(){
  unsigned int ppmCO2PWM = 0;
  unsigned int ppmCO2Serial = 0;
  float ppmCO2Analog = 0.0;
  int temperature = 0;
   
  ppmCO2PWM = getCO2PWM();
  getCO2AndTemp(ppmCO2Serial, temperature);
  ppmCO2Analog = (((analogRead(A0))/1023.0 * 5.0) - 0.4)/1.6 * rangeFactor;
   
  Serial.print("CO2 in ppm (PWM): ");
  Serial.println(ppmCO2PWM);
  Serial.print("CO2 in ppm (Serial): ");
  Serial.println(ppmCO2Serial);
  Serial.print("CO2 in ppm (Analog): ");
  Serial.println(ppmCO2Analog);
  Serial.print("Temperature [°C]: ");
  Serial.println(temperature);
  
  Serial.println("**********************");
  delay(1000);
}

void setRange(unsigned int range){
  rangeFactor = range;
  sendCommand(0x99, range);
  delay(100);
}

void calibrateMHZ(){
  sendCommand(0x87, 0x00);
}

void calibrateMHZByHD(){
  Serial.println("Calibration - please wait for initialization");
  digitalWrite(hdPin, LOW);
  delay(10000);
  digitalWrite(hdPin, HIGH);
  Serial.println("Done");
}

void activateCalibrationMode(bool activate){
  if(activate){
    sendCommand(0x7A, 0x00); // my own command for activation
  }
  else{
    sendCommand(0x79, 0x00); 
  }
  delay(100);
}

unsigned int getRange(){
  byte message[9]; 
  getResponse(message, 0x9B);
  unsigned int range = (unsigned int)(message[4]<<8) + message[5];
  return range; 
}

void getCO2AndTemp(unsigned int &ppmCO2, int &temp){
  byte message[9];
  getResponse(message, 0x86);
  ppmCO2 = (unsigned int)(message[2]<<8) + message[3];
  temp = (int)(message[4] - TEMP_CORR);
}

String getFirmwareVersion(){
  byte message[9];
  String firmware = "";
  getResponse(message,0xA0);
  for(int i=2; i<6; i++){
    firmware += (char)message[i];
  }
  return firmware;
}

byte getSelfCalModeStatus(){
  byte message[9]; 
  getResponse(message, 0x7D);
  return message[7]; 
}

void sendCommand(byte cmdByte, unsigned int range){
  byte cmd[9] = {0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  cmd[2] = cmdByte;
  if(cmdByte==0x99){
    cmd[6] = range>>8;
    cmd[7] = range & 0xFF;
  }
  
  if(cmdByte==0x7A){ // my own command for activation of self calibration
    cmd[2] = 0x79;
    cmd[3] = 0xA0;
  }  
  cmd[8] = getCheckSum(cmd);
  myMHZ.write(cmd,9);
}

unsigned int getCO2PWM(){
  unsigned long highPeriod = 0;
  unsigned long lowPeriod = 0;
  unsigned long startTime = 0;
  unsigned int ppmCO2 = 0;
  
  while(digitalRead(pwmPin)){}
  while(!digitalRead(pwmPin)){}
  startTime = millis();
  while(digitalRead(pwmPin)){}
  highPeriod = millis() - startTime;
  startTime = millis(); 
  while(!digitalRead(pwmPin)){}
  lowPeriod = millis() - startTime;
  
  ppmCO2 = rangeFactor*(highPeriod - 2)/(highPeriod + lowPeriod - 4); 

  return ppmCO2; 
}

void getResponse(byte msg[], byte cmdByte){
  unsigned long maxWaitTime = 1000;
  while(myMHZ.available()){
    myMHZ.read();    // removes "rubbish"
  }
  sendCommand(cmdByte, 0x00);
  unsigned long startTime = millis();
  
  while(!myMHZ.available()){
    if((startTime-millis())>maxWaitTime){ // if the MH-Zxx does not respond
      break;
    }
  }
  
  myMHZ.readBytes(msg,9);
}

byte getCheckSum(byte *seq){
  byte checkSum = 0;
  for(int i=1; i<8; i++){
    checkSum += seq[i];
  }
  checkSum = 255 - checkSum + 1;
  return checkSum;
}

 

 

Genauigkeit der MH-Zxx CO2 Sensoren

Messkammer für CO2 Sensoren

Die Genauigkeit der MH-Zxx CO2 Sensoren habe ich mit dem Technoline WL 1030, einem kommerziell erhältlichem CO2 Messgerät, überprüft. Dieses Gerät war 2021 Testsieger der Stiftung Warentest bei den CO2 Messgeräten. Trotzdem stellt sich natürlich die Frage, wie genau es selbst misst, zumal es, wenn man sich die Funktionsweise und die technischen Daten anschaut, selbst auch auf einem MH-Zxx Sensor oder ähnlichem zu basieren scheint. 

Zu diesem Zweck habe ich mir eine CO2 Messkammer gebaut. Als Grundlage diente ein Kasten aus Acrylkunststoff, den man normalerweise zum Ausstellen von Figuren oder Modellautos benutzt. Über ein kleines, verschließbares Loch habe ich mit einer Spritze das CO2 zugeführt. Ein Elektromotor mit Propeller sorgte für die Verteilung des CO2. Dann habe ich noch ein Breadboard eingeklebt und einen Zugang für elektrische Anschlüsse eingebaut. Das Technoline Messgerät habe ich in die Kammer hineingestellt und einen Zugang für das Stromversorgungskabel in den Kasten gebohrt. Das CO2 hat mir mein Wassersprudler geliefert.

Spritzen für die CO2 Dosierung

Überprüfung des Technoline WL 1030

Versuch

Das Technoline WL 1030 habe ich mehrere Tage laufen lassen und gemäß der Bedienungsanleitung kalibriert. Das funktioniert im Prinzip wie bei den MH-Zxx CO2 Sensoren. Vor den Messungen habe ich gut gelüftet, um einen Startwert von 400 ppm zu erreichen.

Die Innenabmessungen des Kastens betragen 13 cm x 13 cm x 20 cm = 3380 cm3. Für das Technoline WL 1030 habe ich ein Volumen von 260 cm3 abgeschätzt. Es besteht aber zum überwiegenden Teil aus „Luft“. Letzten Endes habe ich mit 130 cm3 für das Messgerät und das Breadboard gerechnet. Damit ist das verbleibende Volumen in der Messkammer ca. 3250 cm3. Sollte ich mich dabei um 50 cm3 vertan haben, ist das ein Fehler von 1.5 %. Eine Zugabe von einem Milliliter CO2 sollte die CO2 Konzentration um 1/3250 = ca. 308 ppm erhöhen.

Ich habe jeweils 0.5 oder 1 Milliliter CO2 zugeführt und gewartet, dass sich ein einigermaßen stabiler Wert einstellte. Das hat jeweils ca. 5 min gedauert. Da meine Messkammer nicht absolut gasdicht ist, nahm der Messwert nach Erreichen eines Maximums langsam wieder ab. Insgesamt habe ich 4 ml CO2 in die Kammer eingebracht. Und so entwickelte sich die Konzentration:

Überpüfung des Technoline WL 1030
Überprüfung des Technoline WL 1030

Auswertung

Der Endwert bei Zugabe von 4 ml CO2 hätte bei 1632 ppm liegen müssen. Gemessen habe ich ein Maximum von ca. 1500 ppm. Nun ist die Kammer aber nicht wirklich dicht. Um den Fehler abzuschätzen, habe ich den Versuch wiederholt, aber diesmal 4 ml CO2 in einem Schritt zugeführt. Diesmal lag der Endwert bei ca. 1550 ppm (grüne Raute). Nach weiteren 5 Minuten sank die Konzentration wegen der Undichtigkeit auf etwas unter 1500 ppm (gelber Kreis), also ein Verlust von ca. 50 ppm. Auf den ersten Messwert hatte ich 5 min gewartet. Wenn ich eine konstante Undichtigkeit zugrunde lege, müsste ich also auf den ersten Messwert 50 ppm aufschlagen. Mit ca. 1600 bin ich dann schon sehr nah an den theoretischen 1632 ppm. Zugegebenermaßen war das die beste Messung. Wiederholungen zeigten gewisse Schwankungen, aber die Messungen lagen (nach Korrektur der Undichtigkeit) nicht mehr als 5 % daneben. Ausreißer sind natürlich auch durch andere Fehler bedingt, z. B. dass ich beim Aufziehen der Spritze vielleicht auch mal etwas Luft mit hineinbekommen habe. 

Mein Fazit ist, dass man sich auf die Messwerte des Technoline 1030 gut verlassen kann – sorgfältige Kalibrierung vorausgesetzt.

Messungen mit den MH-Zxx CO2 Sensoren

Ich habe dann das Technoline WL 1030 genommen, um die MH-Zxx Sensoren zu prüfen. Zunächst ein kleines Video dazu:

Bei meinen Versuchen mit den MH-Zxx CO2 Sensoren habe ich festgestellt, dass diese langsamer reagierten als das Technoline WL 1030. Vielleicht ist das einfach bauartbedingt und das CO2 braucht bei den MH-Zxx Sensoren länger, um durch die Abdeckungen in die eigentliche Messzelle zu gelangen. Vielleicht läuft auch ein Dämpfungsalgorithmus im Hintergrund. Die Folge ist jedenfalls, dass die Messwerte der MH-Zxx Sensoren noch stiegen, während die Messwerte des Technoline WL 1030 schon wieder sanken. Dadurch lagen die Werte des Technoline in der Zugabephase etwas höher. Nach der Zugabephase nahm die CO2 Konzentration wegen der Undichtigkeit der Messkammer langsam ab. Auch hier reagieren die MH-Zxx Sensoren langsamer und liefern entsprechend höhere Werte. Hier exemplarisch ein Ergebnis für den MH-Z14 Sensor:

MH-Z14 vs. Technoline WL 1030
MH-Z14 vs. Technoline WL 1030

Die Ergebnisse für den MH-Z19C sahen sehr ähnlich aus. Insgesamt war ich ebenso erstaunt wie erfreut über die guten Messergebnisse. Wichtig ist allerdings auch hier, dass man die Nullpunktkalibrierung (genauer gesagt die 400 ppm Kalibrierung) sorgfältig durchführt.

Und das passiert bei schlechter Kalibrierung

Wenn ihr die Kalibrierung in einer nicht vollständig gelüfteten Umgebung durch führt, verschiebt ihr den 400 ppm Startpunkt entsprechend. Das ist mir bei der unten abgebildeten Messung mit einem MH-Z19C passiert. Zuerst wollte ich die Daten einfach verwerfen, fand es dann aber ganz interessant. Man kann schön erkennen, dass die Messwerte parallel verschoben sind. Einen Einfluss auf die Steigung hat die fehlerhafte Kalibrierung nicht.

Messwerte bei mangelhafter Kalibrierung
Messwerte bei mangelhafter Kalibrierung

Fazit

Die MH-Zxx CO2 Sensoren liefern zuverlässige Werte, man muss sie aber richtig kalibrieren. Entweder führt ihr dazu von Zeit zu Zeit eine manuelle Kalibrierung durch oder ihr nutzt die automatische Kalibrierung. Für Letztere müsst ihr aber sicherstellen, dass der Sensor in einem Raum steht, der regelmäßig gelüftet wird. Auf keinen Fall sind die MH-Zxx Sensoren dazu geeignet, sie „mal eben“ anzuschalten, um irgendwo eine CO2 Messung durchzuführen.

Danksagung

Das Beitragsbild habe ich auf Pixabay gefunden. Es stammt von Malte Reimold. Ich habe es lediglich quadratisch beschnitten.

4 thoughts on “MH-Z14 und MH-Z19 CO2 Sensoren

  1. Tobias Schürg hat bemerkt, dass man den Sensor nicht in zu kurzem Zeitabstand abfragen sollte. Zum einen weil der Sensor nicht wirklich neue Messungen macht und zum andern, weil es die Lebensdauer extrem verkürzen kann.
    So wie ich das verstanden habe sollte maxtime 120000 (2 Minuten) nicht unterschreiten.

    1. Dagegen spricht, dass ich bei jeder Abfrage andere Ergebnisse erhalte. Und wieso sollte eine Abfrage die Lebensdauer verkürzen, wenn durch die Abfrage keine zusätzlichen Messungen ausgelöst werden? Und im Beispielsketch der Bibliothek von Tobias Schürg wird der Sensor alle 5 Sekunden abgefragt. Aber: genau wissen tue ich das ganz klar nicht! Und eine zu kurze Abfrage macht auch nicht wirklich Sinn (außer vielleicht bei meinen Experimenten), da sich die CO2 Konzentration in einem Raum eher langsam ändert. Also wer auf der sicheren Seite sein möchte sollte den Ratschlag berücksichtigen. Vielen Dank!

    2. Dass eine zu häufige Abfrage die Lebensdauer verkürzt, wäre unlogisch- denn der Sensor gibt selber über den PWM-Ausgang etwa einmal pro Sekunde den aktuellen Messwert aus, selbst wenn man gar nicht aktiv abfragt (exakt alle 1004ms laut Datenblatt). Man könnte also schon darüber etwa 1x pro Sekunde den aktuellen Wert ermitteln.

      Aus dem Datenblatt in https://www.winsen-sensor.com/d/files/PDF/Infrared%20Gas%20Sensor/NDIR%20CO2%20SENSOR/MH-Z19%20CO2%20Ver1.0.pdf ist ebenfalls nicht ersichtlich, dass man nicht zu oft abfragen darf.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.