Reading from UART timed out at byte 0!

I am new to esphome and trying to get work mh-z19e on esp32-c3 supermini. I successfully set up esp32, communication with home assistant seem ok, I double checked uart connection, everything seems fine, but i am still receiving this error:

Reading from UART timed out at byte 0!
Reading data from MHZ19 failed!

Any help for me? Thanks…

Logs


INFO ESPHome 2025.2.2
INFO Reading configuration /config/esphome/esphome-web-4e61bc.yaml...
INFO Starting log output from 192.168.1.209 using esphome API
INFO Successfully connected to esphome-web-4e61bc @ 192.168.1.209 in 0.015s
INFO Successful handshake with esphome-web-4e61bc @ 192.168.1.209 in 1.246s
[15:36:53][I][app:100]: ESPHome version 2025.2.2 compiled on Mar 12 2025, 15:33:03
[15:36:53][C][wifi:600]: WiFi:
[15:36:53][C][wifi:428]:   Local MAC: A0:85:E3:4E:61:BC
[15:36:53][C][wifi:433]:   SSID: [redacted]
[15:36:53][C][wifi:436]:   IP Address: 192.168.1.209
[15:36:53][C][wifi:439]:   BSSID: [redacted]
[15:36:53][C][wifi:441]:   Hostname: 'esphome-web-4e61bc'
[15:36:53][C][wifi:443]:   Signal strength: -65 dB ▂▄▆█
[15:36:53][C][wifi:447]:   Channel: 3
[15:36:53][C][wifi:448]:   Subnet: 255.255.255.0
[15:36:53][C][wifi:449]:   Gateway: 192.168.1.1
[15:36:53][C][wifi:450]:   DNS1: 192.168.1.1
[15:36:53][C][wifi:451]:   DNS2: 178.17.0.11
[15:36:53][C][logger:177]: Logger:
[15:36:53][C][logger:178]:   Max Level: DEBUG
[15:36:53][C][logger:179]:   Initial Level: DEBUG
[15:36:53][C][logger:181]:   Log Baud Rate: 115200
[15:36:53][C][logger:182]:   Hardware UART: USB_SERIAL_JTAG
[15:36:53][C][uart.idf:159]: UART Bus 0:
[15:36:53][C][uart.idf:160]:   TX Pin: GPIO21
[15:36:53][C][uart.idf:161]:   RX Pin: GPIO20
[15:36:53][C][uart.idf:163]:   RX Buffer Size: 256
[15:36:53][C][uart.idf:165]:   Baud Rate: 9600 baud
[15:36:53][C][mhz19:104]: MH-Z19:
[15:36:53][C][mhz19:105]:     Device Class: 'carbon_dioxide'
[15:36:53][C][mhz19:115]:   Warmup time: 75 s
[15:36:53][C][esphome.ota:073]: Over-The-Air updates:
[15:36:53][C][api:140]: API Server:
[15:36:58][D][api:103]: Accepted 192.168.1.149
[15:36:58][D][api.connection:1446]: Home Assistant 2025.3.2 (192.168.1.149): Connected successfully
[15:36:58][D][api:103]: Accepted 192.168.1.149
[15:36:58][D][api.connection:1446]: ESPHome Logs 2025.2.2 (192.168.1.149): Connected successfully
[15:37:39][W][mhz19:037]: MHZ19 warming up, 18 s left
[15:37:44][I][safe_mode:041]: Boot seems successful; resetting boot loop counter
[15:37:44][D][esp32.preferences:114]: Saving 1 preferences to flash...
[15:37:44][D][esp32.preferences:142]: Saving 1 preferences to flash: 0 cached, 1 written, 0 failed
[15:38:39][D][uart_debug:114]: <<< 47:0C:DE:47:0C:DE:47:0C:DE:47:0C:DE:FF:FF:FF:FF:FF:FF:FF:FF:FF:69:C4:1F:07:0C:DE:FF:FF:FF:FF:FF:FF:FF:FF:FF:29:84:1F
[15:38:39][E][uart:015]: Reading from UART timed out at byte 0!
[15:38:39][W][mhz19:044]: Reading data from MHZ19 failed!
[15:38:39][W][component:237]: Component mhz19.sensor took a long time for an operation (120 ms).
[15:38:39][W][component:238]: Components should block for at most 30 ms.
[15:38:39][D][uart_debug:114]: >>> FF:01:86:00:00:00:00:00:79
[15:39:39][E][uart:015]: Reading from UART timed out at byte 0!
[15:39:39][W][mhz19:044]: Reading data from MHZ19 failed!
[15:39:39][W][component:237]: Component mhz19.sensor took a long time for an operation (116 ms).
[15:39:39][W][component:238]: Components should block for at most 30 ms.
[15:39:39][D][uart_debug:114]: >>> FF:01:86:00:00:00:00:00:79

