Gas meter (pulses) using Beetle ESP32-C6

Are the ZigBee solutions using the current crop of ESP processors? I strongly suspect not.

The ones I linked/have seen use zigbee door sensors or similar. They are not esp based.

I just found this on AliExpress:
AU$13.69 | Aqara Door Window Sensor Zigbee MCCGQ11LM Wireless APP Remote Control for Smart Home Work With Xiaomi Mijia Apple HomeKit APP
https://a.aliexpress.com/_mNYlhHX

You’ll see in the link I added here people repurpose them for a wide range of applications.
I’m not saying they are for sure a good solution for your use case but I’ve done similar things with them and it’s straight forward.

Check the thread for the latest and greatest sensor to use if you go down that path.

I removed the pulse_counter component and replaced it with a simple template and a global that increases each time the board wakes up.

I have it running for a couple hours and it seems this may be the final configuration.

esphome:
  name: gas-meter
  friendly_name: Gas Meter
  on_boot:  # This executes on boot and deep sleep wakes up
    priority: -100.0
    then:
      - if:
          # https://esphome.io/components/deep_sleep/#esp32-wakeup-cause
          condition:
            lambda: 'return 7 == esp_sleep_get_wakeup_cause();' # 7 = ESP_SLEEP_WAKEUP_GPIO
          then:
            - lambda: 'id(total_pulses) += 1;'

preferences:
  flash_write_interval: 60s

globals:
  - id: total_pulses
    type: int
    restore_value: yes
    initial_value: "0"

esp32:
  variant: esp32c6
  board: esp32-c6-devkitc-1
  framework:
    type: esp-idf

# Enable logging
logger:

ota:
  - platform: esphome
    password: "SECRET"

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

network:
  enable_ipv6: true

openthread:
  tlv: !secret openthread_tvl
  device_type: MTD
  poll_period: 600s # 10 minutes

deep_sleep:
  wakeup_pin: 
    number: 4
    allow_other_uses: true
    mode:
      input: true
      pullup: true
    inverted: true
  wakeup_pin_mode: KEEP_AWAKE # To avoid counting double if the board wakes up again because the reed sensor is making contact
  run_duration: 1min
  sleep_duration: 60min

sensor:
  - platform: template
    name: "Total consumption"
    id: total_gas_consumption
    unit_of_measurement: "m³"
    icon: "mdi:meter-gas"
    accuracy_decimals: 2
    device_class: "gas"
    state_class: "total_increasing"
    lambda: 'return id(total_pulses) * 0.01;'
    update_interval: 10s
  - platform: adc
    name: "Battery voltage"
    pin: GPIO0
    accuracy_decimals: 2
    update_interval: 1h
    attenuation: 12dB
    samples: 10
    filters:
      - multiply: 2.0  # The voltage divider requires us to multiply by 2
  - platform: template
    name: "Wakeup Cause"
    accuracy_decimals: 0
    lambda: return esp_sleep_get_wakeup_cause();

binary_sensor:
  - platform: gpio
    name: "Gas Pulse"
    pin:
      number: 4
      allow_other_uses: true
      mode:
        input: true
        pullup: true
      inverted: true
    filters:
      - delayed_on: 50ms  # Debounce
    on_press:
      then: # This increases the count when the meter makes another loop before the board goes to sleep
        - lambda: 'id(total_pulses) += 1;'

# Enable Home Assistant API
api:
  encryption:
    key: "SECRET"
  actions:
    # Allow update the total count from HASS
    - action: set_pulse_total
      variables:
        new_pulse_total: int
      then:
        - globals.set:
            id: total_pulses
            value: !lambda 'return new_pulse_total;'

Much better. But why you keep it awake for 1min, I would expect that with openthread it takes just few sec to boot and connect. Remember that at wake esp draws 1000x more than in deep sleep.

Considered as well ESP32 solution, but finally implemented as described in this topic

Since the last post, I noticed no improvement in the battery usage so, at looking at the build logs, I spotted an entry that say something about falling back to pooling mode to detect changes in pins due to the same pin was used by a sensor as well.

So, I had to try new configurations.

