MH-Z19C works on Uno but not on Mega

Hello guys,

my MH-Z19C works fine when connected to my Arduino Uno. After wiring it to my new Arduino Mega it stopped working. What tweaks are there to make when switching between those two different Arduinos?

My wiring:
sensor Vin → Arduino pin 5V
sensor GND → Arduino pin GND
sensor RX → Arduino pin 6
sensor TX → Arduino pin 7

sketch i used:

#include <Arduino.h>
#include "MHZ19.h"                                        
#include <SoftwareSerial.h>                                // Remove if using HardwareSerial

#define RX_PIN 6                                          // Rx pin which the MHZ19 Tx pin is attached to
#define TX_PIN 7                                          // Tx pin which the MHZ19 Rx pin is attached to
#define BAUDRATE 9600                                      // Device to MH-Z19 Serial baudrate (should not be changed)

MHZ19 myMHZ19;                                             // Constructor for library
SoftwareSerial mySerial(RX_PIN, TX_PIN);                   // (Uno example) create device to MH-Z19 serial

unsigned long getDataTimer = 0;

void setup()
{
    Serial.begin(9600);                                     // Device to serial monitor feedback

    mySerial.begin(BAUDRATE);                               // (Uno example) device to MH-Z19 serial start   
    myMHZ19.begin(mySerial);                                // *Serial(Stream) refence must be passed to library begin(). 

    myMHZ19.autoCalibration();                              // Turn auto calibration ON (OFF autoCalibration(false))
}

void loop()
{
    if (millis() - getDataTimer >= 2000)
    {
        int CO2; 

        /* note: getCO2() default is command "CO2 Unlimited". This returns the correct CO2 reading even 
        if below background CO2 levels or above range (useful to validate sensor). You can use the 
        usual documented command with getCO2(false) */

        CO2 = myMHZ19.getCO2();                             // Request CO2 (as ppm)
        
        Serial.print("CO2 (ppm): ");                      
        Serial.println(CO2);                                
        delay(2000);
     }
}

The output i get:
Pic1

Many thanks in advance

The Mega has 3 extra hardware serial ports so there is no need for software serial.

try this

#include <SoftwareSerial.h>
SoftwareSerial co2Serial(3, 2); // define MH-Z19 RX TX
const  byte cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
byte response[9]; // for CO2-Sensor answer

int co2 = 8888;

void setup() {
  Serial.begin(115200);
  co2Serial.begin(9600);
  // Serial.println("Start.");
}

void loop() {
  if (((millis() % 5000) < 10 ) ) {
    readCO2UART();
    delay(10);
  }
}

void readCO2UART() {
  co2Serial.write(cmd, 9); //request PPM CO2
  //  Serial.println("co2Serial.write.");

  // clear the buffer
  memset(response, 0, 9);
  while (co2Serial.available() == 0) {
    delay(500);
  }
  if (co2Serial.available() > 0) {
    co2Serial.readBytes(response, 9);
  }
  byte check = getCheckSum(response);
  if (response[8] != check) {
    //    Serial.println("Checksum not OK!");
    //    Serial.print("Received: ");
    //    Serial.println(response[8]);
    //    Serial.print("Should be: ");
    //    Serial.println(check);
  }
  else {
    // ppm
    co2 = 256 * (int)response[2] + response[3];
    Serial.print("PPM UART: ");
    Serial.println(co2);
    Serial.print("Temperature: ");
    Serial.println(response[4] - 40);
  }
  return ;
}

byte getCheckSum(byte *pack) {
  byte checksum = 0;
  for (byte i = 1; i < 8; i++) {
    checksum += pack[i];
  }
  checksum = 0xff - checksum + 1;
  return checksum;
}

// end of code.
1 Like

@groundFungus well couldn't figure it out how to do that/ it also didn't work, so I came back to what I thought I know :frowning:

@kolaha thanks! reminds me a lot of what I saw here Problem with CO2 sensor MH-Z19B - cannot read values but this also doesn't give me any output :frowning:

Do you know, this sensor has warm up time 2 minute?

@kolaha yes I do, but I get no output

My Setup:

Output:

#include <SoftwareSerial.h>
SoftwareSerial co2Serial(7, 6); // define MH-Z19 RX TX
const  byte cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
byte response[9]; // for CO2-Sensor answer

int co2 = 8888;

void setup() {
  Serial.begin(115200);
  co2Serial.begin(9600);
  // Serial.println("Start.");
}

void loop() {
  if (((millis() % 1000) < 10 ) ) {
    readCO2UART();
    delay(10);
  }
}

void readCO2UART() {
  co2Serial.write(cmd, 9); //request PPM CO2
  Serial.println("co2Serial.write.");

  // clear the buffer
  memset(response, 0, 9);
  while (co2Serial.available() == 0) {
    delay(500);
  }
  if (co2Serial.available() > 0) {
    co2Serial.readBytes(response, 9);
  }
  byte check = getCheckSum(response);
  if (response[8] != check) {
    //    Serial.println("Checksum not OK!");
    //    Serial.print("Received: ");
    //    Serial.println(response[8]);
    //    Serial.print("Should be: ");
    //    Serial.println(check);
  }
  else {
    //ppm
    co2 = 256 * (int)response[2] + response[3];
    Serial.print("PPM UART: ");
    Serial.println(co2);
    Serial.print("Temperature: ");
    Serial.println(response[4] - 40);
  }
  return ;
}

byte getCheckSum(byte *pack) {
  byte checksum = 0;
  for (byte i = 1; i < 8; i++) {
    checksum += pack[i];
  }
  checksum = 0xff - checksum + 1;
  return checksum;
}

// end of code.

make output of response to ser port

