Pulse_meter or pulse_counter and deep_sleep

Hi,

I try to build a battery driven Water Meter. For it a have ordered me some ESP32_Bat_Pro devices from EzSBC. I want to track my water usage on the ZENNER ETKDI-N with preinstalled reed contact which counts ≥1L/Impuls. I connected it to the ESP between IO14 and GND.

The reed closes, when a Liter water passed the counter and opens again, when a new liter starts to pass the counter.

My first problem is, that the counting works not like I expect it. I had it already counting something, but it got not saved. I seams that ESPHome does not save the values from pulse_meter / pulse_counter (I tested both, but only got pulse_meter working) when deep_sleep is used.

WakeUp is working, when GPIO14 get connected to GND, but it seams to me, that there are also two other problems/questions:

  1. is a pulse also counted, when he wakes up, or get those pulses dropped?
  2. the ESP goes to sleep also when water flows
  3. Save the state of pulse_meter before deep_sleep - maybe its not available in ESPHome right now - like it was on ESPEasy

Can somebody help?

I have currently the following setup:

esphome:
  name: "gwz-vorne"
  friendly_name: Gartenwasserzähler Vorne
  libraries:
    - "Wire"
  on_boot:
    priority: 600
    then:
      - switch.turn_on: led_blue

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "XXXX"
  services:
    - service: set_pulse_total
      variables:
        new_pulse_total: int
      then:
        - pulse_meter.set_total_pulses:
            id: water_meter
            value: !lambda 'return new_pulse_total;'

ota:
  password: !secret ota_password
  on_begin:
    then:
      - switch.turn_on: led_red
  on_end:
    then:
      - switch.turn_off: led_red
      - switch.turn_on: led_green

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

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

captive_portal:
    
web_server:
  port: 80
  local: true

i2c:
  id: bus_a

deep_sleep:
  run_duration: 30s
  sleep_duration: 60min
  wakeup_pin: GPIO14
  wakeup_pin_mode: INVERT_WAKEUP

sensor:

  - platform: lc709203f
    i2c_id: bus_a
    address: "0x0B"
    battery_voltage:
      name: Battery Volt
    battery_level:
      name: Battery Level
    icversion:
      name: IC Version
    cell_charge:
      name: Cell Charge
    update_interval: 3600s

  - platform: pulse_meter
    id: water_meter
    name: "Wasser Durchflussmenge"
    pin: 
      number: GPIO14
      inverted: False
      mode:
        input: True
        pullup: True
    internal_filter: 10ms
    unit_of_measurement: "liter/min"
    icon: "mdi:water"
    total:
      id: water_meter_total_m3
      name: "Wasser Verbrauch"
      unit_of_measurement: "m³"
      accuracy_decimals: 3
      device_class: water
      state_class: total_increasing
      filters:
        - multiply: 0.001

  - platform: template
    id: water_usage_total_liter
    name: "Wasser Verbrauch"
    accuracy_decimals: 0
    unit_of_measurement: "liter"
    icon: "mdi:water"
    device_class: water
    state_class: total_increasing
    lambda: return (id(water_meter_total_m3).state * 1000);
    update_interval: 10s

switch:

  - platform: restart
    name: "Restart"

  - platform: gpio
    id: led_red
    name: LED Red
    internal: True
    pin:
      number: GPIO16
      inverted: True

  - platform: gpio
    id: led_green
    name: LED Green
    internal: True
    pin:
      number: GPIO17
      inverted: True

  - platform: gpio
    id: led_blue
    name: LED Blue
    internal: True
    pin:
      number: GPIO18
      inverted: True

You really can’t use deep sleep with this sort of sensor, for 2 reasons:

  1. It will ALWAYS lose pulses on wakeup. The device is effectively rebooting on wake, everything that happens while that reboot is in progress is lost.
  2. It will ALWAYS go to sleep after 30 seconds - regardless of whether the wakeup pin is active or not.

Regarding the sensors not working, can you provide the ESP logs?

Ok, it is was I have expected… but only from the current ESPHome perspective… because ESP32 has a ULP Processor which can handle this

Andreas Spiess has made a nice video about the ULP from ESP32

The idea was to always count the pulses. Best will be that it counts in the ULP. At every X minutes it will wake up report battery and pulse count over wifi.

EDIT: the ZENNER LoRa/M-Bus devices and others do for sure the same. They are also attached with a battery with a lifetime from 10 years (like this module does) - I don’t know what type of processor they use, but they must be also really ultra low power capable.

I will report the logfiles later when the ESP wake up again…

1 Like

Ok, I am back home… Thats are my logfiles:

INFO Trying to connect to gwz-vorne.local in the background
INFO Successfully connected to gwz-vorne.local
[10:01:55][I][app:102]: ESPHome version 2023.5.1 compiled on May 23 2023, 21:54:54
[10:01:55][C][wifi:505]: WiFi:
[10:01:55][C][wifi:363]:   Local MAC: 94:3C:C6:C2:73:1C
[10:01:55][C][wifi:364]:   SSID: [redacted]
[10:01:55][C][wifi:365]:   IP Address: 192.168.99.46
[10:01:55][C][wifi:367]:   BSSID: [redacted]
[10:01:55][C][wifi:368]:   Hostname: 'gwz-vorne'
[10:01:55][C][wifi:370]:   Signal strength: -86 dB ▂▄▆█
[10:01:55][C][wifi:374]:   Channel: 1
[10:01:55][C][wifi:375]:   Subnet: 255.255.255.0
[10:01:55][C][wifi:376]:   Gateway: 192.168.99.1
[10:01:55][C][wifi:377]:   DNS1: 192.168.99.1
[10:01:55][C][wifi:378]:   DNS2: 0.0.0.0
[10:01:55][C][logger:301]: Logger:
[10:01:55][C][logger:302]:   Level: DEBUG
[10:01:55][C][logger:303]:   Log Baud Rate: 115200
[10:01:55][C][logger:305]:   Hardware UART: UART0
[10:01:55][C][i2c.arduino:054]:   SDA Pin: GPIO21
[10:01:55][C][i2c.arduino:059]:   Recovery: bus successfully recovered
[10:01:56][C][uptime.sensor:031]:   State Class: 'total_increasing'
[10:01:56][C][template.sensor:022]: Template Sensor 'Wasser Verbrauch'
[10:01:56][C][template.sensor:023]:   Update Interval: 10.0s
[10:01:56][D][sensor:094]: 'Uptime': Sending state 21.69300 s with 0 decimals of accuracy
[10:01:56][C][switch.gpio:031]:   Pin: GPIO16
[10:01:56][C][switch.gpio:068]: GPIO Switch 'LED Green'
[10:01:56][C][version.text_sensor:021]: Version Text Sensor 'ESPHome Version'
[10:01:56][C][version.text_sensor:021]:   Icon: 'mdi:new-box'
[10:01:56][C][internal_temperature:055]: Internal Temperature Sensor 'Internal Temperature'
[10:01:56][C][internal_temperature:055]:   Unit of Measurement: '°C'
[10:01:56][C][lc709203f.sensor:123]: LC709203F:
[10:01:56][C][lc709203f.sensor:132]:     Device Class: 'voltage'
[10:01:56][C][lc709203f.sensor:132]:     State Class: ''
[10:01:56][C][lc709203f.sensor:134]:     Device Class: 'battery'
[10:01:56][C][pulse_meter:074]: Pulse Meter 'Wasser Durchflussmenge'
[10:01:56][C][pulse_meter:074]:   State Class: 'measurement'
[10:01:56][C][pulse_meter:074]:   Unit of Measurement: 'liter/min'
[10:01:56][C][restart:068]: Restart Switch 'Restart'
[10:01:56][C][web_server:152]:   Address: gwz-vorne.local:80
[10:01:56][C][ota:097]:   Using Password.
[10:01:56][C][wifi_signal.sensor:009]: WiFi Signal 'WiFi Signal'
[10:01:56][C][wifi_signal.sensor:009]:   State Class: 'measurement'
[10:01:57][D][sensor:094]: 'Uptime': Sending state 23.64800 s with 0 decimals of accuracy
[10:01:59][D][sensor:094]: 'Uptime': Sending state 25.65100 s with 0 decimals of accuracy
[10:01:59][D][sensor:094]: 'Wasser Verbrauch': Sending state 0.00000 liter with 0 decimals of accuracy
[10:02:01][D][sensor:094]: 'Uptime': Sending state 27.64800 s with 0 decimals of accuracy
[10:02:03][D][sensor:094]: 'Uptime': Sending state 29.65400 s with 0 decimals of accuracy
[10:02:05][D][sensor:094]: 'Uptime': Sending state 31.64800 s with 0 decimals of accuracy
[10:02:07][D][sensor:094]: 'Uptime': Sending state 33.65400 s with 0 decimals of accuracy
[10:02:10][D][sensor:094]: 'Uptime': Sending state 35.64900 s with 0 decimals of accuracy
[10:02:10][D][sensor:094]: 'Wasser Verbrauch': Sending state 0.00000 liter with 0 decimals of accuracy
[10:02:11][D][sensor:094]: 'Uptime': Sending state 37.65100 s with 0 decimals of accuracy
[10:02:12][I][deep_sleep:116]: Beginning Deep Sleep
[10:02:12][I][deep_sleep:118]: Sleeping for 3600000000us
WARNING gwz-vorne.local: Connection error occurred: Ping response not received after 90.0 seconds
INFO Processing unexpected disconnect from ESPHome API for gwz-vorne.local
WARNING Disconnected from API
WARNING Can't connect to ESPHome API for gwz-vorne.local: Error resolving IP address: [Errno -3] Temporary failure in name resolution
INFO Trying to connect to gwz-vorne.local in the background
INFO Successfully connected to gwz-vorne.local
[11:02:18][D][sensor:094]: 'Wasser Verbrauch': Sending state 0.00000 liter with 0 decimals of accuracy
[11:02:18][D][sensor:094]: 'Uptime': Sending state 25.56300 s with 0 decimals of accuracy
[11:02:20][D][sensor:094]: 'Uptime': Sending state 27.57000 s with 0 decimals of accuracy
[11:02:22][D][sensor:094]: 'Uptime': Sending state 29.56300 s with 0 decimals of accuracy
[11:02:24][D][sensor:094]: 'Uptime': Sending state 31.56700 s with 0 decimals of accuracy
[11:02:26][D][sensor:094]: 'Uptime': Sending state 33.56300 s with 0 decimals of accuracy
[11:02:28][D][sensor:094]: 'Wasser Verbrauch': Sending state 0.00000 liter with 0 decimals of accuracy
[11:02:28][D][sensor:094]: 'Uptime': Sending state 35.56300 s with 0 decimals of accuracy
[11:02:30][D][sensor:094]: 'Uptime': Sending state 37.56700 s with 0 decimals of accuracy
[11:02:32][D][sensor:094]: 'Uptime': Sending state 39.56300 s with 0 decimals of accuracy
[11:02:34][I][deep_sleep:116]: Beginning Deep Sleep
WARNING gwz-vorne.local: Connection error occurred: Ping response not received after 90.0 seconds

