Why does my routine not run after wakeup?

I migrated a device to a Lolin D32. Before, it ran on a different ESP32 board. It worked really well except that it used too much power.

Now, on my LolinD32, the code does what it should (activatings externals, measuring, using those measurements to run a motor, going to sleep) when it is turned on. If it wakes up from deep sleep, it does nothing of that. It doesn’t matter if I use the wakeup pin I have set up, or if it wakes up from sleep after a fixed time.
All it does is printing this to the log, and after that it stays awake:

[15:33:13][I][ota:113]: Boot seems successful, resetting boot loop counter.
[15:33:13][D][esp32.preferences:114]: Saving 1 preferences to flash…
[15:33:13][D][esp32.preferences:143]: Saving 1 preferences to flash: 0 cached, 1 written, 0 failed

…after that nothing happens…

Why does the rutine I set up in my YAML only run on a hard boot and not on a wakeup from deep sleep?

Impossible to say without seeing your device’s yaml configuration.

Here you go:

# GPIO	Connected to
# 33	Moisture Meter
# 23	Pump (thru Mosfet)
# 0	Action Button
# 13 water level power
# 35,25,26, 27,14,	Water level sensors
# 32	Battery level

substitutions:
  esp_name: flaura9
  esp_id: flaura9
  soil_moisture_threshold: "85" # %
  watering_time: 5s
  long_sleep: 24 h
  short_sleep: 2 min
  sleep_prevention_duration: 0 min
  waterLevelSensorThreshold: "0.1" # V

# Enable Home Assistant API
api:
  encryption:
    key: "NoBeITWzY5mJNUVnVor/fNlI1PieOyE6YujHhtA/1jk="

ota:
  password: "fe66a5de37b1805a89749336c83a77c9"

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Flaura9 Fallback Hotspot"
    password: "bA75C1T6cB49"

<<: !include flaura_main.yaml

and then, in flaura_main:

esphome:
  name: ${esp_id}
  on_boot:
    priority: 900.0
    then:
      - delay: 1s
      - switch.turn_off: ${esp_id}_power_moisture_sensor
      - switch.turn_off: ${esp_id}_power_pump
      - script.execute: run
    
time:
  - platform: homeassistant
    id: ha_time

esp32:
  board: esp32dev
  framework:
    type: arduino
        
deep_sleep:
  run_duration: 10h
  id: deep_sleep1
  wakeup_pin:
    number: GPIO00
    inverted: true
        
        # Enable logging
logger:

captive_portal: 

switch:
  - platform: gpio
    pin: 19
    id: ${esp_id}_power_moisture_sensor
    name: ${esp_id} power moisture sensor #green wire

  - platform: gpio
    pin: 23
    id: ${esp_id}_power_pump
    name: ${esp_id} power pump

  - platform: gpio
    pin: 13
    id: ${esp_id}_power_water_level
    name: ${esp_id} power water level

binary_sensor:
  - platform: homeassistant
    id: allow_flaura_deep_sleep
    entity_id: input_boolean.allow_flaura_deep_sleep
 
  - platform: gpio
    pin: 27
    id: "${esp_id}_water_level_sensor_10" #yellow wire
    name: ${esp_id} water level sensor 10
    filters:
      - delayed_on: 400ms

  - platform: gpio
    pin: 26
    id: "${esp_id}_water_level_sensor_30" #white wire
    name: ${esp_id} water level sensor 30
    filters:
      - delayed_on: 400ms

  - platform: gpio
    pin: 25
    id: "${esp_id}_water_level_sensor_50" #red wire
    name: ${esp_id} water level sensor 50
    filters:
      - delayed_on: 400ms

  - platform: template
    id: "${esp_id}_water_present"
    name: ${esp_id} water present

  
