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