I'm using a MHZ19B CO2 sensor with an ESP32 D1 Mini communicating over UART coded in the Arduino IDE to pull CO2 concentration and temperature from the sensor (I really only care about CO2 concentration). My code works, but it can't seem to initialize the sensor right on boot unless I swap the UART pins, then swap them back. To be specific, the following is what happens in sequence from what I can see in the output:
Load the code. Outputs random characters in a repeating loop (I think this is happening in the setup when it tries to initialize the sensor). Remove both of the UART pins, nothing changes in the output, maybe some different characters in the random repeating loop. Put UART pins back in reverse order (tx-tx and rx-rx), random characters stop and outputs CO2 being 0 (because it's not getting data from the sensor). Reinstall UART pins correctly, starts outputting what I think are correct CO2 values.
Why is this happening? Are there any good workarounds to prevent this issue? Code, output and links are below.
Ps. Sorry if this is not how I should have posted my code, it's my first time using code blocks.
CO2 sensor: MH-Z19B ndir CO2 sensor for indoor air quality monitoring--Winsen
Sensor library (my code is adapted from the basic usage example): GitHub - WifWaf/MH-Z19: For Arduino Boards (&ESP32). Additional Examples/Commands., Hardware/Software Serial
Microcontroller: Amazon.com: ACEIRMC D1 Mini NodeMCU ESP32 ESP-WROOM-32 WLAN WiFi Bluetooth IoT Development Board 5V Compatible for Arduino (3pcs) : Electronics
#include <Arduino.h>
#include "MHZ19.h"
#define RX_PIN 10 // Rx pin which the MHZ19 Tx pin is attached to
#define TX_PIN 9 // 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
#if defined(ESP32)
HardwareSerial mySerial(2); // On ESP32 we do not require the SoftwareSerial library, since we have 2 USARTS available
#else
#include <SoftwareSerial.h> // Remove if using HardwareSerial or non-uno compatible device
SoftwareSerial mySerial(RX_PIN, TX_PIN); // (Uno example) create device to MH-Z19 serial
#endif
unsigned long getDataTimer = 0;
void setup()
{
Serial.begin(9600); // Device to serial monitor feedback
mySerial.begin(9600, SERIAL_8N1, RX_PIN, TX_PIN); // (Uno example) device to MH-Z19 serial start
myMHZ19.begin(mySerial); // *Serial(Stream) reference 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();
}
}
19:36:12.610 -> a@�tC cbP1�F��%5�
�BB]
19:36:13.684 ->
,�M���������,�u�1X�A���GA�R%�f@�܉%�����'#e��"V��L&02e=
��t'^������ʍ��dHa�*#�'z? b\u,Ŏ� � �"�K�6u�&�*���Y�
!B/ı.i� (� ���@�CO2 (ppm): 0
19:36:26.273 -> CO2 (ppm): 0
19:36:28.776 -> CO2 (ppm): 0
19:36:31.284 -> CO2 (ppm): 0
19:36:33.804 -> CO2 (ppm): 0
19:36:36.311 -> CO2 (ppm): 0
19:36:38.352 -> CO2 (ppm): 624
19:36:40.374 -> CO2 (ppm): 629
19:36:42.410 -> CO2 (ppm): 630
19:36:44.488 -> CO2 (ppm): 631
19:36:46.520 -> CO2 (ppm): 633