2021 HAss-H2O-PSense

This is my progress on the Water Meter pulse sensor for the HomeAssistant using EspHome.

Project goals:

    • a compact click-on unit

    • powered by a single mini usb plug

    • connects to HAss via WiFi

    • supports OTA updates

    • has THD sensor

    • displays data locally on a small Screen

    • camera snaphots of physical counter (optional)

Proof of Concept

Initial setup

For the POC I am using what I have on hand:


  • 64x48 I2C OLED Screen

  • DHT11 temperature and humidity sensor

  • USB PhoneCharger as power source

A font that is readable on the tiny screen but small and narrow was hard to find.
I settled on "David Device" that can be downloaded from dafont.com.

For testing purposes I am using a simple momentary switch with a 10k pullup resistor to simulate pulses from a sensor.

The values are somewhat off. I think the DHT11 is not that healthy anymore and the pusle multiplier needs tweaking.

EspHome Yaml File

substitutions: # Modify variables based on your settings hostname: 'esp32cam1' ssid: '<wifi network name>' password: '<wifi password>'esphome: name: $hostname platform: ESP32 board: esp32devwifi: ssid: $ssid password: $password fast_connect: Trueapi: reboot_timeout: 0s password: "<otapassword>"ota: password: "<otapassword>"web_server: port: 80 auth: username: admin password: <web server password>logger:text_sensor: - platform: wifi_info ip_address: name: Adress_IP id: ipaddress mac_address: name: ESP Mac Wifi Address id: macaddressfont: - file: "David Device.ttf" id: my_font size: 8# OLED SCREENi2c: sda: 13 scl: 16display: - platform: ssd1306_i2c model: "SSD1306 64x48" reset_pin: 0 lambda: |- it.print(0, 0, id(my_font), "HASS-H2O-PSense"); it.line(0, 9, 63, 9); it.printf(0, 13, id(my_font), "W: %.1f lmin", id(water_usage).state); it.printf(0, 22, id(my_font), "T:%.1f°C H:%.1f%%", id(temp).state, id(hum).state); it.printf(0, 31, id(my_font), "%s %.0fdB", id(ipaddress).state.c_str(), id(wifipower).state ); it.printf(0, 40, id(my_font), "%s", id(macaddress).state.c_str());# DHT11 sensor on GPIO14# WATERMETER PULSE SENSOR# WIFI STRENGTHsensor: - platform: dht model: DHT11 pin: GPIO14 temperature: name: "esp32cam1temp" id: temp humidity: name: "esp32cam12Hum" id: hum update_interval: 5s - platform: pulse_counter pin: GPIO15 name: waterverbruik_in_liters id: water_usage update_interval: 5s unit_of_measurement: 'L' filters: - multiply: 0.17 - platform: wifi_signal name: "WiFi Signal Sensor" update_interval: 5s id: wifipower

Adding a proximity sensor

The sensor I want to use is still being shipped at this time, so I will be testing with the sensor from my earlier pulse counter.
It is a RIKO SN04-N NPN NO inductive sensor.
The operating voltage is 10-30VDC and I'm using a 1.5A 12VDC power supply.
The mounting plate for my Itron water meter was found on Thingiverse.
I will try using the same optocoupler circuit as in my previous water meter as well.

Cyan wire goes to data pin.
5V on the left is the MCU power supply of the Arduino... this needs to connect to the
3.3V of the ESP32

Final Circuit

Seems to be working fine.

Measurement is probably off, but this can be callibrated later in ESPHome and updated OTA.

I updated the WiFi settings with multiple SSIDs and removed the "fast-connect" line so the ESP connects to the nearest access point:

wifi: networks: - ssid: <home ssid> password: $password - ssid: <utilites closet ssid> password: $password

Also added ssid to my text_sensor ...

text_sensor: - platform: wifi_info ip_address: name: Adress_IP id: ipaddress mac_address: name: ESP Mac Wifi Address id: macaddress ssid: name: ESP Connected SSID id: conn_ssid

... and changed the display lambda so the SSID of the AP is shown on the screen:

it.printf(0, 40, id(my_font), "%s", id(conn_ssid).state.c_str());

After that I installed the sensor on the water meter and fired it up ...

Forward a few weeks ... parts came in:

  • 128x64 oled screen

  • LB18A3-8-Z/BX-5V proximity sensor

The POC has been working great in the mean time, but now i can get rid of the additional 12v power supply and the optocoupler. The new sensor is powered by 5V and only needs an 1k restor on the output line (black wire) to bring the voltage down on the digital input pin of the ESP32.

