I'm trying to read data from MH-Z19B sensor to NodeMCU v2 board with a simple circuit like this.

enter image description here

Some key points, which could be not that obvious from picture:
- sensor has separate power supply of 4 AAs, providing ~5,5V
- sensor's TX connected to GPIO15 (TX D2) of NodeMCU
- sensor's RX connected to GPIO13 (RX D2) of NodeMCU

And here is my sketch:

const byte readCommand[] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; // according to datasheet
unsigned char response[9];

void setup() {
  // according to datasheet, sensor uses 9600 baud, 8 databits and 1 stopbit
  // with parity NONE, which I believe corresponds to default config SERIAL_8N1 

void loop() {

    //  ... check if it is time to measure

    Serial.swap(); // switch to sensor

    Serial.write(readCommand, sizeof(readCommand));

    memset(response, 0, sizeof(response));

    int attempts = 5;
    int available = Serial.available();
    while(available < sizeof(response) && attempts > 0) {
        available = Serial.available();

    Serial.readBytes(response, sizeof(response));

    Serial.swap(); // switch back to console

    // print out the response in hex
    for (int i = 0; i < sizeof(response); i++) {
      Serial.print(String(response[i], HEX));
      Serial.print("   ");

    // ...process the response according to protocol

The Problem

For some reason after sending command to serial I get an answer exactly the same as command is although the structure of answer expected to be different. Of course datasheet says nothing about situations like this.

ff 86 .. .. 0 0 0 0 CRC

Reality (same bytes I sent as a command)

ff   1   86   0   0   0   0   0   79 

Other notes:
- I got exactly the same when tried to use SoftwareSerial with D1 & D2 pins
- connecting TX to RX respectively on both sensor and MCU results in reading failure
- I tried to pull everything while available from serial, there are only my expected 9 bytes
- my soldering skills are far from ideal, but I'm pretty sure tx/rx on the sensor are connected properly

I'm new to all this stuff, so it is completely possible that there is ridiculously silly, but crucial mistake, so would appreciate any help on this. And I understand that sensor also has additional interfaces to obtain the value, but as I mentioned I'm a newbie and wanted to familiarize myself with UART as this is something new for me.

UPD 1:
I didn't use level conversion for sensor output as datasheet says:
enter image description here
Assuming this I thought that sensor provides logical level conversion itself. Did I get it wrong?

UPD 2:
I got back to proper TX - RX connection just to check out what is going on exactly to describe that "reading failure" problem with more details. It seems that Serial.available() returns 0 after I send command so this loop gets stopped after 5 attempts:

while(available < sizeof(response) && attempts > 0)
  • It has to be RX to TX with UART. That it results in reading failure is another problem. What exactly do you mean by "reading failure"? – chrisl Apr 30 '20 at 20:10
  • You don't step down the TX voltage of the sensor from 5V to 3.3V for the NodeMCU. That is risky, as you might destroy the RX pin of the NodeMCU – chrisl Apr 30 '20 at 20:14
  • @chrisl thank you for your comments, I updated my question with some details regarding that reading failure case and my assumptions I took from datasheet which made me think I don't need 3,3 level conversion. – Viacheslav May 1 '20 at 7:02

It says in your description that you have the Rx connected to Rx and the Tx connected to Tx. That's backwards. What one transmits the other needs to receive. When you have a conversation with someone, do you talk into their mouth and listen to their ears? You should have Rx-Tx and Tx-Rx.

You also need to be sure that it is OK to feed a 5V Tx into that Rx pin. On some ESP8266 boards it is and on most it isn't. If you don't have one of the boards that specifically has circuitry built in to handle 5V inputs then you will fry your NodeMCU

  • Thank you for your answer. I added a screenshot from sensor's datasheet which says that it provides UART 3,3 so I thought that level conversion was made on sensor's side. Did I get it wrong? – Viacheslav May 1 '20 at 7:06
  • If it does give 3V3 then you're safe. It appeared from your question that it was 5V. – Delta_G May 1 '20 at 13:12

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.