Using ESPhome to build a water flow rate meter

It’a a value that you choose. update_interval is decided upon your requirements about how often you want that value to be updated. If you create an automation where a flow ON/OFF value is important to trigger something else, then you want that interval to update faster.

I have dug deeper in how to model the water flow sensor YF-B10. The Flow pulse Characteristics for YF-B10 is F=6xQ-8, where F is pulses/sec and Q is water flow in liter/min. Rewriting the formula gives the water flow by Q=(F+8)/6. The formula will deliver non-zero Q even when F is zero. This doesn´t make sense since there cannot be any pulses from the sensor when the actual flow is zero.

image

This problem has been addressed by other members in the forum, but I haven’t seen any solution. (Maybe I have missed some contributions on the forum.)

My first approach was to plug in the formula in “lambda function” under “pulse_counter”. The result was of course a non-zero measured flow even when the actual flow was zero.
After a number of different approaches, I just added a correction term to the formula resulting in the new formula:
Q=(F+8)/6 – 8/(6+F*100)
The new formula gives Q=0 when F=0, which is good. The contribution from the correction term fades out fast with increasing F (increasing water flow), so it won´t in practice affect the result adversely.

My Yaml-code for the pulse_counter initially looked like this:
image

So, how does it work?
Well, I have made several measurements for different actual flow levels (low, medium, high).
For each of the measurements I kept the flow constant, noted the time and the measured flow (liter/min). Afterwards I measured the actual volume of water manually, and calculated the actual water flow based on actual volume and time.

I found a good correlation between the measured values, but significant deviation from the values calculated by the formula in the data specification for the sensor.

Hence, the formula gives to low values for low values of Q and to high values for high values of Q. See illustrations:
image
image
image

Next step was to change settings of the parameters in the formula to match the real values.
The new formula expressed in a more general form, indicating three parameters:

      Q=(F-constant) / factor    -   constant / (factor + F*correction)

I managed to match the output from sensor to actual values and came up with following set of numbers:
Factor: 9,3 (spec: 6)
Constant: 28 (spec: 8)
Correction: 100
Resulting in new lambda:

- lambda: return ((x/60.0+28.0)/9.3-28.0/(9.3+100.0*x/60));

I have implemented the new settings and it works well.
I have no explanation why the Factor and especially the Constant had to be changed so much away from the specified values. The only guess I have is that it relates to the mechanical design of the turbine in the sensor. Maybe the quality is low and there are significant differences between individual sensors. I do not suspect the problem is in the ESP32 nor the pulse_counter.

Pulses/liter
Another observation is that the number of pulses per liter varies a lot depending on the intensity of water flow (liter/min). The illustration is derived from the formula and field test.

In view of the “Pulse/liter vs Q characteristics”, the update interval of the pulse_counter should be short enough to allow for a constant water flow during the interval.
image

For normal use of water, the water flow may vary a lot during a minute. That means that the update interval for the pulse_counter should be shorte than that. I have used 1 second so far. Maybe that could be increased somewhat.

4 Likes

Hi, I tried the code but it doesn’t seem to work.
I can give you more information, in about 35 seconds 1 liter of water comes out.
I’m interested in knowing how many liters of water I consume.
This is the code used

- platform: pulse_counter
  state_class: measurement
  name: "log Acqua litri/min"
  id: waterlmin
  pin: D4
  update_interval: 5s
  filters:
    - lambda: return (x / (5.0 * 38));
  unit_of_measurement: "l/min"

- platform: integration
  device_class: water
  state_class: total_increasing
  name: Water m³"
  id: waterm3
  unit_of_measurement: "m³"
  accuracy_decimals: 7
  sensor: waterlmin
  time_unit: min
  icon: "mdi:water"
  filters:
    - lambda: return (x / 1000);

- platform: integration
  state_class: total_increasing
  name: "Water in litres"
  unit_of_measurement: 'L'
  accuracy_decimals: 2
  sensor: waterlmin
  time_unit: min
  icon: "mdi:water"

