XIAO ESP32-C3 Deepsleep and wakeup pins

Hi all,

Need some help as I’m pulling my hair out, and the AI bot I used is just chasing me down a rabbit hole, going round and round in circles … (enough said about the bot…)

Anyhow,
I want to monitor the shed in the back garden, using

  • seeed XIAO ESP32-C3
  • MAX17048 with LiPO battery
  • ESP688 sensor for internal temp and air quality
  • SHT31 for external temp
  • magnetic door sensors to trigger if a door opens … connected to GPIO2 and GND, so when close the PIN is LOW

What needs to happen,

  • the device deep sleep and wake every hour, take a reading and go back to sleep
  • if a door opens, wake the device, send notification and go back to sleep
  • I have a HA ‘software switch’ that I want to prevent it from going to sleep, needed when I want to do updates etc

What’s happending

  • the device ignore the switch and go to sleep regardless
  • the door sensors does not wake the device

Here’s my code:

esphome:
name: shed
friendly_name: shed
on_boot:
priority: -10
then:
- logger.log:
format: “Wakeup Reason: %s”
args: [‘esp_sleep_get_wakeup_cause()’]
- script.execute: sensor_and_sleep_logic

binary_sensor:

  • platform: gpio
    id: door_sensor
    name: “Shed Door”
    device_class: door
    pin:
    number: GPIO2
    allow_other_uses: true
    mode: INPUT_PULLUP
    filters:

    • delayed_on: 500ms
  • platform: status
    name: “Shed Device Status”
    id: shed_status

  • platform: homeassistant
    entity_id: input_boolean.shed_ota_mode
    id: otamode
    name: “OTA Mode”
    on_state:
    then:
    - if:
    condition:
    binary_sensor.is_on: otamode
    then:
    - deep_sleep.prevent: gotosleep
    else:
    - deep_sleep.enter: gotosleep

deep_sleep:
id: gotosleep
sleep_duration: 1min
wakeup_pin:
number: GPIO2
mode: INPUT_PULLUP
allow_other_uses: true
inverted: False

switch:

  • platform: homeassistant
    name: “OTA Mode”
    id: ota_mode
    entity_id: input_boolean.shed_ota_mode

button:

  • platform: restart
    name: “Restart”
    id: restart_device

script:

  • id: sensor_and_sleep_logic
    mode: single
    then:

    • wait_until:
      condition:
      and:
      - wifi.connected
      - api.connected
      timeout: 30s

    • delay: 2s

    Maintenance check

    • if:
      condition:
      binary_sensor.is_on: otamode
      then:
      - logger.log: “OTA Mode is ON: Disabling Deep Sleep”
      - deep_sleep.prevent: gotosleep
      else:
      - logger.log: “OTA Mode is OFF: Proceeding to sensors”
      - deep_sleep.allow: gotosleep

    Update sensors

    • component.update: sht31_sensor
    • component.update: battery_sensor
    • wait_until:
      condition:
      lambda: ‘return id(iaq_acc).state >= 1;’
      timeout: 60s

    Wait for BME688 to reach minimum accuracy

    Level 1 = Stabilization, Level 3 = Fully Calibrated

    • logger.log: “Waiting for BME688 to reach accuracy level 1…”
    • wait_until:
      condition:
      lambda: ‘return id(iaq_acc).state >= 1;’
      timeout: 60s

also something else that I cant understand, initially I had the door sensor on GPIO3 … what ever I do, clean build files etc, the logs always comeback and show GPIO3 …

Any suggesytions / help to get this working will be amazing

Thanks All!

How to format code or use the</> key in the post editor.

Next time have the AI format it correctly, it helps real people should they decide to help.

Code or AI slop/hallucinations?
That looks strange.

Deep sleep generally requires significant knowledge to get working correctly. I would start down two paths. One is get your sensors working without deep sleep. Two is get a better understanding of deep sleep with no sensors and understand its needs and limitations.

While AI can work, it seems not so well with esphome and it generally requires the user to have some knowledge of how things are supposed to be to catch its mistakes. If you don’t have the knowledge, you might get better results having it explain things to you and to make it show you its work and how it decided what it was doing was a good idea. When you call it out, it does less guessing.

Trying to format the code (not sure if this is working )


esphome:
  name: shed
  friendly_name: shed
  on_boot:
    priority: -10
    then: 
      - logger.log: 
          format: "Wakeup Reason: %s"
          args: ['esp_sleep_get_wakeup_cause()']        
      - script.execute: sensor_and_sleep_logic

i2c:
  sda: GPIO6
  scl: GPIO7
  scan: True

