Gas and water meters on ESP32 in Home Assistant
The time has come for the next verification of the gas meter and it was decided to replace it with a meter with a pulse output. The task turned out to be non-trivial, since there was a strict limitation on connection parameters. But, thank the marketplaces, not even a week passes before the treasured gadget falls into my hands.
Smart natural gas meter
In the instruction manual we have the following information:
Thanks to the manufacturer – now we have everything to choose a suitable pulse counter.
I have been building a DIY smart home for several years now. Now I have this configuration:
Raspberry Pi 4 (4GB RAM) with Home Assistant OS on board;
Zig Star LAN as a coordinator for the Zigbee network;
About 90 Zigbee and 10 Wifi devices.
I have already implemented calculation of cold water consumption using a Zigbee pulse counter (Zigbee pulse counter – modkam.ru). Recently, this meter began to fall off the network, but the problem is not in the device itself, but in its location, but more on that later.
Having connected this pulse counter to a new gas meter, I (what a surprise!) did not receive adequate readings. The reason is that it reads, as the device developer answered me in the comments, ~1 pulse/sec. We have in the datasheet and on the device – 1 pulse = 0.000125 m3.
Simple math:
8000 pulses per cube;
2.73 m3/hour maximum gas flow of the boiler;
8000 x 2.73 / 3600 we get about 6 pulses per second.
Further search for a solution naturally led me to ESPHome. For hardware, the choice fell on the ESP32 DEVKIT V1.
The board already has everything you need, a MicroUSB power connector, Wifi, and protruding pins – you can “make up” anything on your knee without a soldering iron.
Having studied the documentation on the website for Pulse Counter Sensor (Pulse Counter Sensor – ESPHome) and tortured Chat GPT with the following configuration:
esphome:
name: gas-count
friendly_name: gas_count
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: ******
# Блок для ввода фактических значений показаний из интерфейса HA
actions:
- service: set_pulse_total_gas
variables:
new_pulse_total: float
then:
- lambda: |-
id(saved_total_gas_consumption) = new_total;
ESP_LOGD("custom", "Set total gas consumption to: %f", id(saved_total_gas_consumption));
ota:
- platform: esphome
password: *******
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Gas-Count Fallback Hotspot"
password: ********
captive_portal:
globals:
- id: saved_total_gas_consumption # Глобальная переменная для сохранения данных при перезагрузке устройства
type: float
restore_value: true
initial_value: '0.0'
sensor:
- platform: pulse_counter
pin: GPIO04
id: gas_meter_counter
name: "Gas Meter Pulse Count"
unit_of_measurement: "pulses"
accuracy_decimals: 1
filters:
- debounce: 10ms # Игнорировать сигналы, которые длятся менее 10 мс. По даташиту длительность импульса от 2 до 6 мс.
- multiply: 0.000125 # Применение коэффициента для пересчета импульсов в м³
- lambda: |-
id(saved_total_gas_consumption) += x;
return id(saved_total_gas_consumption);
# Выводим значения глобальной переменной в HA
- platform: template
name: "Saved Total Gas Consumption"
device_class: gas
lambda: |-
return id(saved_total_gas_consumption);
unit_of_measurement: "m³"
accuracy_decimals: 6
Constructive comments/remarks are absolutely welcome, since I am far from a programming person and will be glad to receive advice from the professional community.
According to the operating manual, the pulse output of the meter is an open collector. The meter was connected according to this scheme:
Connector for connecting a pulse counter – TRS 3.5 (mini jack)
After downloading the firmware to the ESP32, I received the following sensors in the HA interface:
And such beautiful pictures on the Energy panel in HA:
Smart water meter
Having gained positive experience, I decided to replace the Zigbee cold water pulse counter with an ESP32. Zigbee has a lot of advantages, but in my case, it was in the location of the water meter that something went wrong. I was unable to achieve stable operation of the device.
In addition to taking readings from the cold water meter at the entrance to the apartment, I also take readings from a specially installed meter in front of the reverse osmosis filter to correctly account for the resources of the membrane and other cartridges.
Code for ESPHome:
esphome:
name: water-count
friendly_name: water_count
esp32:
board: esp32dev
framework:
type: arduino
# Подключение к Wi-Fi сети
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Water-Count Fallback Hotspot"
password: *******
captive_portal:
# Enable Home Assistant API
api:
encryption:
key: *******
# Блок для ввода фактических значений показаний из интерфейса HA
services:
- service: set_water_total
variables:
new_total: float
then:
- lambda: |-
id(saved_total_water_consumption) = new_total;
ESP_LOGD("custom", "Set total water consumption to: %f", id(saved_total_water_consumption));
- service: set_filter_water_total
variables:
new_total: float
then:
- lambda: |-
id(saved_total_filter_water_consumption) = new_total;
ESP_LOGD("custom", "Set total filter water consumption to: %f", id(saved_total_filter_water_consumption));
ota:
- platform: esphome
password: *******
# Веб-сервер для диагностики
web_server:
port: 80
# Логирование
logger:
# Глобальные переменные для хранения количества литров
globals:
- id: saved_total_water_consumption
type: float
restore_value: True
initial_value: '0.0'
- id: saved_total_filter_water_consumption
type: float
restore_value: True
initial_value: '0.0'
# Настройка для счетчика воды
sensor:
- platform: pulse_counter
pin:
number: GPIO14 # Пин счетчика воды
mode:
input: true
pullup: true
id: water_meter_counter # ID счетчика воды
name: "Water Meter"
unit_of_measurement: "pulses"
accuracy_decimals: 1
filters:
- multiply: 10 # Применение коэффициента для пересчета импульсов в литры. 1 импульс - 10 литров
- lambda: |-
id(saved_total_water_consumption) += x;
return id(saved_total_water_consumption);
# Настройка для счетчика перед фильтром
- platform: pulse_counter
pin:
number: GPIO27 # Пин счетчика воды перед фильтром
mode:
input: true
pullup: true
id: filter_water_meter_counter # ID счетчика перед фильтром
name: "Filter Water Meter"
unit_of_measurement: "pulses"
accuracy_decimals: 1
filters:
# Для счетчика перед фильтром коэффициент не применяю, т.к. 1 импульс у него равен 1 литру.
- lambda: |-
id(saved_total_filter_water_consumption) += x;
return id(saved_total_filter_water_consumption);
# Выводим значения глобальных переменных в HA
- platform: template
name: "Saved Total Water Consumption"
device_class: water
lambda: |-
return id(saved_total_water_consumption);
unit_of_measurement: "L"
accuracy_decimals: 1
- platform: template
name: "Saved Total Filter Water Consumption"
device_class: water
lambda: |-
return id(saved_total_filter_water_consumption);
unit_of_measurement: "L"
accuracy_decimals: 1
The ESPHome documentation regarding connecting outputs from a reed switch says the following:
inverted: true I did not set it because I did not find clear information on the meters. I decided to leave it this way and, in case of incorrect readings, I would correct it. Not needed.
As a result, both sensors flew perfectly into HA and are displayed without problems in the Energy panel:
Well, accounting for the resource of a reverse osmosis filter looks like this:
When you click on the filter icon, a window pops up and you can reset the resource when replacing the cartridge:
I was pleased with the result. Now my house has become a little smarter, and on the 25th of every month I receive notifications in telegram with readings of all meters.