ESP randomly rebooting

I am running a weather station with ESPhome that I am having problems with. It reboots several times a day. I noticed this because I have a sensor that only updates once an hour. This creates “gaps” in the readings, because after a reboot, the sensor has the value “Unknown” for a specific time.

image

It’s unclear to me how to debug this, since I can’t view the old log after a reboot. Can anyone give a tip on how I can address the problem?

Post your yaml - also there will normally be comments on these sort of posts about reliable power supplies and hardware - so maybe tell us about those too.

Are you sure it’s just rebooting, or is it failing wifi and then rebooting after timeout?

No, I don’t know why it is rebooting.

Here is the yaml:

esphome:
  name: "wetterstation"
  friendly_name: Wetterstation

esp32:
  board: nodemcu-32s

logger:

api:
  encryption:
    key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

ota:
  password: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

wifi:
  ssid: !secret wifi_ssid_garden
  password: !secret wifi_password_garden

  ap:
    ssid: "Wetterstation Fallback Hotspot"
    password: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

time:
  - platform: sntp
    id: my_time

web_server:

captive_portal:

http_request:
  useragent: esphome/wetterstation
  timeout: 2s

bme680_bsec:
    address: 0x77

uart:
  rx_pin: GPIO26
  tx_pin: GPIO25
  baud_rate: 9600

i2c:
  sda: GPIO32
  scl: GPIO33
  scan: true
  id: icbus

binary_sensor:
  - platform: gpio
    name: "Regensensor Kontakt"
    pin:
      number: GPIO14
      mode: INPUT
    filters:
      - invert
      - delayed_off: 1s

sensor:
  - platform: sds011
    pm_2_5:
      name: "Feinstaub <2.5µm"
      id: pm25
    pm_10_0:
      name: "Feinstaub <10.0µm"
      id: pm10
    update_interval: 5min
  - platform: pulse_counter
    pin: 
      number: GPIO27
      mode: INPUT_PULLUP
    name: 'Windgeschwindigkeit'
    icon: 'mdi:weather-windy'
    id: wind_meter
    unit_of_measurement: 'km/h'
    accuracy_decimals: 1
    update_interval: 60s
    filters:              # The datasheet claims that winspeed of 2.4 km/h generates 1 pulse per second (1 Hz) (Wo anders gefunden: 1.492mph per rotation so 1 / 25 (update_fq) / 2 * 2.4 = 0.048)
      - multiply: 0.04    # Multiplier wird auf pulses/min angewandt, daher (Pulses / 60) * 2.4 ergibt Multiplier von 0,04
  - platform: pulse_counter
    pin: 
      number: GPIO27
      mode: INPUT_PULLUP
    name: 'Windböhen'
    icon: 'mdi:weather-windy'
    id: wind_meter_max
    unit_of_measurement: 'km/h'
    accuracy_decimals: 1
    update_interval: 5s
    filters:              # The datasheet claims that winspeed of 2.4 km/h generates 1 pulse per second (1 Hz) (Wo anders gefunden: 1.492mph per rotation so 1 / 25 (update_fq) / 2 * 2.4 = 0.048)
      - multiply: 0.04    # Multiplier wird auf pulses/min angewandt, daher (Pulses / 60) * 2.4 ergibt Multiplier von 0,04
      - max:
          window_size: 120
          send_every: 12
  - platform: pulse_counter
    pin:
      number: GPIO14
      mode: INPUT
    unit_of_measurement: 'mm/h'
    name: "Regenintensität"
    icon: 'mdi:weather-pouring'
    id: rain_gauge_hour
    count_mode:
      rising_edge: DISABLE
      falling_edge: INCREMENT
    internal_filter: 13us
    update_interval: 1h
    filters:
      - multiply: 16.764 # 0.2794 * 60
    accuracy_decimals: 4
  - platform: pulse_counter
    pin:
      number: GPIO14
      mode: INPUT
    unit_of_measurement: 'mm/min'
    name: "Regenintensität (intern)"
    icon: 'mdi:weather-pouring'
    id: rain_gauge_min
    internal: true
    count_mode:
      rising_edge: DISABLE
      falling_edge: INCREMENT
    internal_filter: 13us
    update_interval: 60s
    filters:
      - multiply: 0.2794
    accuracy_decimals: 4
#  - platform: pulse_counter
#    pin:
#      number: GPIO14
#      mode: INPUT
#    unit_of_measurement: 'mm/h'
#    name: "Regenintensität"
#    icon: 'mdi:weather-pouring'
#    id: rain_gauge_min
    #internal: true