After a few tries, I ended with this one that only increases the count when the board wakes up due to a change of voltage in a pin. It stays awake for 10 seconds and then backs to sleep.

My gas meter makes a pulse for every 0.01 m3. On my tests I saw my gas boiler burning that in around 15 seconds. It could do more, but I think it tends to not burn at full power to be efficient.

The battery

4.14v on Feb 17th 11am
3.97 on Feb 22th 11am (measured using a multimeter)
That’s a 0.17v drop in 5 days (120 hours) using Thread. That’s a rate of 0.00141v/hour. That’s almost a 4x improvement from the 0.0054v/hour i was getting in my first attempt using Wifi without deep sleep.

Somehow, I was hoping better results. The thuth is that the board wakes up too many times. In average my home consumes 7m3 of gas. That’s 700 wakes.

In theory this means I should charge the battery every 22 days. Not great, not terrible.

Something that bothers me thought is the battery level measurement now.

The ADC sensor is configured to run once an hour and use 10 samples. That works great when the board doesn’t deep sleep. But now it does, I get this:

Over time (days) you can see it goes down, but there’s no much outliners in the reports.

The current configuration:

esphome:
  name: gas-meter
  friendly_name: Gas Meter
  on_boot: # This executes on boot and deep sleep wakes up
    priority: -100.0
    then:
      - if:
          # https://esphome.io/components/deep_sleep/#esp32-wakeup-cause
          condition:
            lambda: 'return 7 == esp_sleep_get_wakeup_cause();' # 7 = ESP_SLEEP_WAKEUP_GPIO
          then:
            - lambda: 'id(total_pulses) += 1;'

preferences:
  flash_write_interval: 2s

globals:
  - id: total_pulses
    type: int
    restore_value: yes
    initial_value: "0"

esp32:
  variant: esp32c6
  board: esp32-c6-devkitc-1
  framework:
    type: esp-idf

# Enable logging
logger:

ota:
  - platform: esphome
    password: "SECRET"

network:
  enable_ipv6: true

openthread:
  tlv: !secret openthread_tvl
  device_type: MTD
  poll_period: 600s # 10 minutes

deep_sleep:
  wakeup_pin: 
    number: 6
    mode:
      input: true
      pullup: true
    inverted: true
  wakeup_pin_mode: KEEP_AWAKE  # To avoid counting double if the board wakes up again because the reed sensor is making contact
  run_duration: 
    default: 1min
    gpio_wakeup_reason: 10s
  sleep_duration: 1h
  

sensor:
  - platform: template
    name: "Total consumption"
    id: total_gas_consumption
    unit_of_measurement: "m³"
    icon: "mdi:meter-gas"
    accuracy_decimals: 2
    device_class: "gas"
    state_class: "total_increasing"
    lambda: 'return id(total_pulses) * 0.01;'
    update_interval: 2s
  - platform: adc
    name: "Battery voltage"
    pin: GPIO0
    accuracy_decimals: 2
    update_interval: 1h
    attenuation: 12dB
    samples: 10
    filters:
      - multiply: 2.0  # The voltage divider requires us to multiply by 2
  - platform: template
    name: "Wakeup Cause"
    accuracy_decimals: 0
    update_interval: 2s
    lambda: return esp_sleep_get_wakeup_cause();

# Enable Home Assistant API
api:
  encryption:
    key: "SECRET"
  actions:
    # Allow update the total count from HASS
    - action: set_pulse_total
      variables:
        new_pulse_total: int
      then:
        - globals.set:
            id: total_pulses
            value: !lambda 'return new_pulse_total;'

This was my initial approach. It worked well, but the problem was that it requires HomeAssistant to be running to count the pulses.

I wanted a solution does the count and remembers the total usage so, even if the network fails or the server is down, the sensor could keep counting and report the current usage once HASS pulls the data.

@dzegarra Thanks for your reply. I’m just curious — what was the reason for choosing the ESP32-C6 board (high-speed IoT with Wi-Fi), which consumes more power, when the ESP32-H2 with Zigbee support, which typically uses less power, is also available?

Voltage drop is not linear. It drops quite rapidly to 3.7V and then it stays there 80% of the battery discharge.
So your improvement looks much better than you calculated.