Let’s adjust the lambda for the pulse counter sensor based on this information.

  1. For the pulse_counter sensor: Given 65.13 pulses represent 1.714 liters/minute, 1 pulse represents 1.714 liters/minute / 65.13

Hence, the lambda can be adjusted as follows:

- platform: pulse_counter
  state_class: measurement
  name: "log Acqua litri/min"
  id: waterlmin
  pin: D4
  update_interval: 5s
  filters:
    - lambda: return (x / 65.13) * 1.714; 
  unit_of_measurement: "l/min"
  1. For the integration sensors: The purpose of the integration sensors is to integrate the flow rate over time to get the total volume. Your approach looks correct here, but I’ll verify the lambdas:

For the “Water m³” sensor, you’re dividing by 1000 to convert liters to cubic meters. This is correct.

For the “Water in litres” sensor, you’re directly integrating the liters/minute to get the total liters. This is also correct.

Given the above adjustments, the rest of your configuration should work as expected. If you still encounter issues, please double-check the wiring and the pin configuration (D4) to ensure there are no hardware issues.

Grazie ancora per il supporto.

Adesso il sensore sembra essere più stabile, ho inserito il codice suggerito ed ho avuto questi valori:

Test
1 Litro in 36 secondi

‘log Acqua litri/min’: Sending state 31.57992 l/min with 2 decimals of accuracy

‘flow rate Acqua in litri’: Sending state 58.76422 L with 2 decimals of accuracy

Non ho capito come hai calcolato impulsi al minuto
image

From the data provided:

1 liter of water flows in 36 seconds.
This means the flow rate is 1 liter / 36 seconds = 1.6667 liters/minute

Now, given the sensor’s formula F = 38 x Q (where Q is the flow rate in liters per minute), when 1.6667 liters of water flow per minute, the sensor should generate 38 ×1.6667 pulses, which are approximately 63.33 pulses.

Now, in your test, you received a reading of 31.58 liters/minute for an actual flow rate of 1.6667 liters/minute. This suggests the correct scaling factor is 31.58 / 1.6667 = 18.93

Using this information, we can recalibrate the pulse_counter sensor as follows:

For the pulse_counter sensor:
Given that 63.33 pulses represent 1.6667 liters/minute, 1 pulse represents 1.6667 L/min / 63.33

Therefore, the lambda can be adjusted as follows:

- platform: pulse_counter
  state_class: measurement
  name: "log Acqua litri/min"
  id: waterlmin
  pin: D4
  update_interval: 5s
  filters:
    - lambda: return (x / 63.33) * 1.6667; 
  unit_of_measurement: "l/min"

Please input this code and test the sensor again. I hope the results will be more accurate this time around. Let us know if this help!


Furthermore, your flow rate Acqua in litri value should be named Volume totale dell’acqua in litri. This value is the sum of all you water used through time.

Same for flow rate Acqua in m3, it should be named Volume totale dell’acqua in m³

Thank you for sharing your code/setup.

Really appreciate it - will try it soon.

Hi, sorry for the late reply but I only managed to try today. Now the formula is clear to me but it still doesn’t work… Searching on the web I found the solution using this guide https://indomus.it/progetti/contabilizzare-i-consumi-dacqua-e-rilevare-perdite-con-la-domotica-home-assistant-via-flussostato-ed-esphome/
using a manual calibration!!!

In reality, even the raw data that it gave me back when I went to put it in the lambda sensor were not entirely correct, resulting in lower consumption than the real one.

