How to take "n" ADC Samples and stop (by sleeping)?

Another day, another plea for help!
As a stepping stone on my development of a Voltmeter, I’d like to take 5 ADC samples and stop (by going to sleep).

This is my (abridged) code:

esphome:
  name: "esp32-adc-sleep"
  on_boot:
    priority: 100   #Wait for everything(?) to be setup...
    then:
      - logger.log: "Sample 1"
      - component.update: volts
      - delay: 100ms
      - logger.log: "Sample 2"
      - component.update: volts
      - delay: 100ms
      - logger.log: "Sample 3"
      - component.update: volts
      - delay: 100ms
      - logger.log: "Sample 4"
      - component.update: volts
      - delay: 100ms
      - logger.log: "Sample 5"
      - component.update: volts
      - delay: 100ms

      - deep_sleep.enter: deep_sleep_control

#housekeeping stuff is here...
  
sensor:
  - platform: adc
    pin: GPIO36
    id: volts
    name: "esp32-sleeping-volts"
    update_interval: 1s    
    attenuation: auto

deep_sleep:
  id: deep_sleep_control
  run_duration: 1s
  sleep_duration: 1min

… and here is the log output:

Leaving...
Hard Resetting...
Hard resetting via RTS pin...
Done! Flashing is complete!

Showing logs:
[08:43:19][I][logger:258]: Log initialized
[08:43:19][C][ota:469]: There have been 0 suspected unsuccessful boot attempts.
[08:43:19][D][esp32.preferences:113]: Saving 1 preferences to flash...
[08:43:19][D][esp32.preferences:142]: Saving 1 preferences to flash: 0 cached, 1 written, 0 failed
[08:43:19][I][app:029]: Running through setup()...
[08:43:19][C][adc:044]: Setting up ADC 'esp32-sleeping-volts'...
[08:43:19][C][adc:083]: ADC 'esp32-sleeping-volts' setup finished!
[08:43:19][C][wifi:037]: Setting up WiFi...
[08:43:19][C][wifi:038]:   Local MAC: FC:F5:C4:07:A2:18
[08:43:20][I][wifi:257]: WiFi Connecting to 'myAP1'...
[08:43:20][D][sensor:127]: 'esp32-sleeping-volts': Sending state 0.76933 V with 2 decimals of accuracy
[08:43:20][D][sensor:127]: 'esp32-sleeping-volts': Sending state 0.76830 V with 2 decimals of accuracy
[08:43:21][D][sensor:127]: 'esp32-sleeping-volts': Sending state 0.76782 V with 2 decimals of accuracy
[08:43:22][D][sensor:127]: 'esp32-sleeping-volts': Sending state 0.76882 V with 2 decimals of accuracy
[08:43:22][I][wifi:518]: WiFi Connected!
[08:43:22][C][wifi:362]:   Local MAC: FC:F5:C4:07:A2:18
[08:43:22][C][wifi:363]:   SSID: 'myAP1'
[08:43:22][C][wifi:364]:   IP Address: 192.168.0.17
[08:43:22][C][wifi:366]:   BSSID: 44:E9:DD:6E:71:6C
[08:43:22][C][wifi:367]:   Hostname: 'esp32-adc-sleep'
[08:43:22][C][wifi:369]:   Signal strength: -51 dB ▂▄▆█
[08:43:22][C][wifi:373]:   Channel: 11
[08:43:22][C][wifi:374]:   Subnet: 255.255.255.0
[08:43:22][C][wifi:375]:   Gateway: 192.168.0.1
[08:43:23][C][wifi:376]:   DNS1: 192.168.0.1
[08:43:23][C][wifi:377]:   DNS2: 0.0.0.0
[08:43:23][C][ota:093]: Over-The-Air Updates:
[08:43:23][C][ota:094]:   Address: esp32-adc-sleep.local:3232
[08:43:23][C][ota:097]:   Using Password.
[08:43:23][C][api:025]: Setting up Home Assistant API server...
[08:43:23][D][main:205]: Sample 1
[08:43:23][D][sensor:127]: 'esp32-sleeping-volts': Sending state 0.76862 V with 2 decimals of accuracy
[08:43:23][C][deep_sleep:037]: Setting up Deep Sleep...
[08:43:23][I][deep_sleep:042]: Scheduling Deep Sleep to start in 1000 ms
[08:43:23][I][app:062]: setup() finished successfully!
[08:43:23][I][app:102]: ESPHome version 2022.11.3 compiled on Nov 30 2022, 08:41:18
[08:43:23][C][wifi:504]: WiFi:
[08:43:23][C][wifi:362]:   Local MAC: FC:F5:C4:07:A2:18
[08:43:23][C][wifi:363]:   SSID: 'myAP1'
[08:43:23][C][wifi:364]:   IP Address: 192.168.0.17
[08:43:23][C][wifi:366]:   BSSID: 44:E9:DD:6E:71:6C
[08:43:23][C][wifi:367]:   Hostname: 'esp32-adc-sleep'
[08:43:23][C][wifi:369]:   Signal strength: -51 dB ▂▄▆█
[08:43:23][C][wifi:373]:   Channel: 11
[08:43:23][C][wifi:374]:   Subnet: 255.255.255.0
[08:43:23][C][wifi:375]:   Gateway: 192.168.0.1
[08:43:23][C][wifi:376]:   DNS1: 192.168.0.1
[08:43:23][C][wifi:377]:   DNS2: 0.0.0.0
[08:43:23][C][logger:293]: Logger:
[08:43:23][C][logger:294]:   Level: DEBUG
[08:43:23][C][logger:295]:   Log Baud Rate: 115200
[08:43:23][C][logger:296]:   Hardware UART: UART0
[08:43:23][D][main:348]: Sample 2
[08:43:23][D][sensor:127]: 'esp32-sleeping-volts': Sending state 0.76396 V with 2 decimals of accuracy
[08:43:23][C][gpio.output:010]: GPIO Binary Output:
[08:43:23][C][gpio.output:011]:   Pin: GPIO2
[08:43:23][D][main:356]: Sample 3
[08:43:23][D][sensor:127]: 'esp32-sleeping-volts': Sending state 0.76784 V with 2 decimals of accuracy
[08:43:23][C][adc:087]: ADC Sensor 'esp32-sleeping-volts'
[08:43:23][C][adc:087]:   Device Class: 'voltage'
[08:43:23][C][adc:087]:   State Class: 'measurement'
[08:43:23][C][adc:087]:   Unit of Measurement: 'V'
[08:43:23][C][adc:087]:   Accuracy Decimals: 2
[08:43:23][C][adc:097]:   Pin: GPIO36
[08:43:23][C][adc:099]:  Attenuation: auto
[08:43:23][C][adc:125]:   Update Interval: 1.0s
[08:43:23][C][mdns:103]: mDNS:
[08:43:23][C][mdns:104]:   Hostname: esp32-adc-sleep
[08:43:23][C][ota:093]: Over-The-Air Updates:
[08:43:23][C][ota:094]:   Address: esp32-adc-sleep.local:3232
[08:43:23][C][ota:097]:   Using Password.
[08:43:23][C][api:138]: API Server:
[08:43:23][C][api:139]:   Address: esp32-adc-sleep.local:6053
[08:43:23][C][api:143]:   Using noise encryption: NO
[08:43:23][C][homeassistant.binary_sensor:039]: Homeassistant Binary Sensor 'prevent_deep_sleep'
[08:43:23][C][homeassistant.binary_sensor:040]:   Entity ID: 'input_boolean.prevent_deep_sleep'
[08:43:23][D][main:364]: Sample 4
[08:43:23][D][sensor:127]: 'esp32-sleeping-volts': Sending state 0.76935 V with 2 decimals of accuracy
[08:43:23][C][deep_sleep:049]: Setting up Deep Sleep...
[08:43:23][C][deep_sleep:052]:   Sleep Duration: 60000 ms
[08:43:23][C][deep_sleep:055]:   Run Duration: 1000 ms
[08:43:23][D][main:372]: Sample 5
[08:43:23][D][sensor:127]: 'esp32-sleeping-volts': Sending state 0.77007 V with 2 decimals of accuracy
[08:43:23][D][sensor:127]: 'esp32-sleeping-volts': Sending state 0.77323 V with 2 decimals of accuracy
[08:43:23][I][deep_sleep:116]: Beginning Deep Sleep
[08:43:23][I][deep_sleep:118]: Sleeping for 60000000us
[08:43:23][D][esp32.preferences:113]: Saving 1 preferences to flash...
[08:43:23][D][esp32.preferences:142]: Saving 1 preferences to flash: 0 cached, 1 written, 0 failed