#    count_mode:
#      rising_edge: DISABLE
#      falling_edge: INCREMENT
#    internal_filter: 13us
#    update_interval: 1h
#    filters:
#      - multiply: 16.764 # 0.2794 * 60, da man ja Pulses/min bekommt
#    accuracy_decimals: 4
#    device_class: PRECIPITATION_INTENSITY
  - platform: total_daily_energy
    name: "Regenmenge heute"
    device_class: PRECIPITATION
    power_id: rain_gauge_min
    id: rain_per_day
    unit_of_measurement: 'mm'
    accuracy_decimals: 4
    icon: 'mdi:weather-pouring'
    # x60 To convert to aggregated rain amount
    filters:
      - multiply: 60
  - platform: ltr390
    update_interval: 10s
    light:
      name: "Licht"
      filters:
        - sliding_window_moving_average:
            window_size: 12
            send_every: 6
    #uv:                # Sensor Counts = Rohe Sensorwerte
    #  name: "UV"
    #uv_index:          # Interne Berechnung ist anscheinen Grütze
    #  name: "UV Index"
    #ambient_light:   # Sensor Counts = Rohe Sensorwerte
    #  name: "Ambient Light"
  - platform: ltr390
    update_interval: 60s
    uv:
      name: "UV Index"
      filters:
        - multiply: 0.010434782608695652173913 # UVI = ( uv / 2300 * wfac ) * 4 * ( 18 / gain ); gain=3, wfac=1
        - sliding_window_moving_average:
            window_size: 15
            send_every: 1
  - platform: bme680_bsec
    temperature:
      name: "Temperatur"
      id: temperature
      filters:
        - sliding_window_moving_average:
            window_size: 20
            send_every: 20
    pressure:
      name: "Luftdruck"
      id: pressure
      filters:
        - sliding_window_moving_average:
            window_size: 20
            send_every: 20
    humidity:
      name: "Luftfeuchtigkeit"
      id: humidity
      filters:
        - sliding_window_moving_average:
            window_size: 20
            send_every: 20
    iaq:
      name: "IAQ Index"
      filters:
        - sliding_window_moving_average:
            window_size: 20
            send_every: 20
      id: iaq
    co2_equivalent:
      name: "CO2-Äquivalent"
      filters:
        - sliding_window_moving_average:
            window_size: 20
            send_every: 20
    breath_voc_equivalent:
      name: "Atem VOC-Äquivalent"
      filters:
        - sliding_window_moving_average:
            window_size: 20
            send_every: 20

text_sensor:
  - platform: bme680_bsec
    iaq_accuracy:
      name: "IAQ Genauigkeit"
  - platform: template
    name: "IAQ Klassifikation"
    icon: "mdi:checkbox-marked-circle-outline"
    lambda: |-
      if ( int(id(iaq).state) <= 50) {
        return {"Exzellent"};
      }
      else if (int(id(iaq).state) >= 51 && int(id(iaq).state) <= 100) {
        return {"Gut"};
      }
      else if (int(id(iaq).state) >= 101 && int(id(iaq).state) <= 150) {
        return {"Leicht verschmutzt"};
      }
      else if (int(id(iaq).state) >= 151 && int(id(iaq).state) <= 200) {
        return {"Moderat verschmutzt"};
      }
      else if (int(id(iaq).state) >= 201 && int(id(iaq).state) <= 250) {
        return {"Stark verschmutzt"};
      }
      else if (int(id(iaq).state) >= 251 && int(id(iaq).state) <= 350) {
        return {"Stärker verschmutzt"};
      }
      else if (int(id(iaq).state) >= 351) {
        return {"Extrem verschmutzt"};
      }
      else {
        return {"error"};
      }

interval:
  - interval: 5min
    then:
      - if:
          condition:
            lambda: 'return id(pm10).has_state() && id(pm25).has_state();'
          then: # https://github.com/opendata-stuttgart/meta/wiki/APIs
            - http_request.post:
                url: https://api.sensor.community/v1/push-sensor-data/
                headers:
                  X-Sensor: esp8266-XXXXXXX
                  X-Pin: 1
                  Content-Type: application/json
                on_response:
                  then:
                    - logger.log:
                        level: INFO
                        format: "sensor.community PM response status: %d"
                        args:
                          - status_code
                json: |-
                  root["software_version"] = 1;
                  JsonArray values = root.createNestedArray("sensordatavalues");
                  JsonObject value1 = values.createNestedObject();
                  value1["value_type"] = "P1";
                  value1["value"] = id(pm10).state;
                  JsonObject value2 = values.createNestedObject();
                  value2["value_type"] = "P2";
                  value2["value"] = id(pm25).state;
                verify_ssl: false
            - http_request.post:
                url: https://api.sensor.community/v1/push-sensor-data/
                headers:
                  X-Sensor: esp8266-XXXXXXX
                  X-Pin: 11
                  Content-Type: application/json
                on_response:
                  then:
                    - logger.log:
                        level: INFO
                        format: "sensor.community TEMP/HUMID/PRESS response status: %d"
                        args:
                          - status_code
                json: |-
                  root["software_version"] = 1;
                  JsonArray values = root.createNestedArray("sensordatavalues");
                  JsonObject value1 = values.createNestedObject();
                  value1["value_type"] = "temperature";
                  value1["value"] = id(temperature).state;
                  JsonObject value2 = values.createNestedObject();
                  value2["value_type"] = "humidity";
                  value2["value"] = id(humidity).state;
                  JsonObject value3 = values.createNestedObject();
                  value3["value_type"] = "pressure";
                  value3["value"] = id(pressure).state;
                verify_ssl: false

