Arduino Mega 2560 Serial2

Please I have problem with this sketch, Arduino Mega 2560 report CRC error in serial monitor.
When I use MH-Z19B with Nano and softwareSerial, it works.

byte cmd[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79}; 
unsigned char response[9];



void setup() {
  Serial.begin(9600);
  Serial2.begin(9600);
}

void loop() 
{

  Serial2.write(cmd, 9);
  memset(response, 0, 9);
  Serial2.readBytes(response, 9);
  int i;
  byte crc = 0;
  for (i = 1; i < 8; i++) crc+=response[i];
  crc = 255 - crc;
  crc++;

  if ( !(response[0] == 0xFF && response[1] == 0x86 && response[8] == crc) ) {
    Serial.println("CRC error: " + String(crc) + " / "+ String(response[8]));
  } else {
    unsigned int responseHigh = (unsigned int) response[2];
    unsigned int responseLow = (unsigned int) response[3];
    unsigned int ppm = (256*responseHigh) + responseLow;
    
    Serial.print ("koncentrace CO2: ");
    Serial.print(ppm);
    Serial.print(" PPM ");
    
  }
  delay(5000);
}

Please read the sticky post read this before posting a programming question and add code tags to the code you posted to prevent parts of it being interpreted as HTML tags

Please I have problem with this sketch, Arduino Mega 2560 report CRC error in serial monitor.
When I use MH-Z19B with Nano and softwareSerial, it works.

Serial2.readBytes(response, 9);

Is the response back from the sensor the same in both cases?

cattledog:

Serial2.readBytes(response, 9);

Is the response back from the sensor the same in both cases?

I don´t understand you, please explain.

I really cannot understand why there would be any difference between hardware and software serial in relation to the checksum.

I was trying to establish that the data received was the same in both cases. Your code only indicates an error. Perhaps no data is sent or received because you have incorrect hardware Serial2 connections.

Screen from serial monitor.

The difference is probably the blocking nature of SoftWareSerial.

With hardware the command gets pushed into the transmit buffer,
so the response is read even before the request was sent.

With SoftWareSerial the data is bit banged out IIRC.

  Serial2.write(cmd, 9);
  memset(response, 0, 9);
  Serial2.readBytes(response, 9);

Screen from serial monitor.

You still have not shown any evidence that any response is received. Serial2.readBytes() should return the number of bytes read. Try this code to see what is coming back from the sensor.

byte cmd[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79}; 
unsigned char response[9];

void setup() {
  Serial.begin(9600);
  Serial2.begin(9600);
}

void loop() 
{

  Serial2.write(cmd, 9);
  memset(response, 0, 9);
  byte value = Serial2.readBytes(response, 9);
  Serial.print("Received bytes = ");
  Serial.println(value);
  int i;
  byte crc = 0;
  for (i = 1; i < 8; i++) 
  {
  crc+=response[i];
  Serial.println(response[i]);
  }
  crc = 255 - crc;
  crc++;

  if ( !(response[0] == 0xFF && response[1] == 0x86 && response[8] == crc) ) {
    Serial.println("CRC error: " + String(crc) + " / "+ String(response[8]));
  } else {
    unsigned int responseHigh = (unsigned int) response[2];
    unsigned int responseLow = (unsigned int) response[3];
    unsigned int ppm = (256*responseHigh) + responseLow;
    
    Serial.print ("koncentrace CO2: ");
    Serial.print(ppm);
    Serial.print(" PPM ");
    
  }
  delay(5000);
}

@Whandall

With hardware the command gets pushed into the transmit buffer,
so the response is read even before the request was sent.

If this is the case, try adding a small delay after Serial2.write(cmd, 9); or perhaps call Serial2.flush(); which should empty the outgoing buffer.

cattledog:
@Whandall
If this is the case, try adding a small delay after Serial2.write(cmd, 9); or perhaps call Serial2.flush(); which should empty the outgoing buffer.

Better would be to use a proper non blocking character reception.

byte cmd[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79}; 
unsigned char response[9];

void setup() {
  Serial.begin(9600);
  Serial2.begin(9600);
}

void loop() 
{

  Serial2.write(cmd, 9);
  memset(response, 0, 9);
  byte value = Serial2.readBytes(response, 9);
  Serial.print("Received bytes = ");
  Serial.println(value);
  int i;
  byte crc = 0;
  for (i = 1; i < 8; i++) 
  {
  crc+=response[i];
  Serial.println(response[i]);
  }
  crc = 255 - crc;
  crc++;

  if ( !(response[0] == 0xFF && response[1] == 0x86 && response[8] == crc) ) {
    Serial.println("CRC error: " + String(crc) + " / "+ String(response[8]));
  } else {
    unsigned int responseHigh = (unsigned int) response[2];
    unsigned int responseLow = (unsigned int) response[3];
    unsigned int ppm = (256*responseHigh) + responseLow;
    
    Serial.print ("koncentrace CO2: ");
    Serial.print(ppm);
    Serial.print(" PPM ");
    
  }
  delay(5000);
}