My question is this: Why are there 4 sensor log entries at time-tag [08:43:20]?
I see the 5 readings that I am expecting later but again, I’m puzzled that they are mixed with what seems to be housekeeping stuff. Is my understanding of on_boot: priority: 100 incorrect? Do I need a different command to wait for startup to finish?

Regards, M.

Try priority: -100 rather than 100.

250.0: At this priority, WiFi is initialized.

200.0: Network connections like MQTT/native API are set up at this priority.

-100.0: At this priority, pretty much everything should already be initialized.

I noticed the question in your title is different to the question in your post.

Thank you Daryl,
Good spot! But no - it does not seem to make any difference?
There are still 4 ADC reads and values sent - even before the WiFi is connected!
If I correctly understand what I am seeing in the UART log.

Can this be correct? I thought that memory is cleared after reset and/or sleep so I am guessing that it is not cached processes from last loop.

Regards, M.

Thank you for the observation.
Do you have any pointers on either question? You will note that I am trying to follow the crumb you threw-out yesterday.
Regards, M.

Hmm - only other thing I can suggest is to do a a wait_until: and in there check for api_connected:.

I’ve never tried it but theoretically should work.

We’ll for the title question my shared config contained a full working solution for what you want to do. So more a three course meal rather than a crumb if you ask me.

