MH-Z19 CO2 Grundwert zurücksetzen (MH-Z19 CO2 Reset the basic value)

mh-z19 CO2 Sensor

Ich habe vereinzelt CO2-Sensoren bekommen, deren Grundwert von ca. 400 ppm nicht stimmte. Das bemerkt man am besten, wenn man die angezeigten Werte mit deren anderer Sensoren vergleicht. Zum Glück lässt sich der Wert leicht zurücksetzen. Wichtig ist, dass der reale Wert auch dem Grundwert in der Atmosphäre entspricht. Dies lässt sich einfach mit einem anderen Sensor prüfen. Ich öffne dann einfach das Fenster so lange, bis der Wert erreicht ist. Anschliessend verbindet man das HD-Pin mit einem ca. 3 kOhm Widerstand für 7 Sekunden gegen Masse. Es darf nach Datenblatt nur ein Strom von max. 10 mA fließen. Nach Neustart der Anwendung bzw. des Sensors sollte der Wert dementsprechen bei ca. 400 ppm liegen. Wenn dann der CO2 Wert später wieder ansteigt sollte der Wert wie bei anderen Sensoren liegen. Für Abweichungen müsste der Istwert korrigiert werden. Dafür habe ich aber noch keine einfache Lösung gefunden. Mal schauen, vielleicht fällt mir da noch etwas ein.

MH-Z19 CO2 Reset the basic value

I have isolated sensors, whose basic value of about 400 ppm was not correct. This is most noticeable when comparing the displayed values with their other sensors. Fortunately, the value can easily be reset. It is important that the real value also corresponds to the basic value in the atmosphere. This can be easily checked with another sensor. I then simply open the window until the value is reached. Then connect the HD pin to a ground with approx. 3 kOhm resistance for 7 seconds. According to the data sheet, only a current of max. 10 mA. After restarting the application or the sensor, the value should correspond to approximately 400 ppm. If the CO2 value rises later, the value should be the same as with other sensors. The actual value should be corrected for deviations. But I have not yet found a simple solution. Let’s see, maybe there’s something else.

MHZ-19 CO2 Messung mit TFT Anzeige

Multisensorsketch mit Arduino MH-Z19 …

Datenblatt

Co2-Messung mit dem MH-Z19 und Anzeige auf dem 7735 TFT-Display 1,8 Zoll

7735 lcd displa mit mh-z21

Hier nun mal ein Sketch um die Werte live auf einem preiswerten TFT-Display anzuzeigen.

/*
  Arduino TFT text example

   http://www.arduino.cc/en/Tutorial/TFTDisplayText

 */

#include <TFT.h>  // Arduino LCD library
#include <SPI.h>

// pin definition for the Uno
#define cs   10
#define dc   9
#define rst  8

// pin definition for the Leonardo
// #define cs   7
// #define dc   0
// #define rst  1

// create an instance of the library
TFT TFTscreen = TFT(cs, dc, rst);

// char array to print to the screen
char sensorPrintout[6];

void setup() {

  // Put this line at the beginning of every sketch that uses the GLCD:
  TFTscreen.begin();

  // clear the screen with a black background
  TFTscreen.background(0, 0, 0);

  // write the static text to the screen
  // set the font color to white
  TFTscreen.stroke(255, 255, 255);
  // set the font size
  TFTscreen.setTextSize(2);
  // write the text to the top left corner of the screen
  TFTscreen.text("Sensor Value :\n ", 0, 0);
  // ste the font size very large for the loop
  TFTscreen.setTextSize(5);

  #define AIQ_SENSOR_ANALOG_PIN 5
}
void loop() {
  //CO2
  
  unsigned long duration = pulseIn(AIQ_SENSOR_ANALOG_PIN, HIGH, 2000000);
  
  //Serial.print(duration/1000); Serial.println(" ms ");
  //from datasheet
  //CO2 ppm = 2000 * (Th - 2ms) / (Th + Tl - 4ms)
  //  given Tl + Th = 1004
  //        Tl = 1004 - Th
  //        = 2000 * (Th - 2ms) / (Th + 1004 - Th -4ms)
  //        = 2000 * (Th - 2ms) / 1000 = 2 * (Th - 2ms)
 
  long co2ppm = 5 * ((duration/1000) - 2);
  Serial.print(co2ppm);

 
String sensorVal = String(co2ppm);
 sensorVal.toCharArray(sensorPrintout, 6);
  TFTscreen.stroke(255,255,255);
  TFTscreen.text(sensorPrintout, 20, 50);

  delay(1000);
  TFTscreen.stroke(0,0,0);
  TFTscreen.text(sensorPrintout, 20, 50);
}

 

4SensorenSketch V0.13 mit dem MH-Z19 für die CO2-Messung

Hier nun die Fortsetzung meines alten 4 Sensoren Sketches. Nun ist der MH-Z19 für die CO2 Messung integriert und ich habe außerdem noch eine Steuerung für eine LED-Warnung eingebaut. Der Sketch funktioniert genau so mit dem MH-Z21.

//Sens4Sketch (Motion, Temperature, Humidity, CO2)

//v0.13 LED blink co2
//v0.12 MH-Z19 integration
//v0.11 Motion corrected
//v0.10 ---- installation co2 value specification outside----under construction
//v0.9 Autoset r0 off, vaule < 400 possible!!!!
//v0.8 Corr. Lib von rstoica (set r0, correction) impl
//v0.7 set r0 to eeprom
//v0.6 SetR0-Button
//v0.5 Motion
//v0.4 autosetr0 if co2<400
//v0.3 api 2.0, redesign
//v0.2 CorrectedRZero basis for calculating r0
//G. Krocker K.-H. Wind et. al. ++++JH
//Caution: The Sketch erorder an amended mq135.h Library

#define MY_DEBUG    // Enables debug messages in the serial log
#define MY_RADIO_NRF24
//#define MY_REPEATER_FEATURE  // Enables repeater functionality for a radio node
#include <SPI.h>
#include <MySensors.h>
#include "DHT.h"
//----------------------------------------------------------------------------
// Timer
unsigned long SLEEP_TIME = 30*1000; // Sleep time between reads (in milliseconds)
//-----------------------------------------------------------------------------
//MOTION
#define DIGITAL_INPUT_SENSOR 3   // The digital input you attached your motion sensor.  (Only 2 and 3 generates interrupt!)
#define INTERRUPT DIGITAL_INPUT_SENSOR-3 // Usually the interrupt = pin -2 (on uno/nano anyway)
#define CHILD_ID_MOTION 16   // Id of the sensor child
MyMessage msgMotion(CHILD_ID_MOTION, V_TRIPPED);
//-----------------------------------------------------------------------------
// DHT22
#define CHILD_ID_HUM 0
#define CHILD_ID_TEMP 1
#define DHTPIN 4     // what digital pin we're connected to
//#define DHTTYPE DHT11   // DHT 11
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)
DHT dht(DHTPIN, DHTTYPE);
float lastTemp;
float lastHum;
boolean metric = true; 
MyMessage msgHum(CHILD_ID_HUM, V_HUM);
MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
//-------------------------------------------------------------------------
#define CHILD_ID_AIQ 0
#define AIQ_SENSOR_ANALOG_PIN 5
float valAIQ =0.0;
float lastAIQ =0.0;
MyMessage msg(CHILD_ID_AIQ, V_LEVEL);
MyMessage msg2(CHILD_ID_AIQ, V_UNIT_PREFIX);
//-----------------------------------------------------------------------------

void setup() {
//--------------------------------------------------------------------- 
 dht.begin();
pinMode(DIGITAL_INPUT_SENSOR, INPUT);
pinMode(7, OUTPUT);
}
//-----------------------------------------------------------------------------
void presentation(){
sendSketchInfo("Sens4", "v0.13");
present(CHILD_ID_TEMP, S_TEMP);
present(CHILD_ID_HUM, S_HUM);
present(CHILD_ID_MOTION, S_MOTION);
present(CHILD_ID_AIQ, S_AIR_QUALITY);  
//--------------------------------------------------------------------
}

void loop(){



//-----------------------------------------------------------------------------
//TEMP_FEUCHTE 
  float temperature = dht.readTemperature();
   send(msgTemp.set(temperature, 1));
    Serial.print("T: ");
    Serial.println(temperature);
 
  float humidity = dht.readHumidity();

      send(msgHum.set(humidity, 1));
      Serial.print("H: ");
      Serial.println(humidity);
//-----------------------------------------------------------------------------  
//CO2
  
  unsigned long duration = pulseIn(AIQ_SENSOR_ANALOG_PIN, HIGH, 2000000);
  
  //Serial.print(duration/1000); Serial.println(" ms ");
  //from datasheet
  //CO2 ppm = 2000 * (Th - 2ms) / (Th + Tl - 4ms)
  //  given Tl + Th = 1004
  //        Tl = 1004 - Th
  //        = 2000 * (Th - 2ms) / (Th + 1004 - Th -4ms)
  //        = 2000 * (Th - 2ms) / 1000 = 2 * (Th - 2ms)
 
  long co2ppm = 5 * ((duration/1000) - 2);
  Serial.print(co2ppm);

    send(msg.set(co2ppm,1));
 
if (co2ppm>1000){
    digitalWrite(7, HIGH);   // turn the LED on (HIGH is the voltage level)
}
if (co2ppm<550) {
    digitalWrite(7, LOW);
}

//-----------------------------------------------------------------------------
//Read digital motion value
boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH;
 Serial.print("Motion: ");
Serial.println(tripped);
send(msgMotion.set(tripped?"1":"0"));  
//-----------------------------------------------------------------------------
wait(SLEEP_TIME);
}
//---------------------------------------------------------------------------

 