sensor:
  - platform: adc
    pin: 33
    id: "${esp_id}_soil_moisture"
    name: "${esp_name} soil moisture"
    unit_of_measurement: "%"
    attenuation: 11dB
    filters:
      - median:
          window_size: 11
          send_every: 11
          send_first_at: 11
      - calibrate_linear:
        - 0.84 -> 100.00
        - 2.40 -> 0.00
      - lambda: |
          if (x < 0) return 0; 
          else if (x > 100) return 100;
          else return (x);
    accuracy_decimals: 0
    update_interval: never

  - platform: adc
    pin: GPIO35
    id: "${esp_id}_battery_raw"
    name: "${esp_name} battery raw"
    update_interval: never
    accuracy_decimals: 2
    attenuation: 11dB
    filters:
      - median:
          window_size: 11
          send_every: 11
          send_first_at: 11
      - multiply: 2.0
    
  - platform: template
    id: "${esp_id}_battery"
    name: "${esp_name} battery"
    unit_of_measurement: '%'
    update_interval: never
    lambda: |-
      return (id(${esp_id}_battery_raw).state - 3.5) / 0.6; // Current change minus minimum Devided by max minus min  (4.1 - 3.5)

script:
  - id: run
    mode: queued
    then:
      - script.execute: measure_battery_level
      - script.execute: measure_soil_moisture
      - script.execute: water_plant
      - script.wait: water_plant
      - delay: 1s

  - id: measure_soil_moisture
    then:
      - switch.turn_on: ${esp_id}_power_moisture_sensor
      - lambda: |-
          for (int i = 0; i < 11; i++) {
            delay(100);
            id(${esp_id}_soil_moisture).update();
          }
      - switch.turn_off: ${esp_id}_power_moisture_sensor

  - id: water_plant
    then:
      - switch.turn_on: ${esp_id}_power_water_level
      - delay: 2s
      - if:
          condition:
             binary_sensor.is_on: ${esp_id}_water_level_sensor_10
          then:
            - binary_sensor.template.publish:
                id: "${esp_id}_water_present"
                state: ON
          else:
            - binary_sensor.template.publish:
                id: "${esp_id}_water_present"
                state: OFF

      - if:
          condition:
            lambda: |-
              return ((id(${esp_id}_soil_moisture).state < ${soil_moisture_threshold}) && (id(${esp_id}_water_level_sensor_10).state));
          then:
            - switch.turn_on: ${esp_id}_power_pump
            - delay: ${watering_time}
            - switch.turn_off: ${esp_id}_power_pump
            - script.execute: enter_short_sleep
          else:
            - script.execute: enter_long_sleep

  - id: measure_battery_level
    then:
      - component.update: ${esp_id}_battery_raw
      - lambda: |-
          for (int i = 0; i < 11; i++) {
            id(${esp_id}_battery_raw).update();
            delay(200);
          }
      - component.update: ${esp_id}_battery

  - id: enter_long_sleep
    then:
    - switch.turn_off: ${esp_id}_power_water_level
    - switch.turn_off: ${esp_id}_power_pump
    - switch.turn_off: ${esp_id}_power_moisture_sensor
    - delay: 2 s
    - if:
        condition:
          binary_sensor.is_on: allow_flaura_deep_sleep
        then:
#          - delay: ${sleep_prevention_duration}
          - logger.log: "enter sleep"
          - deep_sleep.enter:
              id: deep_sleep1
              sleep_duration: ${long_sleep}
        else:
          - logger.log: "long sleep prevented from HA"

  - id: enter_short_sleep
    then:
    - switch.turn_off: ${esp_id}_power_water_level
    - switch.turn_off: ${esp_id}_power_pump
    - switch.turn_off: ${esp_id}_power_moisture_sensor  
    - delay: 5s
    - if:
        condition:
          and:
            - binary_sensor.is_on: allow_flaura_deep_sleep
            - wifi.connected:
        then:
#          - delay: ${sleep_prevention_duration}
          - logger.log: "enter long sleep"
          - deep_sleep.enter:
              id: deep_sleep1
              sleep_duration: ${short_sleep}
        else:
          - logger.log: "long sleep prevented from HA"

