I built a “smart” water meter with ESPHome and Home Assistant, based on the project by Pieter Brinkman.
Hardware
The project uses a 5V LJ18A3-8Z/BX Proximity sensor from AliExpress. Since I already had some ESP32 boards, that’s what I used.
The ESP32 runs on 3.3 Volt. The sensor needs 5 Volts, so in theory a level shifter is required. Even though the Espressif CEO claims that the chip is 5V tolerant, I still added a protection circuit to the proximity sensor, limiting the input voltage to safe values.
Test-installation
For testing, I mounted the components on a breadboard:
And 3D-printed a sensor mount:
Software
The ESPHome configuration YAML looks like this:
substitutions:
devicename: "esp32-watermeter"
long_devicename: "Smart Watermeter"
pcb_version: "2023-02-11"
esphome:
name: "${devicename}"
name_add_mac_suffix: false ## if 'false' use different names/hostnames for each device!
comment: "${long_devicename} ${pcb_version}"
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
# Set pulse counter total from home assistant using this service call:
api:
services:
- service: set_pulse_total
variables:
new_pulse_total: int
then:
- pulse_counter.set_total_pulses:
id: water_consumption
value: !lambda 'return new_pulse_total;'
ota:
wifi:
ssid: !secret esphome_wifi_iot_ssid
password: !secret esphome_wifi_iot_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "${long_devicename} hotspot"
password: !secret watermeter_ap_password
captive_portal:
# Water flow meter using LJ18A3-8-Z/BX sensor (5V, 8mm distance)
# Generic sensor config:
# https://esphome.io/components/sensor/index.html#config-sensor
# Pulse counter config:
# https://esphome.io/components/sensor/pulse_counter.html
# Example project:
# https://www.pieterbrinkman.com/2022/02/02/build-a-cheap-water-usage-sensor-using-esphome-home-assistant-and-a-proximity-sensor/
#
sensor:
# Uptime in seconds
- platform: uptime
name: "${long_devicename} uptime"
id: uptime_seconds
update_interval: 10s
# Pulse COUNTER reports water usage in absolute liters
- platform: pulse_counter
pin:
number: GPIO34
inverted: true # Active LOW input, does not really matter since we're counting pulses
mode:
input: true
id: water_consumption
name: "Water consumption"
unit_of_measurement: 'liter'
device_class: water
state_class: total_increasing
#last_reset: None
#
icon: "mdi:water"
update_interval: 6s
#
total:
id: water_consumption_total
name: "Water consumption total"
unit_of_measurement: "m³"
icon: "mdi:water"
#
accuracy_decimals: 3
device_class: water
state_class: total_increasing
#last_reset: None
filters:
- multiply: 0.001
Software backlog
- The water meter does not yet integrate nicely with the Energy Dashboard in HomeAssistant. Probably needs a specific data format / unit to be added.
- Total water consumption resets to zero when rebooting the board - this leads to hilarious water consumption rates, for example 800.000 liters in one minute. I assumed that “total_increasing” would detect and solve this.
- Initially I enabled the “Bluetooth Proxy” functionality on the water meter, but I encountered frequent reboots so I disabled it for now. That seems to have helped, not sure what causes this.