ESPHome reboots with UART to Plantower sensor

I’ve been debugging a stability issue with two AirGradient Pro 4.2 pre-soldered units running ESPHome 2023.8.2. The below config is what I started with:

esphome:
  name: esphome-airgradient-upstairs
  friendly_name: AirGradient Bedroom
  platform: ESP8266
  board: d1_mini


# Enable logging
logger:

# Enable Home Assistant API
api:

ota:


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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    password: "xxxxxxxxx"

captive_portal:


i2c:
  sda: D2
  scl: D1
  frequency: 800kHz

uart:
  - rx_pin: D5
    tx_pin: D6
    baud_rate: 9600
    id: uartPM
  - rx_pin: D4
    tx_pin: D3
    baud_rate: 9600
    id: uartCO2


button:
  - platform: safe_mode
    name: "Safe Mode Restart"


debug:
  update_interval: 30s

text_sensor:
  - platform: debug
    device:
      name: "Device Info"
    reset_reason:
      name: "Reset Reason"


sensor:
  # SHT31 temp and humidity sensor
  - platform: sht3xd
    temperature:
      id: temperature
      name: "Temperature"
    humidity:
      id: humidity
      name: "Humidity"
    address: 0x44
    update_interval: 5s

  # Plantower PMS5003 PM Sensor
  - platform: pmsx003
    type: PMSX003
    uart_id: uartPM
    update_interval: 300s
    pm_1_0:
      id: pm_1_0
      name: "Particulate Matter <1.0µm Concentration"
      device_class: pm1
    pm_2_5:
      id: pm_2_5
      name: "Particulate Matter <2.5µm Concentration"
      device_class: pm25
    pm_10_0:
      id: pm_10_0
      name: "Particulate Matter <10.0µm Concentration"
      device_class: pm10

  # Senseair S8 CO2 Sensor
  - platform: senseair
    uart_id: uartCO2
    co2:
      id: co2
      name: "SenseAir CO2 Value"
    update_interval: 60s

  # SGP41 DK AK module
  - platform: sgp4x
    voc:
      id: voc
      name: "VOC Index"
    nox:
      id: nox
      name: "NOx Index"
    compensation:
      humidity_source: humidity
      temperature_source: temperature

  - platform: wifi_signal
    name: "Wifi Strength"
    update_interval: 60s

  - platform: uptime
    name: "Uptime Sensor"
    update_interval: 60s

font:
  - file: "fonts/monof55.ttf"
    id: mono_10
    size: 10
    glyphs: |
      !"%()+=,-_.:°0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyzµ₂³ₓ/

  - file: "fonts/slkscr.ttf"
    id: slk_8
    size: 8
    glyphs: |
      !"%()+=,-_.:°0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyzµ₂³ₓ/


display:
  - platform: ssd1306_i2c
    model: "SH1106 128x64"
    address: 0x3C
    lambda: |-
      it.printf(0, 0, id(slk_8),  "%.1f°F", (id(temperature).state * 1.8) + 32);
      it.printf(0, 12, id(slk_8), "%.1f%% RH", id(humidity).state);

      it.printf(0, 36, id(slk_8), "%.0f VOC", id(voc).state);
      it.printf(0, 48, id(slk_8), "%.0f NOx", id(nox).state);

      it.printf(60, 0, id(slk_8), "%.0f ppm CO2", id(co2).state);
      it.print(60, 12, id(slk_8), "µg/m³");
      it.printf(60, 24, id(slk_8), "%.0f PM1.0", id(pm_1_0).state);
      it.printf(60, 36, id(slk_8), "%.0f PM2.5", id(pm_2_5).state);
      it.printf(60, 48, id(slk_8), "%.0f PM10.0", id(pm_10_0).state);

This would reboot randomly 10-20 times per day, and seems to always be software watchdog. I tried whittling it down, and it looks like it’s the Plantower UART. If I remove all sensors and the display, it still restarts. If I remove the i2c config or the uart config for CO2 (D4+D3), it still reboots. Removing the D5+D6 uart config for Plantower makes it stable.

I pulled the D1 mini out and used a bunch of cables to connect, and configuring D4+D3 and plugging THOSE into the D5+D6 socket so they’re connected to Plantower, it’s unstable, so it doesn’t seem to be related to the pins on the D1 mini. If I configure D5+D6 uart as before, it reboots, but if I pull the cable so D5+D6 aren’t connected to anything (but still configured), it stabilizes.

Last think I tried is using TX/RX (the D1 mini pins at the top right that are connected to the hardware UART0, so it doesn’t need to do UART in software) and wiring those to the D5+D6 sockets that connect it to the Plantower UART, it works, and is stable.

I’m at a bit of a loss. I’m starting to think the GPIO pins, when connected to the Plantower UART and configured to be driven as UART via software (because they don’t have hardware UART), become unstable because something causes the SoftwareSerial package to hang, which then triggers the software watchdog for a reboot.

I’ve got a scope on it’s way out of curiosity to see if the UART traffic on Plantower is different than that on the Senseair CO2 sensor, but I’m not sure what other things I can try.

I’ve seen the same issue but couldn’t get it to reproduce enough to get the logs requested
You can take a look here where I have a workaround but if you can get the right logs, it would help the community

I also fixed it by changing the collection interval for the sensor from every 1 second to 120 seconds so it doesn’t refresh as frequently, but could expand life if the sensor and doesn’t generate as much logging traffic which seems to prevent the reboots

Not stable with the update interval down to 300 seconds or with logging set to NONE. The only stability I’ve seen yet, where I’m still talking to the Plantower sensor, is when the sensor is connected through the UART0 hardware pings (TX/RX).

The Sensor S8 is also serial, so I’ve set both to INFO in the past so you could try that or adjusting the update interval for it as well