You need to include your config and you need to use code tags to make it readable.

This is also worth reading:

Just a guess, since there is no config, but it looks like you might have both uart debug and the mhz sensor connected to the same uart. So the debug might be eating all the bytes before the sensor can see them.

Thanks for reply and information.

Here is a actual log and config:

Config:

esphome:
  name: esphome-web-4e61bc
  friendly_name: Senzor
  min_version: 2024.11.0
  name_add_mac_suffix: false

esp32:
  board: esp32-c3-devkitm-1
  framework:
    type: esp-idf

# Enable logger
logger:

# Enable Home Assistant API
api:

# Allow Over-The-Air updates
ota:
- platform: esphome

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  output_power: 8.5

uart:
  tx_pin: 21
  rx_pin: 20
  baud_rate: 9600

sensor:
  - platform: mhz19
    co2:
      name: MH-Z19 CO2 Value
    temperature:
      name: MH-Z19 Temperature

Log:

INFO ESPHome 2025.2.2
INFO Reading configuration /config/esphome/esphome-web-4e61bc.yaml...
INFO Starting log output from 192.168.1.209 using esphome API
INFO Successfully connected to esphome-web-4e61bc @ 192.168.1.209 in 0.051s
INFO Successful handshake with esphome-web-4e61bc @ 192.168.1.209 in 0.022s
[16:27:54][I][app:100]: ESPHome version 2025.2.2 compiled on Mar 13 2025, 23:35:02
[16:27:54][C][wifi:600]: WiFi:
[16:27:54][C][wifi:428]:   Local MAC: A0:85:E3:4E:61:BC
[16:27:54][C][wifi:433]:   SSID: [redacted]
[16:27:54][C][wifi:436]:   IP Address: 192.168.1.209
[16:27:54][C][wifi:439]:   BSSID: [redacted]
[16:27:54][C][wifi:441]:   Hostname: 'esphome-web-4e61bc'
[16:27:54][C][wifi:443]:   Signal strength: -62 dB ▂▄▆█
[16:27:54][C][wifi:447]:   Channel: 3
[16:27:54][C][wifi:448]:   Subnet: 255.255.255.0
[16:27:54][C][wifi:449]:   Gateway: 192.168.1.1
[16:27:54][C][wifi:450]:   DNS1: 192.168.1.1
[16:27:54][C][wifi:451]:   DNS2: 178.17.0.11
[16:27:54][C][logger:177]: Logger:
[16:27:54][C][logger:178]:   Max Level: DEBUG
[16:27:54][C][logger:179]:   Initial Level: DEBUG
[16:27:54][C][logger:181]:   Log Baud Rate: 115200
[16:27:54][C][logger:182]:   Hardware UART: USB_SERIAL_JTAG
[16:27:54][C][uart.idf:159]: UART Bus 0:
[16:27:54][C][uart.idf:160]:   TX Pin: GPIO21
[16:27:54][C][uart.idf:161]:   RX Pin: GPIO20
[16:27:54][C][uart.idf:163]:   RX Buffer Size: 256
[16:27:54][C][uart.idf:165]:   Baud Rate: 9600 baud
[16:27:54][C][uart.idf:166]:   Data Bits: 8
[16:27:54][C][uart.idf:167]:   Parity: NONE
[16:27:54][C][uart.idf:168]:   Stop bits: 1
[16:27:54][C][mhz19:104]: MH-Z19:
[16:27:54][C][mhz19:105]:   CO2 'MH-Z19 CO2 Value'
[16:27:54][C][mhz19:105]:     Device Class: 'carbon_dioxide'
[16:27:54][C][mhz19:105]:     State Class: 'measurement'
[16:27:54][C][mhz19:105]:     Unit of Measurement: 'ppm'
[16:27:54][C][mhz19:105]:     Accuracy Decimals: 0
[16:27:54][C][mhz19:105]:     Icon: 'mdi:molecule-co2'
[16:27:54][C][mhz19:106]:   Temperature 'MH-Z19 Temperature'
[16:27:54][C][mhz19:106]:     Device Class: 'temperature'
[16:27:54][C][mhz19:106]:     State Class: 'measurement'
[16:27:54][C][mhz19:106]:     Unit of Measurement: '°C'
[16:27:54][C][mhz19:106]:     Accuracy Decimals: 0
[16:27:54][C][mhz19:115]:   Warmup time: 75 s
[16:27:54][C][mdns:116]: mDNS:
[16:27:54][C][mdns:117]:   Hostname: esphome-web-4e61bc
[16:27:54][C][esphome.ota:073]: Over-The-Air updates:
[16:27:54][C][esphome.ota:074]:   Address: esphome-web-4e61bc.local:3232
[16:27:54][C][esphome.ota:075]:   Version: 2
[16:27:54][C][safe_mode:018]: Safe Mode:
[16:27:54][C][safe_mode:019]:   Boot considered successful after 60 seconds
[16:27:54][C][safe_mode:021]:   Invoke after 10 boot attempts
[16:27:54][C][safe_mode:022]:   Remain in safe mode for 300 seconds
[16:27:54][C][api:140]: API Server:
[16:27:54][C][api:141]:   Address: esphome-web-4e61bc.local:6053
[16:27:54][C][api:145]:   Using noise encryption: NO
[16:28:10][W][mhz19:037]: MHZ19 warming up, 37 s left
[16:28:33][I][safe_mode:041]: Boot seems successful; resetting boot loop counter
[16:28:33][D][esp32.preferences:114]: Saving 1 preferences to flash...
[16:28:33][D][esp32.preferences:142]: Saving 1 preferences to flash: 0 cached, 1 written, 0 failed
[16:29:10][E][uart:015]: Reading from UART timed out at byte 0!
[16:29:10][W][mhz19:044]: Reading data from MHZ19 failed!
[16:29:10][W][component:237]: Component mhz19.sensor took a long time for an operation (115 ms).
[16:29:10][W][component:238]: Components should block for at most 30 ms.

