Water tank - water level sensor using fuel/water sender and esphome

So, I have two underground oblate toroid (think elongated doughnut) water tanks, joined together making a total of 10,000 litres. This is used to water our garden beds and lawn. I wanted to be able to monitor the amount of water in the tanks, and (as it doesn’t have a float switch) switch the pump off in the event that the water level is getting low - to both protect the pump from burning out should it try to run without water, as well as to stop the pump from dredging up the last few litres that can contain silt that will in turn clog up the watering system.

There are many options out there do do this. I did find a number of people have used sensors that measure the distance to the top of the water which is fine, but can have issues with reflections and you also have to be careful to use something that is protected against water ingress. I instead decided to try a fuel/water sensor as they are rugged sealed stainless steel sensors (used in boats, caravans and cars), and are simple and reliable. Another alternative for me would have been a pressure sensor resting on the bottom of the tank, but I was a little concerned about the cabling etc being constantly submerged plus the math required to work out volume in an oblate toroid made me go ‘meh’. Cost of the sensors were similar, so I went the fuel/water sender (available on Aliexpress, Amazon etc as well as many auto and marine stores - I got mine via eBay).

Getting it to work was actually pretty simple. Hardware required:

  • Fuel/water sensor
  • Wemos D1 mini
  • Pullup resistor to keep the voltage below 1V (the limit for A0 on the D1) - in my case I needed a 1.8k resistor. I had some 2k resistors, so used one of those.
  • Small hobby box
  • Usb cable & charger
  • Cable (I used irrigation cable as it can cope with being buried in the ground etc)

I installed the sensor in the tank, joined the cable from the sensor to the irrigation cable (either solder and heat shrink the joins, or use gel filled crimp connectors - also frequently available in the irrigation section of hardware stores eg https://www.bunnings.com.au/k-rain-idc-gel-cable-connectors-5-pack_p0242399), then ran the cable to where I was going to keep the D1 mini.

I connected my D1 to my hassio server, and uploaded my esphome code on to it, then made sure I could update it wirelessly. Then I hooked everything up. With my sensor there were two wires - one black and one blue. I doubt it matters which wire is used for what, but I ran the black one to ground on the D1 mini. As this was a test, I used a small breadboard - later I’ll probably solder everything up for reliability. Anyhow, the blue wire I ran to a spare row on the breadboard. Then from that row I ran a wire to A0. From that row I also connected my 2k resistor to a second row, then from that row I connected a wire to 3V on the D1.

Initially I set the sensor to take readings every second. Then using the log option in esphome I made a note of the voltage readings as I moved the float up the sensor rod - I decided that 5cm increments would be good enough. I could then use math along with info from my tank supplier to work out what voltages would show specific percentage levels based on height. I then changed the readings to be done every 30 seconds.

If you try to replicate this, the voltage levels & associated percentage levels, plus the pullup resistor will almost certainly be different. See also Monitoring Water Level from Vanomation who did something very similar and I did borrow some of his code! To calculate the pullup resistor you require, multiply the maximum ohm rating of your sensor by 9, then get a resistor that is larger than that. My sensor has a range of 0-190 ohm, so rough calc is 190*9=1710 ohm. So I needed something bigger than 1.71k ohm. 2k was fine.

esphome sensor code:

  - platform: uptime
    name: "watersens01 Uptime"
  - platform: wifi_signal
    name: "watersens01 WiFi Signal"
    update_interval: 60s
  - platform: adc
    pin: A0
    name: "Water Level Voltage"
    id: water_voltage
    update_interval: 30s
    accuracy_decimals: 3
      - multiply: 3.3
  - platform: template
    name: "Water Level Percent"
    unit_of_measurement: "%"
    accuracy_decimals: 0
    update_interval: 30s
    lambda: |-
      if (id(water_voltage).state < 0.02578) {
       return 25;
      } else if (id(water_voltage).state < 0.05479) {
       return 30;
      } else if (id(water_voltage).state < 0.06768) {
       return 33;
      } else if (id(water_voltage).state < 0.09023) {
       return 35;
      } else if (id(water_voltage).state < 0.10957) {
       return 40;
      } else if (id(water_voltage).state < 0.12246) {
       return 45;
      } else if (id(water_voltage).state < 0.13213) {
       return 50;
      } else if (id(water_voltage).state < 0.15469) {
       return 53;
      } else if (id(water_voltage).state < 0.16113) {
       return 56;
      } else if (id(water_voltage).state < 0.18047) {
       return 60;
      } else if (id(water_voltage).state < 0.19336) {
       return 64;
      } else if (id(water_voltage).state < 0.19980) {
       return 67;
      } else if (id(water_voltage).state < 0.21592) {
       return 71;
      } else if (id(water_voltage).state < 0.23848) {
       return 75;
      } else if (id(water_voltage).state < 0.25137) {
       return 85;
      } else {
       return 100;

You could also create a “volume” to show the total number of litres available, although in my case I didn’t bother as it’s a 10,000 litre tank so it’s pretty easy to work out what is there - if it’s 75% then it’s 7,500 litres!


This is exactly what Ive been looking for, thank you for posting this.

Would it you be able to post a picture of the wiring to the esp? I’m having difficulty picturing it in my head.

Thanks again!

Something a little like this… :slight_smile:

1 Like

Thank you for such a quick response!

1 Like


are you sure your coil is in the right place?

Not sure what you mean by that? If you mean the pullup resistor to keep the voltage below 1V, which in my rough sketch I’ll admit looks a little like a coil, then yes. It’s in the right spot.

Thanks for this. I ordered this today. I am going to try to monitor my Sump pit level. With the snow melt I have about 3 inches in there right now. In the summer it is usually 0 inches.
I have a backup 12V pump on it as well.’
I will use home assistant to setoff my water leak siren in the basement. And provide notifications to my phone.

Thank you for providing this. I mimicked your setup except with a 33 - 240 ohm probe. Just curious if you can explain the justification for the x9 pull up resistor? Everything works, but with the internal 220K resistor (part of the voltage divider on A0) the larger the resistor you add the less voltage range you have on ADC. Thank you again for your work.

Basically it depends on the ADC (analog to digital converter) you are using. The ESP8266 ADC pin input voltage range is 0 to 1V so just need to reduce the power so that it doesn’t go above that. If you get the max voltage to be just under the 1V mark then you’ll probably end up with slightly more accurate results. :slight_smile:

In relation to ADC on the ESP8266 and the ESP32. A great video from Andreas Spiess details issues with them. The consensus seems to be to add on something like an ADS1115. Much more accurate.

Ah yes, “the guy with the Swiss accent”. :slight_smile: Yep, as in most cases using something trying to do everything, separate dedicated boards can be better if you’re willing to pay the little extra. In my use case though (providing an indication of how much water is in my tank for the garden) what my Wemos provided is good enough. It would be different if I was measuring something more critical such as, maybe, fuel for a generator.

For me the ADC is constantly showing 3,3v. O matter what the sensor does (I have the same resistive water level sensor). What am I doing wrong?

Never mind. The resistor was faulty

I recognize this is an old thread and thank you to the original poster and the other contributors. I am trying to build this exact same thing with an ESP8266 and this Fuel Level sensor from amazon:
I got the 19" one and the 0 to 190ohm version

I’m getting the same issues a Mario 2 posts above where I am showing 3.3v at all times. Thanks to the follow-up post I have tried a number of different resisters of different sizes. I have tried 2K, 2K2, 5K, 6K , and so on and always get 3.3V.

I think the sensor is exactly the same as the ones from this thread but I could be wrong. It seems like it’s offering zero resistance maybe? I noticed the specs say that the working voltage is from 9V to 32V… could that be my issue?

Best I can think is, given that you’ve tried different resistors with no change, there is something wrong with the wiring and the resistor is not sitting between 3V and the sensor and/or (if you are using something like a breadboard) there is a solder bridge that is providing a direct connection that bypasses the resistor. Take the fuel level sensor out of the equation and just measure the voltage from ground to the wire that should be going to the sensor. Good luck! :slight_smile:

Thanks for responding. Your suggestions convinced me to go back and start over. For some reason it worked this time so clearly I had the resister in the wrong place before even though I think I checked and double checked a few times. I get different values than you so I’ll play around with different resistors and then adjust those percent ranges accordingly. Bottom line for anyone reading in the future, the sensor I linked above from Amazon works fine despite listing it’s for 9 to 32v.

Last question: Do you know if this should work the exact same way on an ESP32? Can you think of anything I would need to do different? I got it working on an 8266 that I have for testing but ultimately want to install it where I already have an ESP32.

Would work fine. The ESP8266 was preferred by me as it’s cheaper and I have a number of them spare, but if you already have an ESP32 sitting there then definitely take advantage of that. I think the ADC used by the ESP32 may even be a little more accurate depending on the board used.