Sensoren4Sketch

Fertiges Sensormodul
  • 0.8 Verwendung der korrigierten Lib von RSTOIKA
  • Der R0 Wert kann automatisch zum Setzen in FHEM verwendet werde. Hiermit wird ein Button oben angezeigt. attr CO2_SZ setReading_R0 textField<br>
  • Einbrennzeit und Stabilisierung abwarten
  • Kalibrierung im Freien bei Windstille
  • Redesign MySensors 2.0
  • Grundwert R0Cor wird gesetzt, wenn CO2 < 390
  • Spezielle Lib ist für den Kalibierung – Button notwendig
  • EEPROM Speicherung R0Cor

MQ135lib.tar

//Sens4Sketch (Motion, Temperature, Humidity, CO2)

//v0.8 Corr. Lib von rstoica (set r0, correction) impl
//v0.7 set r0 to eeprom
//v0.6 SetR0-Button
//v0.5 Motion
//v0.4 autosetr0 if co2<400
//v0.3 api 2.0, redesign
//v0.2 CorrectedRZero basis for calculating r0
//G. Krocker K.-H. Wind et. al. ++++JH
//Caution: The Sketch erorder an amended mq135.h Library

//#define MY_DEBUG    // Enables debug messages in the serial log
#define MY_RADIO_NRF24
#include <SPI.h>
#include <MySensors.h>
#include <DHT.h>
#include <MQ135.h>
//----------------------------------------------------------------------------
// Timer
unsigned long SLEEP_TIME = 15*1000; // Sleep time between reads (in milliseconds)
//-----------------------------------------------------------------------------
//MOTION
#define DIGITAL_INPUT_SENSOR 3   // The digital input you attached your motion sensor.  (Only 2 and 3 generates interrupt!)
#define INTERRUPT DIGITAL_INPUT_SENSOR-3 // Usually the interrupt = pin -2 (on uno/nano anyway)
#define CHILD_ID_MOTION 8   // Id of the sensor child
MyMessage msgMotion(CHILD_ID_MOTION, S_MOTION);
//-----------------------------------------------------------------------------
// DHT22
#define CHILD_ID_HUM 0
#define CHILD_ID_TEMP 1
#define HUMIDITY_SENSOR_DIGITAL_PIN 4
DHT dht;
float lastTemp;
float lastHum;
boolean metric = true; 
MyMessage msgHum(CHILD_ID_HUM, V_HUM);
MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
//-----------------------------------------------------------------------------
// MQ135
#define CHILD_ID_CO2C 24
#define CHILD_ID_CO2 25
#define CHILD_ID_R0C 26
#define CHILD_ID_R0 27
#define EEPROM_R0C 0
int C02;
int CO2C;
float R0;
float R0C;
float R02;
MQ135 gasSensor = MQ135(0);//PIN0 
MyMessage msgCO2C(CHILD_ID_CO2C, V_VAR1);
MyMessage msgCO2(CHILD_ID_CO2, V_VAR1);
MyMessage msgR0C(CHILD_ID_R0C, V_VAR1);
MyMessage msgR0(CHILD_ID_R0, V_VAR1);
//-----------------------------------------------------------------------------
void setup() {
//--------------------------------------------------------------------- 
 //R0C aus EEPROM sonst 55
dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN);
pinMode(DIGITAL_INPUT_SENSOR, INPUT);
uint8_t R02 = loadState(EEPROM_R0C);
// get R0C from EEPROM
float R0C = R02 * 2;
if (R0C > 1.0 && R0C < 500.0)
{
Serial.print(F("Setting R0 from EEPROM: "));
}
else
{
Serial.print(F("Setting default R0C: "));
R0C = 50;
}
Serial.print(R0C);
Serial.println(F(""));
gasSensor.setRZero(R0C);
}
//-----------------------------------------------------------------------------
void presentation(){
sendSketchInfo("Sens4", "v0.7");
present(CHILD_ID_TEMP, S_TEMP);
present(CHILD_ID_HUM, S_HUM);
present(CHILD_ID_CO2C, S_CUSTOM);
present(CHILD_ID_CO2, S_CUSTOM);
present(CHILD_ID_R0C, S_CUSTOM);
present(CHILD_ID_R0, S_CUSTOM);
present(CHILD_ID_MOTION, S_MOTION);
}
//-----------------------------------------------------------------------------



