My grandparents live out in the woods, and are grappling with the largely anthropogenic drought in CA. They’ve been rationing their water, but haven’t had a good sense of how much water is available at a given time besides knocking on the side of the well-water tank and exclaiming “we’ve got water!” or the dour alternative. I looked into buying pre-built water tank sensors, but they were prohibitively expensive, so I figured we could make our own.

We wanted a continuous stream of water tank data, easily accessible from our phones. To do this, we needed to build sensors for detecting the water levels in the various tanks, and a smarthome server to receive all of the sensor outputs, aggregate them, and make them accessible on our phones/computers.

We’ll start with the sensor, then setup the homeassistant server and integrate the sensor

Table of Contents

An exhaustive list of all materials used in this project (total = $77, $61 of which is the raspberry pi home server)

The Sensor

Materials:

  • ESP-12E Development Board
  • DuPont Wires (socket-socket, otherwise known as female-female)
  • Ultrasonic HC-SR04 Distance Sensor
  • microUSB charger

These are all the parts you’ll need for the sensor:

Here’s the wiring diagram:

Here’s what it looks like wired up:

When I ‘water proof’ it, it is unexpectedly and impossibly cute (the nodemcu board is detached so I can feed it through the hole I put in the tank):

You can see the white ballon mounted next to the tank input pipe here, carefully such that the sensor is perpindicular to the water.

Here’s the hole and the wires out the back.

Here’s our little conjuction of power cable and distance sensor wires and the nodemcu board, mounted to the side of the tank

Now we’ll setup the software for the sensor

I’m assuming you have a unix system (linux or mac) open Terminal or some other terminal emulator and run the following

I use pip as a python package manager. It should be installed by default with python3

download the esphome package

pip install esphome

Now we’re going to make a .yaml configuration file that will be used to flash the software onto the sensor.

We’re gonna assume we name the config file ‘water.yaml’

esphome water.yaml wizard

Answer the questions like this if you got the exact sensor hardware I did:

(name [water_level]): <choose_a_name_for_water_sensor>
(ESP32/ESP8266): ESP8266
(board): nodemcu
(ssid): <your_wifi_network_name(ssid)>
(PSK): <your_wifi_password_(wpa_key)>
(password): <choose_a_password_for_flashing_sensor_if_you_want>

Once this is done, ensure that your sensor is plugged in via USB and run

esphome water.yaml run

It compiled, but I received the following error

INFO Successfully compiled program.
INFO Resolving IP address of barntank_sensor.local
ERROR Error resolving IP address of barntank_sensor.local. Is it connected to WiFi?
ERROR (If this error persists, please set a static IP address: https://esphome.io/components/wifi.html#manual-ips)
ERROR Error resolving IP address: Error resolving address with mDNS: Did not respond. Maybe the device is offline., [Errno 8] nodename nor servname provided, or not known

After about an hour of trouble shooting I realized it was because the microUSB cable I was using does not transfer data, it only charges devices, which is the case with some cheap cables. After replacing the cable with another microUSB I had lying around, it worked.

It’s gonna compile and take a few minutes. When prompted, select the option to flash over ‘serial’ i.e. USB.

If you change the configuration and flash it again you can use the following command to flash it over wifi

esphome water.yaml run --upload-port XX.XX.XX.XX

where xx.xx.xx.xx is the IP address of the sensor (the IP of the sensor is reported after you flash it over USB the first time. Might be worth writing it down.)

This is what my .yaml looks like

esphome:
  name: barntank_sensor
  platform: ESP8266
  board: nodemcu

# Enable logging
logger:

# Enable Home Assistant API
api:
  password: <choose_a_password_for_HomeAssistant>

ota:
  password: <choose_a_password_for_HomeAssistant>

wifi:
  ssid: <your_wifi_network_name(ssid)>
  password: <your_wifi_password_(wpa_key)>

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Barntank Sensor Fallback Hotspot"
    password: <auto_generated>


captive_portal:

sensor:
  - platform: ultrasonic
    trigger_pin: D6
    echo_pin: D5
    name: "Water Level"
    icon: "mdi:water"
    update_interval: 20s
    timeout: 3m
    filters:
    - filter_out: nan
    - lambda: return x * (-444.693) + 5000; # See Below for the Math I used
    - sliding_window_moving_average: # This takes the mean of 3 measurements and sends the 3rd measurement to home assistant. 
        window_size: 3
        send_every: 3
    unit_of_measurement: "gallons"

OK so the math to calculate the gallons (or whatever unit of volume) is going to be particular to your use.

Our tank was a cylinder, so the formula for volume was

$V = pi * r^2 * h$

We measured:

circumference = 8.33m

diameter = 2.65

height (when full) = 3.43m

$r = diameter / (2 * pi) $

So

$V = pi * (diameter / (2 * pi))^2 * h$

We’re looking for the Volume as a function of height, so we reduce the equation to volume and height.

Because we’re putting the sensor above the water in the tank, $Volume_{Current} = Volume_{Max} - Volume_{Sensor\ Distance}$

We know the volume of our tank is $8.93m^3$ gallons, so

$Volume_{Current} = 8.93m^3 - pi * (diameter / (2 * pi))^2 * sensor\ distance$

Your sensor distance is going to be some fixed distance above the water, so when the tank is full figure out what the $sensor\ distance$ is and adjust the constant such that both sides of the equation are equal when the tank is full.

For me this simplifies to the values seen in the above code block.

Flash/update the software on the sensor as often as you change the .yaml configuration. Now the sensor should be set up

Smarthome Server

Materials:

  • Raspberry Pi 4, 2 GB memory
  • microSD
  • microSD –> SD/USB converter
  • USB-C power cord

This part is pretty easy, but opens up pandora’s box. There are so many things you can do. But to integrate our sensor it’s pretty easy.

So we’re gonna install Home Assistant on a raspberry pi 4. You can install Home Assistant software on a bunch of different machines/computers, but raspberry pis are cheap and effective.

You’re going to start by taking your microSD card and using the microSD converter and plugging it into your computer.

Once you’ve got the microSD in, follow this tutorial for installing Home Assistant. It says to use Balena Etcher but you can also use Raspberry Pi Imager, which is what I used.

Once you set up home assistant you should find the sensor under the ‘configuration’ menu.

Now you can customize how to display the sensor data in your Home Assistant dashboard!