Cannot get MH-Z19B CO2 Sensor to Work

Hi there everyone, I'm new this this forum and fairly new to Arduino.

I'm having and issue getting my MH-Z19B CO2 sensor to read in my serial monitor. I've tried looking at

many different examples of code that others have posted in their success stories. When I open my serial

monitor, all I see is that the sensor is preheating. Nothing after that. The sensor needs about 3 minutes

to heat up, and I've waiting for 20 minutes to no avail.

Serial Monitor looks like this:

MHZ 19B
Preheating...

But I don't get anything after that. I just keep seeing more ............... the longer I wait.

I hope that I am not doomed to fail! Please if you can help, with gentle language for simple folk :slight_smile:

The MH-Z19B has the following connected to the Arduino Nano:

MH-Z19B Arduino Nano

Vin <=======================> 5V

GND <=======================> GND

PWM <=======================> D10

RX <=======================> TX1

TX <=======================> RX0

Below is the code that I am using.

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

// pin for pwm reading
#define CO2_IN 10

// pin for uart reading
#define MH_Z19_RX 1
#define MH_Z19_TX 0

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

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

// 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);
}

MH-Z19B.txt (1.2 KB)

You're using the hardware serial pins for debugging messages and talking to your sensor.

Put the sensor on some other pins, like in the examples for the library.

Thanks for the quick response!

If I wired the RX/TX from the MH-Z19B to say the D6/D7 pins on the Arduino Nano...is that what you mean?

Yes. You will need to make corresponding changes in your code too - here:

// pin for uart reading
#define MH_Z19_RX 1
#define MH_Z19_TX 0

Just reconnected the RX to D7 and the TX to D6 but I still have the same result :frowning:

I also updated the code there.

// pin for uart reading
#define MH_Z19_RX 7 // D7
#define MH_Z19_TX 6 // D6

Post the latest version of your code, in code tags please.

Also, it might be worth uncommenting the stuff that turns debugging on.

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

// pin for pwm reading
#define CO2_IN 10

// pin for uart reading
#define MH_Z19_RX 7  // D7
#define MH_Z19_TX 6  // D6


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

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

  // 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);
}

I still only see this in the Serial Monitor...

MHZ 19B
MHZ: debug mode ENABLED
Preheating...........................

If that is literally what you saw, you didn't wait long enough. Also, I don't know anything about that particular sensor, but many with a burn in period need far longer than that.

I've been letting it run for 15 minutes at this point...and yes above is all I see on the serial monitor except now it's:

MHZ 19B
MHZ: debug mode ENABLED
Preheating...

Where did you get the library?

The version I'm looking at just waits three minutes based on millis. I had assumed it was checking something on the sensor, but no.

I downloaded the latest one, version 1.2.0

MH_Z_CO2_Sensors-1.2.0.zip (6.47 KB)

Looks like the same one. I can't see why it never ends preheat.

I would try commenting out all the code that checks for preheating and replace it with three minutes of delay.

So I took out the preheating part...and added in a 3 minute delay. It definitely does something...although only PWM seems to work and if it is indeed working I should be dying right now...this is what I see:

----- Time from start: 310 s
PPMuart: n/a-- reading CO2 from pwm ...

PPM PWM: 2175

, PPMpwm: 2175, Temperature: n/a


----- Time from start: 317 s
PPMuart: n/a-- reading CO2 from pwm ...

PPM PWM: 2145

, PPMpwm: 2145, Temperature: n/a


Here is the updated code:

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

// pin for pwm reading
#define CO2_IN 10   //D10

// pin for uart reading
#define MH_Z19_RX 7  // D7
#define MH_Z19_TX 6  // D6


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

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

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

 delay(180000); // 3 minute delay for warmup
}

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);
}

Any thoughts to why I can't see the uart readings?

Don't know. Bad sensor? Rx and Tx reversed? Other wiring issues? Tricky thing to debug. It's time for dinner here, I'll take another look at the library tomorrow.

Print what you get from the readCO2UART call. It can return several different negative status numbers to indicate why it didn't get a reading.

Also, I'm still baffled as to why the isPreHeating function never returned false. Can you post the copy from your library?