void loop(){



//-----------------------------------------------------------------------------
//TEMP_FEUCHTE 

wait(dht.getMinimumSamplingPeriod());// TheoL
  float temperature = dht.getTemperature();
  if (isnan(temperature)) {
      Serial.println("Failed reading temperature from DHT");
  } else if (temperature != lastTemp) {
    lastTemp = temperature;
    if (!metric) {
      temperature = dht.toFahrenheit(temperature);
    }
   send(msgTemp.set(temperature, 1));
    Serial.print("T: ");
    Serial.println(temperature);
  }
  
  float humidity = dht.getHumidity();
  if (isnan(humidity)) {
      Serial.println("Failed reading humidity from DHT");
  } else if (humidity != lastHum) {
      lastHum = humidity;
      send(msgHum.set(humidity, 1));
      Serial.print("H: ");
      Serial.println(humidity);
  }
//-----------------------------------------------------------------------------  
//CO2
  float R0 = gasSensor.getRZero();
  float R0C = gasSensor.getCorrectedRZero(temperature, humidity);
  float CO2 = gasSensor.getPPM();
  float CO2C = gasSensor.getCorrectedPPM(temperature, humidity);
  
  Serial.print("R0: "); 
  Serial.println(R0);
  send(msgR0.set(R0,1));

  Serial.print("R0C: ");
  Serial.println(R0C);
  send(msgR0C.set(R0C,1));

  Serial.print("CO2: ");
  Serial.println(CO2);
  send(msgCO2.set(CO2,1));

  Serial.print("CO2C: ");
  Serial.println(CO2C);
  send(msgCO2C.set(CO2C,1));
  
  Serial.println();
// Grundwert CO2 < 400 ppm dann setze R0C in Lib
if (CO2C < 420)
{
  saveState(EEPROM_R0C, (uint8_t)(R0C/2));
  gasSensor.setRZero(R0C);
  send(msgR0C.set(R0C, 2));
  Serial.print(F("CO2 < 420: R0 gesetzt "));
}
//-----------------------------------------------------------------------------
//Read digital motion value
boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH;
Serial.println(tripped);
send(msgMotion.set(tripped?"1":"0"));  
//-----------------------------------------------------------------------------
wait(SLEEP_TIME); //sleep for: sleepTime // byTheo: Changed
}
//-----------------------------------------------------------------------------
//incomingMessage
void receive(const MyMessage& message){
 Serial.println(F("Incoming Message:"));

if (message.isAck())
{
Serial.println(F("This is an ack from gateway"));
}

uint8_t sensor = message.sensor;
if (sensor == CHILD_ID_R0C)
{
float R0C = message.getFloat();

Serial.print(F("Incoming R0C: "));
Serial.print(R0C);
Serial.println(F(""));

saveState(EEPROM_R0C, (uint8_t)(R0C/2));
gasSensor.setRZero(R0C);
send(msgR0.set(R0C, 2));
}
}
//-----------------------------------------------------------------------------

 

MQ135.h Beispiel Sketch zum Verstehen der Bibliothek für die CO2 Messung

5sens Modul

Anbei ein kleiner Sketch zum Verstehen des Bibliothek vom G. Krocker zur Anzeige der relevanten Werte des MQ135 und Verwendung der Temperatur-Kompensation. Der MQ135 Sensor wird verwendet um die Luftgüte, hier speziell das CO2 zu messen. Mit den Werten ist eine Eichung des Sensors auf den mittleren CO2 Wert in der Atmosphäre (ca. 400 ppm) möglich (rzeroc). Einen kompletten Sketch findet man hier Vier Sensoren Sketch

Hilfreich:

https://www.grower.ch/forum/threads/wir-basteln-ein-arduino-co2-messgeraet.89083/

https://hackaday.io/project/3475-sniffing-trinket

 

#include "MQ135.h"
#include <DHT.h>  

#define HUMIDITY_SENSOR_DIGITAL_PIN 4 // DHT22 an PIN4

MQ135 gasSensor = MQ135(0); //GAS Sensor PIN A0

DHT dht;



void setup() {
   Serial.begin(115200);
    dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN);
    
}

void loop() {
{
  float h = dht.getHumidity();
  float t = dht.getTemperature();
 
  float rzero = gasSensor.getRZero();
  float rzeroc = gasSensor.getCorrectedRZero( t, h);
   
  float ppm = gasSensor.getPPM();
  float ppmc = gasSensor.getCorrectedPPM(t, h);
 
  Serial.println(t);
  Serial.println(h);   
  Serial.println(rzero);
  Serial.println(rzeroc);
  Serial.println(ppm);
  Serial.println(ppmc);
  Serial.println();

  delay(3000);
 
}
}