Screen from serial monitor after upload this sketch.
Serial2.flush() or delay didn´t help.

Screen from serial monitor after upload this sketch.

You are not receiving anything. Please now show the same screen from the software serial version of the sketch you just ran.

Can you please provide a drawing of how the software serial pins and the hardware serial pins are connected to the pins of the sensor.

cattledog:
You are not receiving anything. Please now show the same screen from the software serial version of the sketch you just ran.

Can you please provide a drawing of how the software serial pins and the hardware serial pins are connected to the pins of the sensor.

Board Nano Clone works, but Mega2560 Keyestudio with same wiring on analog, digital pins or Serial2 doesn´t works. I use this sketch:

#include <SoftwareSerial.h>
SoftwareSerial co2Serial(A3, A4); // define MH-Z19 RX TX
unsigned long startTime = millis();
 
void setup() {
  Serial.begin(9600);
  co2Serial.begin(9600);
}
 
void loop() {
  Serial.println("------------------------------");
  Serial.print("Time from start: ");
  Serial.print((millis() - startTime) / 1000);
  Serial.println(" s");
  int ppm_uart = readCO2UART();
  delay(5000);
}

int readCO2UART(){
  byte cmd[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79};
  byte response[9]; // for answer

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

  // clear the buffer
  memset(response, 0, 9);
  int i = 0;
  while (co2Serial.available() == 0) {
//    Serial.print("Waiting for response ");
//    Serial.print(i);
//    Serial.println(" s");
    delay(1000);
    i++;
  }
  if (co2Serial.available() > 0) {
      co2Serial.readBytes(response, 9);
  }
  // print out the response in hexa
  for (int i = 0; i < 9; i++) {
    Serial.print(String(response[i], HEX));
    Serial.print("   ");
  }
  Serial.println("");

  // checksum
  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);
  }
  
  // ppm
  int ppm_uart = 256 * (int)response[2] + response[3];
  Serial.print("PPM UART: ");
  Serial.println(ppm_uart);

  // temp
  byte temp = response[4] - 40;
  Serial.print("Temperature? ");
  Serial.println(temp);

  // status
  byte status = response[5];
  Serial.print("Status? ");
  Serial.println(status); 
  if (status == 0x40) {
    Serial.println("Status OK"); 
  }
  
  return ppm_uart;
}

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

serial monitor:

22:15:50.678 -> ------------------------------
22:15:50.725 -> Time from start: 0 s
22:15:50.725 -> Sending CO2 request...
22:15:51.708 -> ff   86   3   d6   3e   0   0   0   63   
22:15:51.755 -> PPM UART: 982
22:15:51.755 -> Temperature? 22
22:15:51.802 -> Status? 0
22:15:56.745 -> ------------------------------
22:15:56.792 -> Time from start: 6 s
22:15:56.792 -> Sending CO2 request...
22:15:57.776 -> ff   86   3   d8   3e   0   0   0   61   
22:15:57.811 -> PPM UART: 984
22:15:57.811 -> Temperature? 22
22:15:57.856 -> Status? 0
22:16:02.777 -> ------------------------------
22:16:02.811 -> Time from start: 12 s
22:16:02.811 -> Sending CO2 request...
22:16:03.811 -> ff   86   3   d9   3e   0   0   0   60   
22:16:03.857 -> PPM UART: 985
22:16:03.857 -> Temperature? 22
22:16:03.903 -> Status? 0
22:16:08.841 -> ------------------------------
22:16:08.888 -> Time from start: 18 s
22:16:08.888 -> Sending CO2 request...
22:16:09.856 -> ff   86   3   d8   3e   0   0   0   61   
22:16:09.903 -> PPM UART: 984
22:16:09.903 -> Temperature? 22
22:16:09.950 -> Status? 0

PetrKoz:
Board Nano Clone works, but Mega2560 Keyestudio with same wiring on analog, digital pins or Serial2 doesn´t works. I use this sketch:

so did you actually connect the SoftwareSerial on the Mega as well ? Then there is no explanation.
This way of blocking actually makes sense (until it works then you should use a non-blocking method )

   Serial.print("Waiting for response ");  
    while (co2Serial.available() < 9) {
      Serial.print(".");
      delay(200);
      i++;
    }
  Serial.println(" 9 Bytes received");  
  if (co2Serial.available() >8) { // this condition is always true of course
      co2Serial.readBytes(response, 9);
  }

If you are going to read 9 bytes then you may as well wait until they are all there.

so did you actually connect the SoftwareSerial on the Mega as well ? Then there is no explanation.

I agree.

If software serial works on the mega, I would try Serial1 or Serial3 on the mega in case the Serial2 pins are defective. Are you absolutely certain that you have cross connected the mega rx to sensor tx and mega tx to sensor rx.

If software serial does not work on the mega then the mystery deepens.

Be careful with selection of the software serial pins on the Mega.

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).

