0

I would like to connect a CO2 sensor to the Wemos D1. I would like it to work via UART (RX, TX) and not the PWM pin. I've encountered numerous libraries on Github, but I can't seem to get it working. I've connected the following things:

enter image description here

I've tried a lot of snippets from all over the internet, and a lot of libraries on Github, but I can't seem to get it working. For the sake of this question, I am going to use this advanced library.

This is my code:

#include <Arduino.h>
#include "MHZ19.h"                                         // include main library
#include <SoftwareSerial.h>                                // Remove if using HardwareSerial or non-uno library compatable device

#define RX_PIN D1                                          // Rx pin which the MHZ19 Tx pin is attached to
#define TX_PIN D2                                          // Tx pin which the MHZ19 Rx pin is attached to
#define BAUDRATE 9600                                      // Native to the sensor (do not change)

MHZ19 myMHZ19;                                             // Constructor for MH-Z19 class
SoftwareSerial mySerial(RX_PIN, TX_PIN);                   // Uno example
//HardwareSerial mySerial(1);                              // ESP32 Example

unsigned long getDataTimer = 0;                             // Variable to store timer interval

void setup()
{
    Serial.begin(9600);                                     // For ESP32 baudarte is 115200 etc.
    mySerial.begin(BAUDRATE);                               // Uno example: Begin Stream with MHZ19 baudrate
    //mySerial.begin(BAUDRATE, SERIAL_8N1, RX_PIN, TX_PIN); // ESP32 Example
    myMHZ19.begin(mySerial);                                // *Important, Pass your Stream reference 
    myMHZ19.autoCalibration();                              // Turn auto calibration ON (disable with autoCalibration(false))
}

void loop(){
    if (millis() - getDataTimer >= 2000)                    // Check if interval has elapsed (non-blocking delay() equivilant)
    {
        int CO2;                                            // Buffer for 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;                                         // Buffer for temperature
        Temp = myMHZ19.getTemperature();                     // Request Temperature (as Celsius)
        Serial.print("Temperature (C): ");                  
        Serial.println(Temp);                               

        getDataTimer = millis();                            // Update interval
    }
}

I am constantly getting this:

19:39:59.750 -> !Error: Timed out waiting for response
19:39:59.784 -> !ERROR: Failed to verify connection(1) to sensor. Failed to stablise
19:39:59.853 -> !ERROR: Initial communication errorCode recieved
19:40:00.272 -> !Error: Timed out waiting for response
19:40:00.758 -> !Error: Timed out waiting for response
19:40:00.792 -> CO2 (ppm): 0
19:40:01.280 -> !Error: Timed out waiting for response
19:40:01.315 -> Temperature (C): -17

Am I connecting something wrong or what am I doing wrong?

EDIT: Version using only the serial instead of library that also doesn't work:

#include <SoftwareSerial.h>
SoftwareSerial co2Serial(3, 1);
unsigned long startTime = millis();

void setup() {
  Serial.begin(9600);
  co2Serial.begin(9600);
  pinMode(9, INPUT);
}

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(byte *packet) {
  byte i;
  unsigned char checksum = 0;
  for (i = 1; i < 8; i++) {
    checksum += packet[i];
  }
  checksum = 0xff - checksum;
  checksum += 1;
  return checksum;
}
  • You do know you need to cross RX and TX with UART communications, don't you? TX connects to RX, and RX connects to TX. – Majenko Aug 18 at 17:53
  • I know, tried it both ways (drew it wrong in this picture), neither works – Mark D Aug 18 at 17:58
  • did you try to send the commands without using a MHZ19 library? – jsotola Aug 18 at 22:51
  • Yes, also no response, see the edit – Mark D Aug 19 at 17:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.