So I thought about lowering the value and adjusting it until I got the correct consumption (lambda: return (x / 2000.00000).

I don’t know why the formula you suggested didn’t work, maybe the information on the sensor card wasn’t correct.

Anyway thanks for the support.

If it’s not a problem, I wanted to ask you two more questions
1- Do you think it works even on a stream of sparkling water?
2- How can I create a sensor that then eliminates my water consumption?

I have tried using a water flow sensor type: YF-S401, working range 0.3-6 L/min,Allowing pressure: pressure 1.75Mpa,Load capacity: 10 mA (DC 5V),Working voltage range: DC 5~18 v,Maximum operating current: 15 mA (DC 5V),The lowest rated working voltage: DC4.5 5V-24V,Size : 6.5cmX4cm/2.55’‘X1.57’’ ,but I encountered problems, this sensor cannot detect flow. I tried installing it on a water dispenser, to measure the rate of drinking water use. Is there a forum member who uses the YF-S401 sensor, please help. Thank you

a water flow sensor type: YF-S401, working range 0.3-6 L/min,Allowing pressure: pressure 1.75Mpa,Load capacity: 10 mA (DC 5V),Working voltage range: DC 5~18 v,Maximum operating current: 15 mA (DC 5V),The lowest rated working voltage: DC4.5 5V-24V,Size : 6.5cmX4cm/2.55’‘X1.57’’ ,but I encountered problems, this sensor cannot detect flow. I tried installing it on a water dispenser, to measure the rate of drinking water use.The amount of water in liters does not appear, here is the screenshot’
``
[18:37:33][D][sensor:093]: ‘Temperatur Tangki Dispenser’: Sending state nan °C with 1 decimals of accuracy
[18:37:33][D][pulse_counter:174]: ‘Débit d’eau instantané’: Retrieved counter: 0.00 pulses/min
[18:37:33][D][sensor:093]: ‘Débit d’eau instantané’: Sending state 0.00000 L/min with 2 decimals of accuracy
[18:37:38][D][pulse_counter:174]: ‘Débit d’eau instantané’: Retrieved counter: 0.00 pulses/min
[18:37:38][D][sensor:093]: ‘Débit d’eau instantané’: Sending state 0.00000 L/min with 2 decimals of accuracy
[18:37:43][D][pulse_counter:174]: ‘Débit d’eau instantané’: Retrieved counter: 0.00 pulses/min
[18:37:43][D][sensor:093]: ‘Débit d’eau instantané’: Sending state 0.00000 L/min with 2 decimals of accuracy
[18:37:48][D][pulse_counter:174]: ‘Débit d’eau instantané’: Retrieved counter: 0.00 pulses/min
[18:37:48][D][sensor:093]: ‘Débit d’eau instantané’: Sending state 0.00000 L/min with 2 decimals of accuracy
[18:37:53][D][pulse_counter:174]: ‘Débit d’eau instantané’: Retrieved counter: 0.00 pulses/min
[18:37:53][D][sensor:093]: ‘Débit d’eau instantané’: Sending state 0.00000 L/min with 2 decimals of accuracy
[18:37:58][D][pulse_counter:174]: ‘Débit d’eau instantané’: Retrieved counter: 0.00 pulses/min.

any suggestions to solve this problem. thank you

Hello @phendrank,

Based on your description and the information provided, there are a few things to consider:

  1. Ensure the sensor is powered correctly: The YF-S401 needs to be powered with a voltage within its working range. Given that the working voltage range is DC 5~18 V, you should ensure that the sensor is receiving a stable 5V from the ESP32 board if that’s what’s being used as the power source. ESP32 boards have a 5V DC output power pin.
  2. Correct the GPIO pin if necessary: Your ESPHome configuration specifies number: 4 for the pin, which corresponds to GPIO4 on the ESP32. Please make sure this is indeed the physical pin where the sensor’s signal wire (yellow) is connected.
  3. Pulse rate adjustment: According to the sensor’s datasheet, the pulse frequency per L/min is 98Hz. This means the conversion factor in the lambda filter should reflect this pulse rate to accurately calculate the flow rate.

Here’s an adjusted version of the user’s ESPHome configuration, incorporating the information from the datasheet and correcting the lambda function for conversion:

sensor:
  - platform: pulse_counter
    pin:
      number: GPIO4
      mode: INPUT_PULLUP
    unit_of_measurement: 'L/min'
    name: "Débit d'eau instantané"
    id: water_usage
    update_interval: 5s
    accuracy_decimals: 2
    filters:
      - lambda: return x / 98.0; # Adjusted to the pulse rate from the datasheet

The lambda filter now takes the count of pulses per minute (x) and divides it by 98 to convert it to liters per minute, which is the specification provided by the sensor’s datasheet.

Additional Considerations:

  • Check the sensor installation: Flow sensors are typically sensitive to orientation and flow direction; make sure that the sensor is installed correctly according to the arrow marked on the sensor body indicating the flow direction.
  • Inspect the water flow: If the water flow is too low (below the sensor’s minimum specification of 0.3 L/min), the sensor might not register any pulses.
  • Wiring Check: Double-check the wiring, especially the signal wire, to ensure a good connection to the specified GPIO pin on the ESP32.
  • Debugging: If the above configuration still does not yield results, you may want to add some logging to the ESPHome configuration to ensure that pulses are being read by the ESP32. They could also check the signal from the sensor with an oscilloscope or a multimeter capable of reading frequency to ensure it’s operating correctly.

Good luck with you project

2 Likes

Very interesting project.

It was very easy to follow all the discussions and instructions to create a water flow rate meter for my kitchen.

What I do not understand is if the esp continuous to count the flow, even if the reporting is for example set to 5 sec or 30 sec etc.

I am using a water filter that I need to change every X LT of water. So I want to use the sensor to capture all water flowing through my filter and warn me when I am close to the X LT, in order to change it.

Any experience you can share for the above use case?
Also is the refresh (update intervals) we setup on the sensor side in ESPhome, the frequency that the sensor will be updated in HA?

thanks in advance

Yiannis

Hello @John_Kotrolos,

The ESPHome pulse counter sensor component is designed to count pulses continuously, regardless of the reporting interval (the update_interval setting). The update_interval simply determines how often the ESPHome device reports the counted pulses to Home Assistant, not how often it counts. Here’s how it works:

  1. Continuous Counting: The pulse counter in ESPHome will continuously monitor the pulses from the flow sensor. It does not stop counting between the updates that it sends to Home Assistant.
  2. Reporting Interval: When you set an update_interval of, say, 5 seconds, the ESPHome device will sum up all the pulses it has counted in that 5-second period and then send that number to Home Assistant.
  3. Accumulation: For your use case of tracking the total volume of water to determine when to change the filter, you would typically use an integration sensor in ESPHome that takes the flow rate and integrates it over time to calculate the total volume.
  4. Home Assistant Update: The update_interval in ESPHome corresponds to how often the sensor data is sent to Home Assistant. If you set it to 5 seconds, then Home Assistant’s entity state will refresh every 5 seconds with the latest data from the sensor.

For your specific use case, here’s what I would recommend:

  • Use an Integration Sensor: In ESPHome, define an integration sensor that uses the data from the pulse counter to calculate the total volume of water that has passed through the sensor.
  • Total Volume: You can maintain a running total of the volume of water that has passed through the filter. This would involve storing the accumulated volume in a variable that persists across reboots, which can be done using ESPHome’s Globals or by saving the state to flash.
  • Alerts: Set up an automation in Home Assistant that triggers an alert when the total volume reaches a certain threshold, indicating that it’s time to change the water filter.

Here’s a basic example of how you might define such a sensor in ESPHome:

sensor:
  - platform: pulse_counter
    pin: GPIO4
    unit_of_measurement: 'L/min'
    name: "Débit d'eau instantané"
    id: water_usage
    update_interval: 5s
    accuracy_decimals: 2
    filters:
      - lambda: return x / 98.0;

  - platform: total_daily_energy
    name: "Total Water Usage"
    power_id: water_usage
    unit_of_measurement: 'L'
    accuracy_decimals: 2

Note: The total_daily_energy sensor is typically used for energy measurement, but it can be repurposed for any kind of cumulative measurement like total water usage. You might need to adapt this to your specific requirements or use a different sensor type that’s more appropriate for water flow integration.

Remember to replace power_id with the correct ID if you’re not measuring power. This is just an example, and ESPHome might have different ways to handle cumulative totals for non-energy sensors.

In conclusion, the ESPHome setup you design should be able to handle the continuous tracking of water flow and integrate over time to calculate the total volume, independent of the reporting interval to Home Assistant.

Hi everyone,
Whenever I reset the esp8266 di mini, all the values ​​are set to 0.
Is there a solution for this?

sensor:

  - platform: pulse_counter
    name: "Wasserverbrauch/Min."  
    pin: GPIO2  
    update_interval: 5s  
    accuracy_decimals: 2  
    id: water_usage  
    unit_of_measurement: 'L/min' 
    filters:  
      - lambda: return (x / 690); 
  
  
  - platform: integration 
    name: "Wasserverbrauch m³"    
    unit_of_measurement: 'm³'   
    accuracy_decimals: 2  
    sensor: water_usage   
    device_class: water  
    state_class: total_increasing    
    time_unit: min   
    filters:    
      - lambda: return (x / 1000);
  
  
  
  - platform: total_daily_energy  
    name: "Wasserverbrauch total"   
    power_id: water_usage   
    unit_of_measurement: 'L'   
    accuracy_decimals: 2 
    device_class: water   
    state_class: total_increasing


image

This is where you need to setup your utility meter in configuration.yaml

utility_meter:
  consommation_main_hourly:
    source: sensor.utilisation_d_eau_total
    cycle: hourly
  consommation_main_daily:
    source: sensor.utilisation_d_eau_total
    cycle: daily
  consommation_main_weekly:
    source: sensor.utilisation_d_eau_total
    cycle: weekly
  consommation_main_monthly:
    source: sensor.utilisation_d_eau_total
    cycle: monthly
  consommation_main_yearly:
    source: sensor.utilisation_d_eau_total
    cycle: yearly

And then you can benefit from long-term data storage for these values.

1 Like

Thank you! I didn’t consider the utility meter for my water system, but it is perfect. You saved me sooooo much time. Merci!

1 Like

after latest esphome update this conf is not working anymore, state is always 0 (and i have 3 this sensors, none of them isnt working)

  - platform: pulse_counter
    pin: 32
    name: "Vesi 1. korrus_kook"
    id: vesi_1_korrus_kook
    update_interval: 5s
    filters:
    - lambda: return (x / 660.0);  # 660 = 11 * 60 sec
    unit_of_measurement: "L/sec"
    total:
      name: "Total Vesi 1. korrus_kook"
      unit_of_measurement: "L"
      accuracy_decimals: 3
      filters:
        - lambda: return (x / 660.0);  

help?

It’s a temporary glitch related to the latest ESPHome update. I’ve seen this problem not only with platform: pulse_counter but also with platform: dht and others too. This is not surprising that they pushed 2-3 updates close from each other, there is an ongoing issue but I managed to find a solution that worked for me.

  1. Note your API Encryption key and IP Address in logs:
    Capture d’écran, le 2023-12-23 à 09.15.17
    Capture d’écran, le 2023-12-23 à 09.17.07

  2. Delete the integration for the duplicated ESP-Node
    Capture d’écran, le 2023-12-23 à 09.13.02

Capture d’écran, le 2023-12-23 à 09.13.19
Capture d’écran, le 2023-12-23 à 09.13.26

  1. Manually add your ESPHome node
    Capture d’écran, le 2023-12-23 à 09.13.43

  2. Let Home Assistant add it after it rediscovers your node (optionnally)
    If you are not on a rush, juste give HA some time and the node will be discovered and you can add it by a single click.

im downgraded to 11.6 and working again.

Hey mate, thanks for this post it’s highly informative.
I aspire to have an off grid setup with a dam one day. I’m starting a nursary, esphome is so awesome. Thank you