Foto of wiring Nano and Mega, Mega doesn´t work, when I change A9 and A10, serial monitor write this:

17:52:42.935 -> ------------------------------
17:52:42.935 -> Time from start: 0 s
17:52:42.982 -> Sending CO2 request...
17:52:43.919 -> ff   86   13   88   3e   0   0   0   a1   
17:52:43.966 -> PPM UART: 5000
17:52:44.013 -> Temperature? 22
17:52:44.013 -> Status? 0
17:52:48.967 -> ------------------------------
17:52:49.013 -> Time from start: 6 s
17:52:49.013 -> Sending CO2 request...
17:52:49.982 -> ff   86   13   88   3e   0   0   0   a1   
17:52:50.029 -> PPM UART: 5000
17:52:50.029 -> Temperature? 22
17:52:50.076 -> Status? 0
17:52:55.013 -> ------------------------------

OK, you're making progress. With the functional software serial pins on the Mega you are getting data.

The module photo shows a Green wire attached to RX and a Yellow wire attached to TX. The working nano has the green wire attached to A4 and the Yellow to A3. The software serial constructor is

SoftwareSerial co2Serial(A3, A4);
//SoftwareSerial mySerial (rxPin, txPin);

Note, that the TX wire of the module is connect to the RX pin of the Arduino and the RX wire of the module is connect to the TX pin of the arduino.

You now just need to get those connects right for the hardware serial ports of the Mega.

The Arduino Mega has three additional serial ports: Serial1 on pins 19 (RX) and 18 (TX), Serial2 on pins 17 (RX) and 16 (TX), Serial3 on pins 15 (RX) and 14 (TX).

Let's see a photo which shows the connections to the module and the connections to one of the hardware serial ports of the Mega. As previously suggested, you can try any of the three ports if one of them is actually defective when wired correctly.

I really don´t understand it, because I tried to swap the RX and TX on Arduino Mega and sensor didn´t work, but now Seral2 working. I thank you guys very much for your help, itś valuable experiences for me, sorry if I was annoying.

unsigned long startTime = millis();
 
void setup() {
  Serial.begin(9600);
  Serial2.begin(9600);
}
 
void loop() {
  Serial.println("------------------------------");
  Serial.print("Time from start: ");
  Serial.print((millis() - startTime) / 1000);
  Serial.println(" s");
  int ppm_uart = readCO2UART();
  delay(5000);
}

int readCO2UART(){
  byte cmd[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79};
  byte response[9]; // for answer

  Serial.println("Sending CO2 request...");
  Serial2.write(cmd, 9); //request PPM CO2

  // clear the buffer
  memset(response, 0, 9);
  int i = 0;
  while (Serial2.available() == 0) {
//    Serial.print("Waiting for response ");
//    Serial.print(i);
//    Serial.println(" s");
    delay(1000);
    i++;
  }
  if (Serial2.available() > 0) {
      Serial2.readBytes(response, 9);
  }
  // print out the response in hexa
  for (int i = 0; i < 9; i++) {
    Serial.print(String(response[i], HEX));
    Serial.print("   ");
  }
  Serial.println("");

  // checksum
  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);
  }
  
  // ppm
  int ppm_uart = 256 * (int)response[2] + response[3];
  Serial.print("PPM UART: ");
  Serial.println(ppm_uart);

  // temp
  byte temp = response[4] - 40;
  Serial.print("Temperature? ");
  Serial.println(temp);

  // status
  byte status = response[5];
  Serial.print("Status? ");
  Serial.println(status); 
  if (status == 0x40) {
    Serial.println("Status OK"); 
  }
  
  return ppm_uart;
}

byte getCheckSum(char *packet) {
  byte i;
  unsigned char checksum = 0;
  for (i = 1; i < 8; i++) {
    checksum += packet[i];
  }
  checksum = 0xff - checksum;
  checksum += 1;
  return checksum;
}
20:21:03.952 -> ------------------------------
20:21:03.999 -> Time from start: 0 s
20:21:03.999 -> Sending CO2 request...
20:21:04.982 -> ff   86   4   90   3f   0   0   0   a7   
20:21:05.029 -> PPM UART: 1168
20:21:05.029 -> Temperature? 23
20:21:05.029 -> Status? 0
20:21:09.990 -> ------------------------------
20:21:10.036 -> Time from start: 6 s
20:21:10.036 -> Sending CO2 request...
20:21:11.019 -> ff   86   4   90   3f   0   0   0   a7   
20:21:11.066 -> PPM UART: 1168
20:21:11.066 -> Temperature? 23
20:21:11.066 -> Status? 0
20:21:16.013 -> ------------------------------
20:21:16.060 -> Time from start: 12 s
20:21:16.107 -> Sending CO2 request...
20:21:17.043 -> ff   86   4   95   3f   0   0   0   a2   
20:21:17.090 -> PPM UART: 1173
20:21:17.090 -> Temperature? 23
20:21:17.136 -> Status? 0
20:21:22.050 -> ------------------------------