That’s a pretty high boot priority. That’s before the switches have even been initialised.

Try it after wifi is set up at about 200.

Have you tried adding things that help with faster connection? Like static ip.

I’ve found sometimes you can miss early boot logs which could help troubleshoot.

I think logger is maybe set up a bit later. Like around where Tom is suggesting.

I also add in custom logger messages around the place when I’m trying to debug.

Have you thought about making these

restore_mode: ALWAYS_OFF

(if it’s available and it works? I know sometimes people report unexpected behaviour with that feature)

That would then possibly let ESPHome manage it at the right time.

I’m taking a bit of interest in your code as I’m comparing our irrigation projects to see if there’s things you are doing that I like better than mine.

Here’s an excerpt of my boot. Shout out if this is off topic and you want to stay on topic.

On Boot and shutdown snippets
  on_boot:    
    # #Try this if sensors don't boot. https://community.home-assistant.io/t/add-sensor-delay-upon-power-on/158567/6?u=mahko_mahko
    # https://community.home-assistant.io/t/i2c-bus-scan-after-deep-sleep-recovery/524925/7?u=mahko_mahko
    - priority: 900
      then:
      - lambda: |-
          Wire.begin();
          delay(500);
    - priority: -100
      then:
        #Reset sensor update counters. These are for debugging.
        - lambda: id(count_irrigation_lux).publish_state(0);
        - lambda: id(count_batt_voltage).publish_state(0);
        - lambda: id(count_irrigation_tof).publish_state(0);
        - delay: 1s     
        
        #Auto sensor updates are turned off and manually requested on boot. These are multi-sampled and then aggregated. 
        #The ESP then goes back to sleep when they're done (unless told to stay awake).
          #Request sensor updates        
        - logger.log: "....Starting sensor updates"
        - repeat:
            count: 5 #Update cycles
            then:
              - component.update: batt_voltage #Battery level
              - delay: 100ms
              - component.update: soil_moisture_voltage #Moisture level
              - delay: 100ms
              - component.update: tof #Water tank level
              - delay: 100ms
              - component.update: irrigation_lux #Light level
              - delay: 100ms
            #second pass for ADC based sensors which benefit from more samples.
              - component.update: batt_voltage
              - delay: 250ms
              - component.update: soil_moisture_voltage
              - delay: 250ms

  on_shutdown:
    priority: -100
    then:
      - if:
          condition:
            - binary_sensor.is_on: all_updates_recieved           
          then:
            - logger.log: "Data updates ok..."
          else:
            - logger.log: "A sensor might be down...missing updates" 
            - binary_sensor.template.publish:
                id: data_update_problem
                state: ON
            - delay: 1s
              
      - switch.turn_off: pump #Probably not required....
    #Turn off 5v peripheral power. It will retore as on when it wakes.
      - logger.log: "Turning off peripheral power..."
      - switch.turn_off: power_peripherals
    #Turn off the "Fresh data recieved sensors"
      - binary_sensor.template.publish:
          id: water_tank_level_recieved
          state: OFF
      - binary_sensor.template.publish:
          id: irrigation_lux_recieved
          state: OFF
      - binary_sensor.template.publish:
          id: batt_level_recieved
          state: OFF
      - binary_sensor.template.publish:
          id: solar_plant_moisture_level_recieved
          state: OFF
      - binary_sensor.template.publish:
          id: all_updates_recieved
          state: OFF

I tried and tested this, and it works. Thanks, @tom_l , I could have spend weeks figuring out it was this line that was causing issues.

Thank you for your fine suggestions.

Yes, I have tried faster connections with static IP and fast-connect. It was mostly to save battery, though. It was giving me all sorts of trouble connecting. Maybe it was due to the onboot-issue that tom_l fixed. I should probably give it a try again.

As for restore_mode: ALWAYS_OFF… What I have today is working. I think I’ll stick with that.

1 Like