It even had the priority set at -100 which seemed to be working pretty well for me.

I can point out the key parts of it’s too much to dig through.

I did noticed some disorderly logs too but as they didn’t appear to be impacting functionality I just ignored them. I think on boot the logger might get a bit overwhelmed/flooded and has to play catch-up (my guess only).

I did a lot of visualization in Grafana to help validate what data is actually sent/received to HA. And you’ll notice I have checks that all data is actually sent before I actually sleep again. I might consolidate some of this after a period of in situ testing.

Hi Mahko(?),
My apologies if I sounded rude? The “crumb” I was referring to was: “The key thing is to trigger updates on boot …” That hadn’t occurred to me until your comment.
And I agree, your example is a “three course meal”. At my stage of esphome/yaml experience, to continue the dining metaphor, a little too bloating for me!
Rest assured, I’ll be looking for your advice, as I try to understand the code you have offered.

Many thanks, Martin

1 Like

No prob.

This was the first project where I used this approach so I’m sure the code could be improved.

I’ve been doing more tweaks to it but I believe it’s pretty sound - it was some of the ESPHome devs on Discord who suggested the approach.

Oh … lucky you :wink:. I’ve never been able to get into Discord to ask any questions?
Regards, M

It’s open to all.

See the “join the community” link here.

Once you get the hang of the style of interaction it’s really good.

Much more interactive/faster support and the level of knowledge of the average user is much higher too.

Yep, I’ve seen and tried the invite link. This is what I get?
image
… so I “Continue to Discord”…
image
… So I start…

… but as I have not registered and do not have a password, I don’t get very far!!!

I know, its not relevant in this forum, but I’ just trashing around trying to make some progress!

Regards, Martin

Hmm right weird …

Hi again Mahko,

Guess I’m just showing off now :clown_face:, but I think I’ve got what I was looking for. There are still some bits I’d like to tidy up but subject to testing on the real hardware (ADC input pre-conditioning PCB is in the Chinese pipe-line), I think I’m done.
Here’s my code:

esphome:
  name: "esp32-adc-sleep"
  # logger.log: calls will only show on UART until the API connects...
  on_boot:
    priority: -100.0
    then:
    - logger.log: "Waiting for the API to connect..."
    - wait_until:
        condition:
          api.connected:
    - if:
        condition:
          api.connected:
        then:
          - logger.log: "API Connected"
        else:
          - logger.log: "API NOT Connected"  
    - logger.log: "I'm still in the on_boot code..."

# Awaiting help from the forum....
# ... on how to avoid the "- delay: 5s"
# https://community.home-assistant.do/t/how-to-test-the-returned-id-binary-sensor-state-is-valid/497299
    - delay: 5s
    - logger.log:
        format: 'Prevent Sleep Flag is set to: %i'
        args: [id(prevent_deep_sleep).state]


    - if:
        condition:
          binary_sensor.is_on: prevent_deep_sleep
        then:
          - logger.log: "Turning ON LED"
          - output.turn_on: blue_led
          - logger.log: "Sampling stopped!"
          - logger.log: "Waiting for OTA Update..."
          - logger.log: "UnTag flag and run OTA Update..."
          - wait_until:
              condition:
                lambda: |-
                  return false; 
          - logger.log: "I'm hoping that this never get printed!"
              
        else:
          - repeat:
              count: 5
              then:
              - component.update: lei_volts
              - delay: 10ms
              - logger.log: "Reading 'n' of 5 ADC samples..."
              #https://community.home-assistant.io/t/how-do-i-print-the-value-of-a-loop-counter/497365
          
          - logger.log: "Turning OFF LED"
          - output.turn_off: blue_led
          - logger.log: 'Entering Deep Sleep'
          - deep_sleep.enter: deep_sleep_control

esp32:
  board: esp32dev  
  framework:
    type: arduino    

# Enable logging
logger:
  level: DEBUG

# Enable Home Assistant API
api:
  
ota:
  password: !secret ota_password

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

output:
  platform: gpio
  pin: GPIO2      #The only led I've got
  id: blue_led

# Look to the Home Assistant UI to find a flag ...
# ... this flag is used to tell this program ...
# ... whether to continue its "Read ADC/Sleep" cycle ...
# ... or if it should "stay awake" in preparation ...
# ... for an OTA update.
binary_sensor:
  - platform: homeassistant
    id: prevent_deep_sleep
    entity_id: input_boolean.prevent_deep_sleep
    # Use the on-board blue LED (GPIO2) to ...
    # ... give feedback. Only needed during development ...
    # ... but kept active as there no overhead.
    on_state:
      then:
        if:
          condition:
            binary_sensor.is_on: prevent_deep_sleep
          then:
            - logger.log: "Turning ON LED"
            - logger.log:
                format: "Sleep Flag is: %i"
                args: ['id(prevent_deep_sleep).state']
            - output.turn_on: blue_led
          else:
            - logger.log: "Turning OFF LED"
            - logger.log:
                format: "Sleep Flag is: %i"
                args: ['id(prevent_deep_sleep).state']
            - output.turn_off: blue_led
 
                
# Do not let sensor run in the background ...
# ... ie "update_interval: never"
# The ADC will be triggered as required (- component.update: volts) ...
# ... by the "repeat: count:" in the "on-boot" action.
sensor:
  - platform: adc
    pin: GPIO36
    id: lei_volts
    name: "Leisure Battery"
    update_interval: never    
    attenuation: auto
    accuracy_decimals: 2
    filters:
    - median:
        window_size: 5
        send_every: 5
        send_first_at: 5

# Do not let sleep run in the background...
# ... ie no run-duration:
# It is called (- deep_sleep.enter: deep_sleep_control) from ...
# ... the on_boot: action (at head of this .yaml)
deep_sleep:
  id: deep_sleep_control
#  run_duration: 1s
  sleep_duration: 1min

Any comments/improvements you can offer gratefully received. And once again, thank for the help.
Regards, M.

1 Like

Nice progress!

I’m still fine tuning mine too.

When mine is working well it is up (as per uptime sensor) for about 7-9 secs before it sleeps again. Which I figure is good enough.

If one of the sensors doesn’t update properly it will wait a max of 30secs before sleeping.

I might look into using the “API connected”. I recall seeing that but haven’t put it to use.