I personally have no experience at all with deep sleep, but I do have a watermeter setup with an ESP32, using a LJ18A3-8-Z-BX 5V proximity sensor and the ESPHome pulse counter.
And to be able to handle sudden power outages I added some code to store the pulse counter value locally to flash at shutdown and every 30 seconds, and to reload the value at boot.
This is some example code:


# ======================================
# Created:            20220721
# Last modified:      20230109
# --------------------------------------
# MCU type: ESP32
# MCU board: LilyGO TTGO T7 Mini32 V1.3
# --------------------------------------
# Main usage:         Watermeter
# --------------------------------------
# Installed features:
# - Friendly name substitution
# - Pulse counter
# - LJ18A3-8-Z-BX 5V proximity sensor
# ======================================
esp32:
  board: ttgo-t7-v13-mini32
  framework:
    type: arduino

esphome:
  name: watermeter
  on_boot:
    then:
      - pulse_counter.set_total_pulses:
          id: pulse_counter_water
          value: !lambda 'return id(global_water_total);'
  on_shutdown:
    then:
      - globals.set:
          id: global_water_total
          value: !lambda 'return id(water_total_liter).state;'

interval:
  - interval: 30s
    then:
      - globals.set:
          id: global_water_total
          value: !lambda 'return id(water_total_liter).state;'

preferences:
  flash_write_interval: 60s

# Global variables
globals:
  - id: global_water_total
    type: int
    restore_value: yes

substitutions:
  friendly_name: Watermeter

# Enable Home Assistant API
api:

ota:
  password: !secret pwd_ota_watermeter

wifi:
  ssid: !secret ssid_iot_wlan
  password: !secret pwd_iot_wlan
  domain: !secret ip_domain
  manual_ip:
    static_ip: !secret ip_esp_watermeter
    gateway: !secret ip_gateway
    subnet: !secret ip_subnet
    dns1: !secret ip_dns1
    dns2: !secret ip_dns2
  ap:
    ssid: !secret ssid_fbap_wlan_watermeter
    password: !secret pwd_fbap_wlan_watermeter

captive_portal:

sensor:
  # Water meter setup
  - platform: pulse_counter
    pin: GPIO16
    update_interval : 6s
    name: $friendly_name Water Rate
    id: pulse_counter_water
    use_pcnt: true
    unit_of_measurement: "l/min"
    icon: "mdi:water-outline"
    total:
      name: $friendly_name Water Total Liter
      id: water_total_liter
      device_class: water
      state_class: total_increasing
      accuracy_decimals: 0
      unit_of_measurement: "l"
      icon: "mdi:water-plus-outline"
  - platform: template
    name: $friendly_name Water Total
    device_class: water
    state_class: total_increasing
    accuracy_decimals: 3
    unit_of_measurement: "m³"
    icon: "mdi:water-plus-outline"
    lambda: return (id(water_total_liter).state * 0.001);
    update_interval: 6s

I am not sure, but it might be that you can use a similar setup for deep sleep?

Thanks @thusassistint I will test this.

but the more safe way would be to use ulp. I have seen, that Tasmota can use ULP

Also I have found code to program the ulp as a pulse counter…

1 Like

Just to be complete: I also found that it is possible to use ESPHome with ULP.

When I have time I will try to get it working.

My situation is that I cannot setup electricity next to the watermeter so am targeting a non-esp, zigbee solution. The sensors however are consuming anyhow, did anyone of you look at low-power sensors?
Thx

How did you go with this? I’m interested in getting the ULP pulse counter working for the electricity meter, where I ironically don’t have wifi

i had currently no time do look into it.
but without wifi is seems that you need to store data on a sd card. Or better get wifi there with a repeater or mesh ap :slight_smile: