Water Tank Level and Water Volume with ESPHome

Tags: #<Tag:0x00007f326b66b6e8> #<Tag:0x00007f326b66b4e0> #<Tag:0x00007f326b66b300>

Hello every one

Sooo Finally I’ve got time to figure this one out.

Not really that hard but never find a really clear and direct solution for it it was only a matter of find the right equation.
Main goal of this is to track the water tank level in my house as some times the water is being cut off and the water pump auto stopes working and it had to restarted. this way I can setup an Automation when the water level drops less then 50% the pump will be switched off for 10 seconds and started again so it can pump water to the main tank on the roof again.
So…
I used an ESP8266-01 and water proof ultrasonic sensor
image image
I tried to use this ultrasonic sensor but it was not detecting any distance far more than 50cm
image

any way my connections
Trig >> GPIO1
Echo >> GPIO3

  - platform: ultrasonic
    trigger_pin: GPIO1
    echo_pin: GPIO3
    name: "Water Tank Level"
    unit_of_measurement: "%"
    accuracy_decimals: 0
    update_interval: 30m
    filters:
      - lambda: return ((((x*100)-20)-(123-20))/(123-20))*-100;
      - filter_out: nan
      
  - platform: ultrasonic
    trigger_pin: GPIO1
    echo_pin: GPIO3
    update_interval: 30m
    name: "Water Tank Volume"
    unit_of_measurement: "l"
    accuracy_decimals: 0
    filters:
      - lambda: return ((((x*100)-20)-(123-20))/(123-20))*-1000;
      - filter_out: nan

and here is the breakout of the equation I used that I have to include for my case
Tank Depth = TD al the way from the cover where the sensor is mounted to the bottom
Sensor Value = x this is will stay the same as this is the reading from the sensor
Excluded Distance = EX which is the distance I have on top from the sensor which is mounted to the cover to the highest level the water can reach

     return ((((x*100)-EX)-(TD-EX))/(TD-EX))*-100

the same for the Water Tank Equation but you have the Tank Capacity in Liters = TC as for mine I have a 1000 Liters tank.

     return ((((x*100)-EX)-(TD-EX))/(TD-EX))*-TC

Hope this I’ll help not sure if this is the perfect way to do it but it server my purpose perfectly
what I’m going to add to it later if I can get a water temperature sensor it might be useful in some way.

Regards.

12 Likes

Thanks for sharing this.
Would you also share exact types of sensors you tried/use?
How do you mount it inside the water tank?

well I just finished the prototype as you see in the photo will be installing it later
but what I have in mind is to drill a hole to fit the ultrasonic sensor in the tank cover and will have the rest of the components sit in some where shade I’ll try to get a water proof outdoor box to fit every thing in only wires will be one fro the sensor and another to power it.

powering it will need a bit of work one of two options using a usb phone charger to power the sensor 5v and a step-down to power the esp 3.3v or to build it all on a single board and power it directly from the mains power.

any way as soon as I get any progress with this will post everything here.

Here is a link for the sensor I used

best thing about this sensor is you have potentiometer that can increase the distance and also have a long cable to so it can be separated from the other components.

the other sensor I used is just the normal prototyping ultrasonic which was failing to detect any distance after 60 cm.

Thanks for sharing, I definitely am going to try this.

Is it possible the schema is wrong?
Your lines are going to GPIO2 and GPIO7, but in the code you use GPIO1 and GPIO3.

No it’s right this is PIN number in schematic not GPIO in ESP-01 TX is GPIO1 and RX is GPIO03

This sensor must be higher than 20cm.

Omar
I will be following with interest. I have had this project sitting on my tinker list for some time. In relation to powering it. I was looking to have the unit not continually running. I want my esp01 to go into deep sleep. Wake up every day for 5 minutes. Provide a measurement - which will be sent via mqtt back to my hassio.
Then when I am confident that measurements are accurate I will be attempting to have an automation trigger my electric pump. I.E if water level gets to 40% and sun is up (solar power bonus) then turn on the pump for a set time. I already know my feed rate on the pump so I can predict how long to run to raise level by certain percentage.
To power the measuring device - which will be located about 70 metres from the house I was thinking of a 12v battery topped up by small solar charger. If I can limit the amount of power used by having the unit only switch on for 5 minutes each day then the battery should last for years.
BUT - i’m no electronics guru so will be looking for help on all this.
Patrick

Oh, I thought you are already using it for some time and now just found time to share it :slight_smile:

In case you didn’t install it, I would probably recommend using some other ESP board capable of using 5V (like D1 Mini), so you need just one power source in that box on the roof.

I was mainly asking because I have two water tanks. In one of them I have expensive ultrasound sensor from Loxone and even that one have issues with false reflections.
I found placement is a key. So I was interested how you placed yours and how reliable it is.

Did you notice, that minimum measuring distance is 55 cm ? That can be limiting in smaller tanks.

Is it possible to extend the length of this cable to 6m?

not a good idea. I tried and the reading is all over the place. shielded cable might work but haven’t tried it :thinking:
I work around it by extending the connection from the nodemcu to the sr04t with a network cable. I have 3 sensors; one in basement and two on the roof, but I still use only 1 nodemcu

Hi, TD and EX is in CM (Centimeters)? I just blindly ordered a sensor :slight_smile:

You think the sensor will work in the middle of such a barrel:

?

I tried setting this up and I keep getting the following message:

Distance measurement timed out!

I connected it to a nodemcu.
Any ideas on this?

Hi
Apologies I really am a newby at this. Do you just need those 2 components? In the photo it seems like you have more?

I have had the same sensors working with rpi3 and use 23AWG ethernet cable over 10m. Make sure you are using copper and not CCA.

Re: not getting ‘fuzzy measurements’, it took some tinkering but the key is in the delays between measurements (add sleep between ping and echo reading as well) – and then given the possibility of random echo, take several measurements.

Measurements are taken every minute and then hass will trigger the powering of wells to fill tanks based on threshold levels (i.e. once tank is below 85%, start pumping).
But to save on power costs, it calculates how long it expects that it will need to pump to fill and then begins pumping such that it will maximize the amount of pumping on cheapest power timeslots (with the goal of being full by next business day)

Also using blitzortung integration, if there have been more than two lightning strikes within 20km in the past 30 minutes it will remove power from wells and actuate a physical disconnect of mains (we are in a remote area and a burnt well with a golf course to water is not fun or cheap)

rpi communicates over MQTT back to hass. implementation has been flawless for year+

Example code for rpi to hass mqtt:

#%%Sensor
#Libraries
import RPi.GPIO as GPIO
import time
import statistics
 
#GPIO Mode (BOARD / BCM)
GPIO.setmode(GPIO.BCM)
 
#set GPIO Pins
GPIO_TRIGGER = 18
GPIO_ECHO = 24
 
#set GPIO direction (IN / OUT)
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)
 
def distance():
    # set Trigger to HIGH
    GPIO.output(GPIO_TRIGGER, True)
 
    # set Trigger after 0.01ms to LOW
    time.sleep(0.00005)
    GPIO.output(GPIO_TRIGGER, False)
 
    StartTime = time.time()
    StopTime = time.time()
 
    # save StartTime
    while GPIO.input(GPIO_ECHO) == 0:
        StartTime = time.time()
        # wait for real bounce
        time.sleep(0.0005)
 
    # save time of arrival
    while GPIO.input(GPIO_ECHO) == 1:
        StopTime = time.time()
 
    # time difference between start and arrival
    TimeElapsed = StopTime - StartTime
    # multiply with the sonic speed (34300 cm/s)
    # and divide by 2, because there and back
    distance = (TimeElapsed * 34300) / 2
 
    return distance

def middis():
    runs=[]
    for i in range(11):
        runs.append(distance())
        time.sleep(1)
    #print(runs)
    midrun = statistics.median(runs)
    return midrun

