====== CO$_2$ – Kohlenstoffdioxid in der Luft ======
Kohlenstoffdioxid, auch Kohlendioxid oder CO$_2$
- farbloses, nicht brennbares und geruchloses Gas,
- schwerer als Luft
- natürlicher Bestandteile der Atmosphäre (neben Stickstoff N$_2$, Sauerstoff O$_2$ und den Edelgasen)
- wichtig für das Leben auf der Erde (Photosynthese)
- 6 CO$_2$ + 6 H$_2$O + Lichtenergie ⇌ C$_2$H$_{12}$O$_6$ + 6 O$_2$
- Treibhausgas: trägt wesentlich zur Erderwärmung bei
- Eine zu hohe Kohlenstoffdioxidkonzentration in Innenräumen führt zu Kopfschmerzen, Schläfrigkeit, Unaufmerksamkeit,
===== Entstehung von Kohlenstoffdioxid: =====
- Entsteht bei der Zellatmung
- Zerfall toter Organismen
- Vulkangas
- 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 =====
{{:arduino:co2_schwingungen.png?200 |}}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.
{{:arduino:ndir-prinzip.png?400 |}} **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: {{ :arduino:mh-z16.pdf |}}
Internetquellen:
* [[https://revspace.nl/MHZ19]]
{{:arduino:esp8266_mh-z19_verbindung.png?400 |}}
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:
|<30em>|
^ 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)
|<30em>|
^ Antwort|255 |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:
- Berechne die Summe von Byte 1 bis Byte 7: 0x01 + 0x86 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 = 0x87
- Subtrahiere das Ergebnis von 255 (FF) : 0xFF - 0x87 = 0x78
- Addiere nochmals eine 1:0x78 + 0x01 = 0x79
===== Abfrage über UART ohne Bibliothek =====
#include
#include
#include
#include
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
#include
#include
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);
}