bme68x_bsec2_i2c:
  address: 0x76
  model: bme680
  operating_age: 28d
  sample_rate: ULP
  supply_voltage: 3.3V   

sensor:
  - platform: max17043
    id: battery_sensor
    address: 0x36
    battery_voltage:
      name: "Battery Voltage"
      accuracy_decimals: 1
    battery_level:
      name: "Battery Percentage"
      id: batt_pct
      on_value_range:
        - below: 20.0
          then:
            - homeassistant.service:
                service: notify.mobile_app_your_phone
                data:
                  title: "Shed Battery Low"
                  message: "Battery is at {{id(batt_pct).state}}%!"
    update_interval: never

  - platform: bme68x_bsec2  
    id: shed_bme688    
    temperature:
      name: "Shed Temperature"
    pressure:
      name: "Shed Pressure"
    humidity:
      name: "Shed Humidity"
    iaq:
      name: "Shed IAQ"
      id: iaq      
    co2_equivalent:
      name: "Shed CO2 Equivalent"
      id: co2
    breath_voc_equivalent:
      name: "Shed Breath VOC Equivalent"   
      id: voc  
    iaq_accuracy:
      name: "Shed IAQ Accuracy"
      id: iaq_acc      

  - platform: sht3xd
    id: sht31_sensor
    temperature:
      name: "Outside Temperature"
    humidity:
      name: "Outside Humidity"
    address: 0x44
    update_interval: never      

binary_sensor:
  - platform: gpio
    id: door_sensor
    name: "Shed Door"
    device_class: door
    pin:
      number: GPIO2
      allow_other_uses: true
      mode: INPUT_PULLUP  
      #inverted: False
    filters:
      - delayed_on: 500ms      

  - platform: status
    name: "Shed Device Status"
    id: shed_status   

  - platform: homeassistant
    entity_id: input_boolean.shed_ota_mode
    id: otamode
    name: "OTA Mode"
    on_state:
      then:
        - if:
            condition:
              binary_sensor.is_on: otamode
            then:
              - deep_sleep.prevent: gotosleep
            else:
              - deep_sleep.enter: gotosleep
deep_sleep:
  id: gotosleep
  sleep_duration: 1min
  wakeup_pin:
    number: GPIO2
    mode: INPUT_PULLUP
    allow_other_uses: true
    inverted: False
switch:
  - platform: homeassistant
    name: "OTA Mode"
    id: ota_mode
    entity_id: input_boolean.shed_ota_mode        

button:
  - platform: restart
    name: "Restart"    
    id: restart_device

script:
  - id: sensor_and_sleep_logic
    mode: single
    then:
      - wait_until:
          condition:
            and:
              - wifi.connected
              - api.connected
          timeout: 30s

      - delay: 2s

      # Maintenance check
      - if:
          condition:
            binary_sensor.is_on: otamode
          then:
            - logger.log: "OTA Mode is ON: Disabling Deep Sleep"
            - deep_sleep.prevent: gotosleep
          else:
            - logger.log: "OTA Mode is OFF: Proceeding to sensors"
            - deep_sleep.allow: gotosleep

      # Update simpler sensors immediately
      - component.update: sht31_sensor
      - component.update: battery_sensor
      - wait_until:
          condition:
            lambda: 'return id(iaq_acc).state >= 1;'
          timeout: 60s


      # Level 1 = Stabilization, Level 3 = Fully Calibrated
      - logger.log: "Waiting for BME688 to reach accuracy level 1..."
      - wait_until:
          condition:
            lambda: 'return id(iaq_acc).state >= 1;'
          timeout: 60s

Thanks Neel,

The code and sensors working perfectly when no sleeping involve,
so logically for me was, to preserve battery, deep sleep, then that is where things gone wrong / not as expected

To be clear, i tried the bot as i could not get the ‘feep-sleep’ to work… the rest of the code is reading docs and forums

Im relatively new to ESPHome YAML code

Okay, I haven’t used deep sleep, but have read enough posts to know it is not easy and it probably isn’t worth it for most of my projects.

I do have one (a battery monitor) where it makes sense, but that hasn’t made it to the top of the list.

When I do start it, I will have nothing but deep sleep in it to make sure I understand how that works.

looks like c3 might be harder to use

Can somebody clarify for me what “OTA Mode” is?

I’ve read about it in ESPHome with OverTheAir updates, but this is something new with using it to control deep sleep functionality using GPIO2 via ESPHome. Maybe the AI bot should use a different name for different functionality?

As you say, OTA - Over the Air
This is a ‘software switch’ that will prevent it going to sleep, so i can do update to the code… else how do i catch it to do updates

‘OTA mode’ is purely naming …