I’m using this 5V/1A IKEA Power Supply: https://www.ikea.com/de/de/p/smahagel-ladegeraet-mit-1-usb-ausgang-weiss-70538728/

Unfortunately, I do not remember which board exactly I used and can only check it with a lot of effort, because the weather station is installed on the roof. Therefore, I would try to solve it without this information for now, if possible.

You can save the log to disk. ESPHome logger => to a file

1 Like

The debug sensor could come in handy here at it will tell you the cause of the last restart (reset_reason) :arrows_counterclockwise:

1 Like

Also - there is a lot hanging off that ESP. How are you powering it?

If via USB, consider going up a size on the power supply, or better still power via the 5V pins using a good quality power supply.

But all the suggestions about grabbing the logs are a good place to start.

1 Like

I have now started this afternoon to collect the logs OTA. Here is an interesting excerpt:

[13:58:45][W][http_request:087]: HTTP Request failed; URL: https://api.sensor.community/v1/push-sensor-data/; Error: send header failed; Duration: 8 ms
[13:59:03][D][api:102]: Accepted 192.168.178.10
[13:59:03][D][api.connection:1031]: Home Assistant 2023.7.3 (192.168.178.10): Connected successfully

Is it possible that a failed HTTP request triggers a restart? The “Windböhen”-sensor should report every 5s, it usually does, but not in the above period. Is the ESP just restarting between 13:58:45 and 13:59:03? Otherwise it always looks like this on the console:

[14:07:00][D][pulse_counter:174]: 'Windböhen': Retrieved counter: 60.01 pulses/min
[14:07:05][D][pulse_counter:174]: 'Windböhen': Retrieved counter: 59.96 pulses/min
[14:07:10][D][pulse_counter:174]: 'Windböhen': Retrieved counter: 72.03 pulses/min
[14:07:15][D][pulse_counter:174]: 'Windböhen': Retrieved counter: 96.00 pulses/min

Thank you, I’ll try this next.

Shouldn’t but could be a bug indeed - or your ö in the sensor kills the esp :joy:

The sensor states “Software Reset CPU” as reason for the reboot.

That sounds like it was “planned”. So no hardware/brown-out/power/external related reset. :white_check_mark:

Now it’s the time to get/search some logs to see (before the restart happens) why it is requested. :bulb:

I have now commented out both http_request.post that are supposed to pass my values to the sensor.community. The last 28h the ESP ran without restart. Very strange I think.

Hi @AndrejDelany did you manage to solve this somehow? I was using a NodeMCU and was having some issues, I assumed it was too far from the house so today I migrated my project to a QuinLED-ESP32 AB (Antenna Board) and after some investigation, I saw these Software Reset CPU issues as well, after a couple of http_request.post.

I managed to reduce the reboots a lot by putting delay: 30s between each HTTP call. However, it still does so.

This is my config: https://github.com/golles/ESPHome-Config/blob/d4bb5c7e2d53267850692a4906015f253f25a5df/particulate_matter.yaml

I solved it by removing the http posts and migrating this part of my esp config to a home assistant automation. So, no, I never found out, why this happened.

1 Like

I’ve considered doing that as well, but I do like and prefer the ESP can run on its own

You are right. If you find a solution, please let me know.

There is an open issue for this: Crash on http_request.post · Issue #2853 · esphome/issues · GitHub

I’ve added a “standalone mode” switch to my esp config Add standalone mode switch · golles/ESPHome-Config@afd93ee · GitHub when that is off, it won’t post and I let Home Assistant do that, https://github.com/golles/Home-Assistant-Config/blob/cd12289f8bd5a94a18a3e4638c29465fc83b1ed9/packages/particulate_matter.yaml

Not great but it works