Template / formula for measured distance compared to current water level

Hi everybody,

I have two 1000l rain water tanks in my backyard. I finally got around to installing an ESPHome with HC-SR04 ultrasonic distance sensors (well, one for now, still testing).

I’d like to do two things:

  1. automatically convert the reading(s) (in meters) to how much water is left (in liters)
  2. run automations when water levels above/below certain points (I got this figured out already)

I got this data (water left in liters compared to reading in meters)

  • 960 - ~0.06
  • 900 - ~0.1
  • 850 - ~0.15
  • 800 - ~0.2
  • etc.

I took measurements in 50l steps (displayed on the outside of the tanks). There is about 0.05m / 5cm distance per 50l water level. Unfortunately, this is not an exact value, but then again, I don’t need to know the exact amount of water that’s in there. ~10l accuracy is fine.

Question

How can I convert the readings via Home Assistant and display the water level in liters? It might be due to doing this in the noon sun for way too long, but I cannot figure out the formula. I do know that 100l ~50l = ~0.05m. But is there a way to automatically return this value, instead of using an enormous if/else if statement via template_sensor?

I would now do something like

sensor:
  - platform: template
    sensors:
      left_tank:
        friendly_name: "Linke Tonne"
        unit_of_measurement: "Liters remaining"
        value_template: >
          {% if states("sensor.linke_tonne") <= 0.06 %}
            950
          {% elif states("sensor.linke_tonne") > 0.06 and <= 0.1 %}
            900
          {% elif states("sensor.linke_tonne") > 0.1 and <= 0.15 %}
            850
# etc. etc. 
          {% else %}
            ok
          {% endif %}

This template is not accurate (damn you, sun!!), but I hope you understand what I mean. If I figure out the actual template, it’d work. But it’d require me to create and elif for each 50l (or 0.05m) interval. Instead, I am sure there is some smart formula to mathematically use the sensor.linke_tonne value to convert it into the equal amount of water left. Obviously, the following is not it, but just as an example

sensor:
  - platform: template
    sensors:
      left_tank:
        friendly_name: "Linke Tonne"
        unit_of_measurement: "Liters remaining"
        value_template: >
          {% states("sensor.linke_tonne") | float / <something> * <something_else> | round(2) %}

Thank you for your help.

sensor:
  - platform: template
    sensors:
      left_tank:
        friendly_name: "Linke Tonne"
        unit_of_measurement: "Liters remaining"
        value_template: >
          {{ 1000 - (states("sensor.linke_tonne") | float * 1000) }}

That will report the current quantity to the litre. If you want it to the nearest 50l increment, use integer division to divide by 50 then multiply the result by 50.

        value_template: >
          {{ ((1000 - (states("sensor.linke_tonne") | float * 1000)) // 50) * 50 }}

EDIT
Correction. Changed 100 to 1000.

1 Like

Think you’re equation is wrong, off by a factor of 10 based on his values.

value_template: >
  {{ -1000 * states('sensor.linke_tonne') | float + 1000 }}

0.1 returns 900
0.2 returns 800

etc

2 Likes

Right you are and, oddly enough, my calculator app still shows the 1000 I had used during testing yet somehow I wrote 100 in the template! Another one of those “should have answered after breakfast”.

Thank you both. This works perfectly. I’ll go with the exact-ish value, but will keep in mind the other formula was well.