The reason was convineance. This is the first ESP32 board I got my hands on. When I read this board had Thread and a battery charger manager for only 6 buck, I went for it.

I see the H2 consumes half the power.

Maybe I’ll buy one.

The total wake time will be driving a lot of your battery usage.

You can probably shave it down a lot by using a “push approach” to your sensor updates and sleeping once done.

You can trace through that kind of approach here.

From what I recall wifi is a major power consumer. I think there’s more control over turning wifi on/off these days, so you might even be able to restrict connecting to wifi and transmitting data to a few times a day (and just store data updates on the esp between this).

I read your post. Nice project.

In my case, I cannot avoid waking up the device since I need it to be awake to count the pulses.

Maybe, what would help would be to keep the antena off between these wakes, and turn it on to send the total collected pulses count every X pulses.

But, I couldn’t find nothing that would allow me that level of control over the antena in the ESPHome docs.

This is your unsolvable conundrum, cause by incorrect component selection. You shouldn’t be using that version of the ESP32 for low power operations. Like putting lipstick on a pig, it looks pretty, but at the end of the day, you still have a flat battery far too early, and everything still stinks

Rather than continue to try and eke a few milliamps less out of your ESP chip, reconsider your design. Separate the counting, maybe to another chip, and the transmission to something more power friendly. Maybe use a network protocol that has faster setup time than Wifi, such as BLE (the LE stands for Low Energy) instead, that uses far less energy for transmission. Your battery up time can then be measured in years instead of days. Your vocabulary will change from milliamps to nanoamps.

My suggestion: Check out the nRF52840 which is a similar price point as a ESP32 H2 series and absolutely sips the battery power instead of gulping it.

Bonus: ESPHome supports both chips, making your yaml code efforts reusable with very minor changes.

Don’t be disenchanted. Thousands of hobbyists and electronic engineers over the last few years since the low cost ESP chips were released have attempted to go down the path of trying to force their ESP chips to run on batteries, and have eventually admitted defeat. Accept the inevitable conclusion - you are wasting your time. Even the chip designers at Espressif have acknowledged it, refining their chip design to release lower power versions eventually, as the rest of the world moved to other chip vendors and alternate designs to solve their battery operational requirements.

I agree that real low power setups are not done with esp, neither with esphome.
But since this forum topic is for esphome and nrf52 doesn’t have any power/sleep control here at the moment, the choices are limited.
That board OP uses is likely one of the bests you can get for consumption with esphome.
700 wakeups per day should give reasonable battery life. Only thing that matters is the time esp is awake. 2s vs 10s is ~5x battery life. 20uA deep sleep current is irrelevant.

I was contemplating if it matters much if it connects to WiFi / API or not when it wakes. From what I recall that takes time and power.

Maybe you could have a counter for wakes and only connect to WiFi every nth time, else just sleep immediately after pulse counter update / store ?

That might get most wakes to just a few seconds.
Data updates to HA every pulse is probably beyond needed for monitoring.

Sorry reread this. See my comments above. I think it’s worth exploring further.

Even if you can’t turn antenna off (I’m not sure), I think sleep immediately after counter update except every nth time has some promise as a strategy.

Edit: There’s this too. Not sure what that gets you.

See wifi.enable, wifi.disable and enable_on_boot

Edit 2: Sorry all reading along, my messages above are repetitive. Multi-tasking today and clearly I’m not great at that :slight_smile: .

Yes, esphome wakeup is long process in any case. With wifi/api it’s painfully long.

As a rule, lower power consumption comes with lower transmission range. If your device is located far from the base transmitter, this ESP32-H2 may not be a suitable choice.
P.S. I’m just awaiting mine H2 and RF52840 boards from AliExpress to play around with it. By the way for RF52840 is possible to use Arduino IDE :grinning:

I’m looking forward to seeing your project and wish you great success!

I’ve created the project Esp32H2GasCounter, which is an adaptation of Ignacio’s Zigbee Gas Counter for the ESP32-H2 board. Thanks to Ignacio for the original work.

Hi there!

Thanks awesome! Hope you enjoy the project as I’m doing. The code should “just work” with very small modifications in an Esp32H2 board!

Best regards
Ignacio