The new oled screen allows more data to be shown and it was delivered in just in time ... i broke the little one :(

A new sensor holder

The new holder is based on the original one used for the SN-04 sensor.

I've opted for tie-wrap attachment to keep it as light as possible and avoid using the nuts that come with the sensor. It is plenty strong, the sensor does not move and the dials are still visible.

The screw hole has been edited so the plate can actually be screwed in place with a M4x10 sunken screw.

The files are on thingiverse: https://www.thingiverse.com/thing:4843391

Rethinking the housing

I thought I would want a small housing that holds everything and clips on to the water meter.
As the sensor holder design suggests I went in antoher direction. I did not want everything to be down near the floor where it could easily be damaged. Also I would like the ability to add features at a later point. I've opted for a Sonoff IP66 Waterproof Case (https://www.itead.cc/smart-home/sonoff-ip66.html) that I can hang on the wall.

Finalizing the ESP MCU

Fist thing to do is to swap out the ESP32-CAM module for the final Wemos D1 M1n1 and test the setup.
Everything is now powered from a single USB phone charger via the mini USB plug on the D1Mini.

The components were transfered one by one to a proto board and tested. The whole thing was mounted in the case, connected and screwed to the wall.

ESP-Home setup

This is the final esphome YAML file (it will probably need tweaking) :

esphome: name: hass_h2o_psense platform: ESP8266 board: d1_mini
wifi: networks: - ssid: "DomacinskaMreza_Privatno" password: !secret wifi_primary_pass - ssid: "Gajes-Utilities" password: !secret wifi_utilites_passapi: reboot_timeout: 0s password: !secret esphome_ota_pass
ota: password: !secret esphome_ota_pass
web_server: port: 80 auth: username: admin password: !secret esphome_ota_pass
text_sensor: - platform: wifi_info ip_address: name: psense_ip id: ipaddress mac_address: name: psense_mac id: macaddress ssid: name: psense_ssid id: conn_ssid font: - file: "David Device.ttf" id: my_font size: 8
# OLED SCREENi2c: sda: D1 scl: D2
display: - platform: ssd1306_i2c model: "SSD1306 128x64" reset_pin: D0 lambda: |- it.print(0, 0, id(my_font), "HomeAssistant - H2O PSense V1.0"); it.line(0, 9, 127, 9); it.line(0, 11, 127, 11); it.printf(0, 15, id(my_font), "Water Usage: %.1f lmin", id(water_usage).state); it.printf(0, 25, id(my_font), "Temp: %.1f°C RelHum:%.1f%%", id(temp).state, id(hum).state); it.printf(0, 35, id(my_font), "IP: %s Pow: %.0fdB", id(ipaddress).state.c_str(), id(wifipower).state); it.printf(0, 45, id(my_font), "SSID: %s", id(conn_ssid).state.c_str());
# DHT11 sensor on d5# WATERMETER PULSE SENSOR d3# WIFI STRENGTHsensor: - platform: dht model: DHT11 pin: D5 temperature: name: "psense_temp" id: temp humidity: name: "psense_hum" id: hum update_interval: 60s - platform: pulse_counter pin: D4 name: psense_water id: water_usage update_interval: 60s unit_of_measurement: 'L' filters: - multiply: 1 # 0.17 - platform: wifi_signal name: "psense_wifi" update_interval: 60s id: wifipower

I've also added the following to the configuration.yaml :

utility_meter: waterverbruik_kwartier: source: sensor.psense_water cycle: quarter-hourly waterverbruik_uur: source: sensor.psense_water cycle: hourly waterverbruik_dag: source: sensor.psense_water cycle: daily waterverbruik_week: source: sensor.psense_water cycle: weekly

.... IT WORKS !


A few things to consider:

  • OTA updates will only work if the D1 Mini (ESP8266) is connected to a pure 2.4GHz WiFi network. 5GHz will not work and dual band will break the pipe during upload. This is not a problem if you are using a ESP32 module with 5GHz support, like the ESP32-CAM for example.

  • The tempreture/humidity sensor is not there for environment monitoring, since it is in a waterproof case. It can be used to trigger an alarm if humidty gets in the enclosure or something starts overheating.

  • The little plastic bit above the screw hole on the water meter is meant to be broken off.

  • If your water meter is far away from your WiFi router consider getting a D1 mini with an external antenna

Possible improvements:

  • it could be handy to route the reset/programming switch to the case. If OTA fails for some reason, you could just hold the button down and plug the USB cable in your laptop to flash the unit on the spot.

  • i noticed once that when powering on the D1Mini it kept getting stuck on boot with the status led glowing continously. I suspect that the sensor being engaged was the problem, since it booted fine after i let some water out so the sensor led turned off. If this proves to be a problem, I might need to add a small relay, so i can power on the sensor after the boot.

Parts List

  • Wemos D1 Mini ( Pro / with external antenna )

  • LB18A3-8-Z/BX-5V inductive proximity sensor

  • 128X64 I2C SSD1306 OLED Display Module

  • DH11 temperature/humidity sensor

  • KF301-3P 5.08mm Screw Connector

  • Resistor 4.7kΩ ( DHT11 pull-up )

  • Resistor 10kΩ ( proximity sensor pull-down )

  • Resistor 1kΩ-2kΩ ( proximity sensor voltage drop)

  • Female headers ( 2x8pin, 1x4-pin )

  • Prototype PCB (5x7cm, 2.54mm hole pitch)

  • Mini USB charging/data cable

  • USB power supply ( phone charger )

  • Sonoff IP66 Waterproof Case

  • 20mm PCB standoffs and screws

  • misc prototyping wire