is sensor blinking?
switch pls RX and TX

What exactly to you mean with:"make output of response to ser port"

Yes,
I did numerous times

You are foolish to use Software Serial on a Mega, and your time is better spent trying to get Serial1,2,or 3 working instead of using various pins for software serial without reading the documentation.

  • Not all pins on the Mega and Mega 2560 support change interrupts, so only the following can be used for RX: 10, 11, 12, 13, 14, 15, 50, 51, 52, 53, A8 (62), A9 (63), A10 (64), A11 (65), A12 (66), A13 (67), A14 (68), A15 (69).
1 Like

Indeed, I am! :disappointed_relieved:
I am now happy that it works with
SoftwareSerial co2Serial(10, 11); // define MH-Z19 RX TX

Many thanks!

to make it complete, it also works with my first sketch:

#include <Arduino.h>
#include "MHZ19.h"                                        
#include <SoftwareSerial.h>                                // Remove if using HardwareSerial

#define RX_PIN 10                                          // Rx pin which the MHZ19 Tx pin is attached to
#define TX_PIN 11                                          // Tx pin which the MHZ19 Rx pin is attached to
#define BAUDRATE 9600                                      // Device to MH-Z19 Serial baudrate (should not be changed)

MHZ19 myMHZ19;                                             // Constructor for library
SoftwareSerial mySerial(RX_PIN, TX_PIN);                   // (Uno example) create device to MH-Z19 serial

unsigned long getDataTimer = 0;

void setup()
{
    Serial.begin(9600);                                     // Device to serial monitor feedback

    mySerial.begin(BAUDRATE);                               // (Uno example) device to MH-Z19 serial start   
    myMHZ19.begin(mySerial);                                // *Serial(Stream) refence must be passed to library begin(). 

    myMHZ19.autoCalibration();                              // Turn auto calibration ON (OFF autoCalibration(false))
}

void loop()
{
    if (millis() - getDataTimer >= 2000)
    {
        int CO2; 

        /* note: getCO2() default is command "CO2 Unlimited". This returns the correct CO2 reading even 
        if below background CO2 levels or above range (useful to validate sensor). You can use the 
        usual documented command with getCO2(false) */

        CO2 = myMHZ19.getCO2();                             // Request CO2 (as ppm)
        
        Serial.print("CO2 (ppm): ");                      
        Serial.println(CO2);                                

        getDataTimer = millis();
    }
}

You have been told twice to NOT use SoftwareSerial on a Mega, and still you do.

Study the MultiSerial example that comes with the IDE.
Leo..

@Wawa Thanks for the reminder! Is this what you expected?

#include <MHZ19.h>

MHZ19 mhz(&Serial1);

void setup()
{
  Serial.begin(9600);
  Serial.println(F("Starting..."));

  Serial1.begin(9600);
}

void loop()
{
  MHZ19_RESULT response = mhz.retrieveData();
  
    Serial.print(F("CO2: "));
    Serial.println(mhz.getCO2());
  
  
  delay(2000);
}

My output:

hello. i tried to use ur code but why i cant upload it? the error messages is "no matching function for call to 'MHZ19::MHZ19(HardwareSerial&)' do u know how to solve it? sorry i just new to arduino. thankyou

I think there are several errors in the code posted in Reply #13.

Try this modification of the basic library example code. It compiles for the Mega.

#include <Arduino.h>
#include "MHZ19.h"                                        
//#include <SoftwareSerial.h>                                // Remove if using HardwareSerial

//#define RX_PIN 10                                          // Rx pin which the MHZ19 Tx pin is attached to
//#define TX_PIN 11                                          // Tx pin which the MHZ19 Rx pin is attached to
//#define BAUDRATE 9600                                      // Device to MH-Z19 Serial baudrate (should not be changed)

MHZ19 myMHZ19;                                             // Constructor for library
//SoftwareSerial mySerial(RX_PIN, TX_PIN);                   // (Uno example) create device to MH-Z19 serial

unsigned long getDataTimer = 0;

void setup()
{
    Serial.begin(9600); // Device to serial monitor feedback
    Serial1.begin(9600);
    //mySerial.begin(BAUDRATE);                               // (Uno example) device to MH-Z19 serial start   
    //myMHZ19.begin(mySerial); // *Serial(Stream) refence must be passed to library begin(). 
     myMHZ19.begin(Serial1);
      
    myMHZ19.autoCalibration();                              // Turn auto calibration ON (OFF autoCalibration(false))
}

void loop()
{
    if (millis() - getDataTimer >= 2000)
    {
        int CO2; 

        /* note: getCO2() default is command "CO2 Unlimited". This returns the correct CO2 reading even 
        if below background CO2 levels or above range (useful to validate sensor). You can use the 
        usual documented command with getCO2(false) */

        CO2 = myMHZ19.getCO2();                             // Request CO2 (as ppm)
        
        Serial.print("CO2 (ppm): ");                      
        Serial.println(CO2);                                

        int8_t Temp;
        Temp = myMHZ19.getTemperature();                     // Request Temperature (as Celsius)
        Serial.print("Temperature (C): ");                  
        Serial.println(Temp);                               

        getDataTimer = millis();
    }
}
1 Like

thank you so much!

thanks for ur help. anyway, im new on this sensor and i just read the datasheet recently. but i still dont understand deeply about the callibration. does the autocalibration in the code already calibrate the sensor? or still i need to do zero calibration and span calibration? thankyou

im using mh-z19b sensor btw, not mh-z19c

Here the link to the Library Read Me on Git Hub which has information about calibration and auto calibration.

It appears to recommend performing a manual zero calibration (400 ppm) and leaving the span alone.

1 Like

thanks!