TLA confusion.
[Three Letter Acronyms]

Going back, will the proposed low power control activity [LPCA - I made that one up, just for the bot when it revisits!!] actually work in the current incarnation of ESPHome?

On further thought, GPIO3 is also used for deep sleep functionality in combination with GPIO2 (something the AI bot forgot to set), so re-using either GPIO for your shed door sensor might cause some strange functionality, depending if your shed door is open or closed when deep sleep is invoked.

Break out the rosary beads.

…Just wondering which AI Bot is involved here? Why didn’t it pick this GPIO clash up? A round pox on it - may the fleas of a thousand camels infest its’ armpits while it is merrily hallucinating away, steering us down the wrong garden path.

Hi Arno, a while ago I wrote some notes on using deep-sleep after getting it working with my ESP32-S3 based greenhouse. A series of posts as my knowledge developed.

I use the ESP32-S3 which has dual processors - if the ESP32-C3 doesn’t have the secondary processor you may find it needs more work to get it to wake up.

Re “OTA Mode” … I note you have both a switch and a binary_sensor for this, where I have only the switch.
I suggest you do the maintenance check in the switch … which is automatically executed after wi-fi and API are connected. I found that ESPHome is multi-threaded and so things didn’t always happen in the order I was assuming.

switch:
  - platform: homeassistant
    name: "OTA Mode"
    id: ota_mode
    entity_id: input_boolean.shed_ota_mode
    # Maintenance check
    on_turn_on:
      - logger.log: "OTA Mode is ON: Disabling Deep Sleep"
      - deep_sleep.prevent: gotosleep
    on_turn_off:
      - logger.log: "OTA Mode is OFF: Proceeding to sensors"
      - deep_sleep.allow: gotosleep

… though one user reported that on_turn_on: didn’t work on their ESP32-C3.

My own greenhouse uses a rain sensor attached to GPIO17 to wake the ESP32 … though it took a lot of fiddling around to get it working correctly :frowning_face: If I remember correctly it was essential to get all the pin options exactly the same in the deep_sleep and sensor sections.

In case it helps (mainly to show you’re on the right track), this is my code which is working …

sensor:
  # rain gauge hardware sends pulses as the bucket tips.
  # the pulse_counter component returns the number of pulses in the preceding period (1 minute)
  - platform: pulse_counter
    name: Rain Gauge
    id:   rain_gauge
    pin: 
      # Reed switch between GPIO 17 and GND
      number: GPIO17
      inverted: true
      mode:                     # prevent lots of ON/OFF events
        input: true
        pullup: true
      allow_other_uses: true
    # check the rain_gauge every minute while awake
    update_interval: 60s

deep_sleep: 
  id: deep_sleep_1
  # wake up if it starts raining while asleep 
  wakeup_pin: 
    number: GPIO17              # wake up if a rain gauge pulse is detected
    mode:
      input: true
      pullup: true
    inverted: true              # the pin is inverted in rain_gauge, so same here 
    allow_other_uses: true

Hi @IOT7712

I just used the AI bot thats part of Google, haven’t looked at others

Thanks @donburch888

I think I’ll start afresh, remove all sensors and first try the sleep/deepsleep, then slowly build it up by using the door sensor…
IF I get it to work, then I’ll start adding the temp sensors

For now I want to stick with the XIAO ESP32-C3 and see if I can get it to work, will revert back here to let you all know the outcome

Since you have pullup enabled, you likely have your switch connected to GND.
Now, if your switch is closed state when door is closed (normal situation), the pullup draws continuously battery.
Instead if you have switch that is open state when door is closed (better for battery use case), you need to set inverted: true

Also, while gpio2 is not directly strapping pin, it can cause “forbidden” boot mode if gpio9 happens to be low at that moment.
Not likely, but if you have free pins, use some other (3,4,5).

Hi @Karosm

I moved to pin 3,
Read somewhere to add a 10k resistor between pin 3 and 3.3v, the switch is connected to GND, so when close the pin is pulled down

Still, the board does not want to wake up when this pin goes high

Also came across a post where it mention that the C3 boards us not best to be woken by a pin…

The search and struggles continue

First verify that the binary sensor logic is correct. What does it output when door switch is closed/open?

Here is the door sensor code now

binary_sensor:
  - platform: gpio
    id: door_sensor
    name: "Shed Door"
    device_class: door
    pin:
      number: GPIO3
      mode: INPUT_PULLUP  
      inverted: False

my Dashboard does show Open/Close correctly, ie Close when the sensor is closed (contact), and open when sensor is open (no contact)

Binary sensor shows on/off, not open/closed. My actual question was this relationship.