def cisternlevel(dist_to_water):
    #dist = middis()
    cisterndepth = 270 #set cistern total depth
    bufferheight = 25 #set height of sensor above max waterline + safety buffer
    cisternlevel = 100 * (cisterndepth + bufferheight - dist_to_water) / cisterndepth
    return cisternlevel
#%% MQTT
import paho.mqtt.client as mqtt
def bigmqtt():
    def on_connect(client, userdata, flags, rc):
        if rc==0:
            cisternclient.connected_flag = True
            print("connected ok returned code=",rc)
        else:
            cisternclient.bad_connection_flag=True
            print("bad connection returned code=",rc)
        
        
    def on_publish(client,userdata,result):
            print("data published \n")
            pass
    
    def on_disconnect(client,userdata,rc):
        logging.info("disconnected reason " +str(rc))
        cisternclient.connected_flag = False
        cisternclient.disconnect_flag = True

    # configure mqtt connection

    broker = "192.168.xx.xx"
    port = xxx
    username = "xxx"
    password = "xxx"
    mqtt.Client.connected_flag=False
    mqtt.Client.bad_connection_flag=False
    cisternclient=mqtt.Client("cistern1")
    cisternclient.username_pw_set(username, password)
    cisternclient.connected_flag = False
    cisternclient.on_connect = on_connect
    cisternclient.on_publish = on_publish
    cisternclient.will_set("borgo/cistern/health",payload="Disconnected",qos=0,retain=False)

    cisternclient.loop_start()
    try:
        cisternclient.connect(broker, port, keepalive=10)
        while not cisternclient.connected_flag and not cisternclient.bad_connection_flag:
            print("in wait loop")
            time.sleep(1)
        if cisternclient.bad_connection_flag:
            cisternclient.loop_stop()
            exit() #exit where?
        print("in Main loop")
        if __name__ == '__main__':
            try:
                while True:
                    dist = middis()
                    percentlevel=cisternlevel(dist)
                    print ("distance to top = %.1f cm" % dist)
                    print ("cistern level = %.1f percent" % percentlevel)
                    cisternclient.publish("borgo/cistern/level",payload=percentlevel,qos=0,retain=True)
                    cisternclient.publish("borgo/cistern/dist",payload=dist,qos=0,retain=True)
                    cisternclient.publish("borgo/cistern/health",payload="Connected",qos=0,retain=True)
                    time.sleep(10)
            except:
                print("smth broke")
                exit(1)
    except:
        print("main loop connection failed")
        exit(1)
    cisternclient.loop_stop()
    cisternclient.disconnect()
    

if __name__ == '__main__':
    try:
        while True:
            print("alors on danse")
            bigmqtt()
            time.sleep(10)
        # Reset by pressing CTRL + C
    except KeyboardInterrupt:
        print("Measurement stopped by User")
        GPIO.cleanup()


And then in hass config yaml mqtt sensor:

sensor:
    - platform: mqtt
      name: 'cistern_level'
      state_topic: 'borgo/cistern/level'
      unit_of_measurement: '%'
      value_template: "{{ value | round(1) }}"

    - platform: mqtt
      name: 'cistern_dist'
      state_topic: 'borgo/cistern/dist'
      unit_of_measurement: 'cm'
      value_template: "{{ value | round(1) }}"

    - platform: mqtt
      name: 'cistern_health'
      state_topic: 'borgo/cistern/health'
      unit_of_measurement: '%'

Waaaw, amazing, finally I got both sensors work on same NodeMCU (water flow & ultrasonic distance sensor waterproof) , thank you Omer and other brothers for your kind support :smiley:

Can you please share link of water flow sensor you are using?

I am using : YF-S201 Hall Effect Water Flow Meter / Sensor

Would this work for just measuring the water level in a 60 gallon rain barrel? We have one that is used to feed water to our chickens. I’d ideally just like to know when the water level gets low so I can refill it.

Hello @nawafbana its possible to share the code?