Your new log is not at the same level of debug as the first one.

I would set the log level to very verbose to see if that provides more insight.

This from the first log, seems to indicate there is a debug print on the logger, which could have been consuming the bytes before the mhz component could read them. Your current config doesn’t show you adding a debug statement, but does appear to show the UART component generating an error.

This appears to be the code generating the error:

It will wait up to 100ms for the amount of data to show up.

This is the MH-Z19 code:

line 44 is what reports the error.

Line 89-101 are the main code:

  • first clear the UART buffer of previous stuff
  • send command to the sensor
  • wait for a response

This goes back to esphome/esphome/components/uart/uart_component_esp_idf.cpp at 7679c716b31a0cf79859383dc984e79b3ddf37dc · esphome/esphome · GitHub
line 204 is where it is waiting

My reading of the code and error message is that the MH-Z19 component is waiting for data that does not show up in time. There are more reasons for this to not work than there are for it to work.

It appears that these boards are particularly fussy and others have had issues with esphome.

Some have had success with Tasmota, others probably gave up and got a better sensor.

Hello.
Thank you very much for the detailed answer. I’ll try different sensor. If you are interested I tried to adjust the log level and re-enabled debug, but I don’t see anything interesting in log:

INFO ESPHome 2025.2.2
INFO Reading configuration /config/esphome/esphome-web-4e61bc.yaml...
INFO Starting log output from 192.168.1.209 using esphome API
INFO Successfully connected to esphome-web-4e61bc @ 192.168.1.209 in 0.015s
INFO Successful handshake with esphome-web-4e61bc @ 192.168.1.209 in 0.072s
[08:52:27][I][app:100]: ESPHome version 2025.2.2 compiled on Mar 15 2025, 08:43:31
[08:52:27][C][wifi:600]: WiFi:
[08:52:27][C][wifi:428]:   Local MAC: A0:85:E3:4E:61:BC
[08:52:27][C][wifi:433]:   SSID: [redacted]
[08:52:27][C][wifi:436]:   IP Address: 192.168.1.209
[08:52:27][C][wifi:439]:   BSSID: [redacted]
[08:52:27][C][wifi:441]:   Hostname: 'esphome-web-4e61bc'
[08:52:27][C][wifi:443]:   Signal strength: -62 dB ▂▄▆█
[08:52:27][V][wifi:445]:   Priority: 0.0
[08:52:27][C][wifi:447]:   Channel: 3
[08:52:27][C][wifi:448]:   Subnet: 255.255.255.0
[08:52:27][C][wifi:449]:   Gateway: 192.168.1.1
[08:52:27][C][wifi:450]:   DNS1: 192.168.1.1
[08:52:27][C][wifi:451]:   DNS2: 178.17.0.11
[08:52:27][C][logger:177]: Logger:
[08:52:27][C][logger:178]:   Max Level: VERY_VERBOSE
[08:52:27][C][logger:179]:   Initial Level: VERY_VERBOSE
[08:52:27][C][logger:181]:   Log Baud Rate: 115200
[08:52:27][C][logger:182]:   Hardware UART: USB_SERIAL_JTAG
[08:52:27][C][uart.idf:159]: UART Bus 0:
[08:52:27][C][uart.idf:160]:   TX Pin: GPIO21
[08:52:27][C][uart.idf:161]:   RX Pin: GPIO20
[08:52:27][C][uart.idf:163]:   RX Buffer Size: 256
[08:52:27][C][uart.idf:165]:   Baud Rate: 9600 baud
[08:52:27][C][uart.idf:166]:   Data Bits: 8
[08:52:27][C][uart.idf:167]:   Parity: NONE
[08:52:27][C][uart.idf:168]:   Stop bits: 1
[08:52:27][C][mhz19:104]: MH-Z19:
[08:52:27][C][mhz19:105]:   CO2 'MH-Z19 CO2 Value'
[08:52:27][C][mhz19:105]:     Device Class: 'carbon_dioxide'
[08:52:27][C][mhz19:105]:     State Class: 'measurement'
[08:52:27][C][mhz19:105]:     Unit of Measurement: 'ppm'
[08:52:27][C][mhz19:105]:     Accuracy Decimals: 0
[08:52:27][C][mhz19:105]:     Icon: 'mdi:molecule-co2'
[08:52:27][C][mhz19:106]:   Temperature 'MH-Z19 Temperature'
[08:52:27][C][mhz19:106]:     Device Class: 'temperature'
[08:52:27][C][mhz19:106]:     State Class: 'measurement'
[08:52:27][C][mhz19:106]:     Unit of Measurement: '°C'
[08:52:27][C][mhz19:106]:     Accuracy Decimals: 0
[08:52:27][C][mhz19:115]:   Warmup time: 75 s
[08:52:27][C][mdns:116]: mDNS:
[08:52:27][C][mdns:117]:   Hostname: esphome-web-4e61bc
[08:52:27][V][mdns:118]:   Services:
[08:52:27][V][mdns:120]:   - _esphomelib, _tcp, 6053
[08:52:27][V][mdns:122]:     TXT: friendly_name = Senzor
[08:52:27][V][mdns:122]:     TXT: version = 2025.2.2
[08:52:27][V][mdns:122]:     TXT: mac = a085e34e61bc
[08:52:27][V][mdns:122]:     TXT: platform = ESP32
[08:52:27][V][mdns:122]:     TXT: board = esp32-c3-devkitm-1
[08:52:27][V][mdns:122]:     TXT: network = wifi
[08:52:27][C][esphome.ota:073]: Over-The-Air updates:
[08:52:27][C][esphome.ota:074]:   Address: esphome-web-4e61bc.local:3232
[08:52:27][C][esphome.ota:075]:   Version: 2
[08:52:27][C][safe_mode:018]: Safe Mode:
[08:52:27][C][safe_mode:019]:   Boot considered successful after 60 seconds
[08:52:27][C][safe_mode:021]:   Invoke after 10 boot attempts
[08:52:27][C][safe_mode:022]:   Remain in safe mode for 300 seconds
[08:52:27][C][api:140]: API Server:
[08:52:27][C][api:141]:   Address: esphome-web-4e61bc.local:6053
[08:52:27][C][api:145]:   Using noise encryption: NO
[08:52:42][VV][api.service:697]: on_ping_request: PingRequest {}
[08:52:42][VV][api.service:043]: send_ping_response: PingResponse {}
[08:52:51][VV][scheduler:225]: Running interval '' with interval=60000 last_execution=168743 (now=228745)
[08:52:55][VV][scheduler:225]: Running interval 'update' with interval=60000 last_execution=172480 (now=232485)
[08:52:55][VV][uart.idf:237]:     Flushing...
[08:52:55][E][uart:015]: Reading from UART timed out at byte 0!
[08:52:55][W][mhz19:044]: Reading data from MHZ19 failed!
[08:52:55][W][component:237]: Component mhz19.sensor took a long time for an operation (114 ms).
[08:52:55][W][component:238]: Components should block for at most 30 ms.
[08:52:55][D][uart_debug:114]: >>> FF:01:86:00:00:00:00:00:79
[08:53:22][VV][api.service:697]: on_ping_request: PingRequest {}
[08:53:22][VV][api.service:043]: send_ping_response: PingResponse {}
[08:53:27][VV][api.connection:133]: Sending keepalive PING...
[08:53:27][VV][api.service:037]: send_ping_request: PingRequest {}
[08:53:27][VV][api.service:706]: on_ping_response: PingResponse {}

This makes it clearer.

The problem appears to be a not so good design of the component. The log shows the MH-Z19 answering with 9 bytes, but the answer comes after the component gave up waiting for the answer. The simple solution is likely to increase the timeout.

There are several ways to do this. The easiest is probably just wait for there to be the 9 bytes it is expecting.

Line 89-101 are the main code:

first clear the UART buffer of previous stuff
send command to the sensor
ADD wait for the correct number of bytes to be available
wait for a response

It is a reasonably simple change if you already know how to modify an existing component.

  • clone/copy the folder containing the code (I liked the GitHub repo above)
  • add it as an external component in your YAML
  • modify one of the logging statements (hello world) do you know it is using your code
  • make the change

The better fix would be to query the sensor before you need the data, but I am unaware of a good way to do that only before you need the data. The other way is to change the code to periodically query the sensor (use loop() and some additional code to only check every so often) so it always has a value and only publish it when required.