, ,

Measure water level in cisterns and tanks with Home Assistant, ESPHome and TL-136 pressure sensor – UPDATE!

How do you measure the fill level of a cistern or tank with little effort and good accuracy? I have a solution with ESPHome and a TL-136 pressure sensor in use.

Wasserstand mit ESPHome und HomeAssistant messen

>> Zur deutschen Version dieses Beitrags gehen

Rainwater is now a precious commodity. Last year we got a 5,000 litre rainwater cistern from Rewatec. It’s rarely worth having something like this installed just for the rainwater, as the effort and costs are considerable.

5.000 litre rainwater cistern from Rewatec

However, when renovating our patio, we realised that our guttering was dilapidated and the digger was already there anyway, so the cistern could be installed with little effort. The rain that falls on the 75 square metres of the south side of the roof now flows into it – if it rains at all …

We feed our Gardena sprinklers from the cistern, which are supplied by a Renkforce submersible pump (which has been in service for 5-7 years). Of course, we want to know how much water is in the cistern so that we can then control the irrigation. In addition, the submersible pump needs a minimum fill level of 8 cm so that it does not run dry.

DIY solutions usually unreliable

There are several DIY approaches for measuring the water level, but they often work rather poorly. Ultrasonic sensors that are aimed at the water surface not only suffer from the damp environment and then fail, but often do not measure correctly due to reflections. The same applies to optical TOF (Time of Flight) sensors. Capacitive sensors tend to measure inaccurately, as impurities change the dielectric constant of the water. I also experimented with this, but quickly abandoned it.

Tests with capacitive water level measurement

Cascades with reed relays and resistors and a float with a magnet work well and are robust, but only have a very coarse resolution. This is rather unsatisfactory for a cistern that can reach a maximum level of 1.05 metres.

Floats with pulleys and rope on a potentiometer are too adventurous.

Pressure sensors, on the other hand, are very accurate. Small pressure sensors, such as those built into blood pressure monitors, would be sufficient for the application and are quite inexpensive. However, they do not take into account the variable air pressure acting on the water column and do not provide accurate readings, and the hose to the sensor is also prone to clogging.

TL-136 pressure sensor as a solution

Piezoelectric pressure sensors, the TL-136 liquid level transducer, are not quite as inexpensive, but are robust and accurate. These also have a small tube in the supply line that allows the external pressure to flow into the measurement. These sensors are available for various filling levels for around 50 euros. For this you get a solid stainless steel housing with a very simple control unit. The sensor is simply placed at the bottom of the cistern or tank. I chose the 0-1 metre model as the overflow of my cistern is already at 105 cm. The 0-1 metre model should also be suitable for the popular IBC containers, as you don’t let them fill up to the last centimetre.

TL-136 sensor

The sensor is supplied with 24 volts and converts the pressure in the range 0-20 mA. The current must therefore be measured in order to calculate the fill level and later the fill quantity. There are inexpensive small modules with a transconductance converter, i.e. the conversion of a current into a voltage. However, you can also simply use a resistor to pick up the dropped voltage.

With a 150 Ohm resistor, you can tap the range up to 100 cm in such a way that it becomes a voltage with a maximum of 3.2 volts – ideal for the ADC of an ESP8266 or ESP32. With a 27 kOhm resistor in series to the analogue input of the ESP, you have additional protection, as this can tolerate a maximum of 3.3 volts. I still like to use the practical and inexpensive WeMos D1 Mini.

Circuit diagram with an ESP8266 WeMos D1 Mini

There is no need to use an additional power supply for the sensor’s 24 volts. A step-up converter does the job and can generate the 24 V from the 5 V pin of the ESP. The step-up converter is set to the required 24 V output voltage BEFORE installation.

Test setup with a water-filled HT tube and multimeter

To find out which voltage is output at which fill level, I put a plug in a 100 mm HT pipe, filled it with water, immersed the sensor to different depths and measured the voltage. The hydrostatic pressure in such a pipe at the same depth is just as high as in a 5,000 litre cistern.

Determine immersion depth and measured values

The ESPHome code for water level measurement

The code for the ESPHome sensor is fairly self-explanatory. The A0 pin, i.e. the analogue-digital converter, is read out. Incidentally, the ESP8266 does not output 0 – 3.3 volts here, but 0 – 1 V. I have therefore installed a filter with – multiply: 3.3. The id: levelraw allows me to access the level in centimetres again later in another function.

esphome:
  name: waterking
  platform: ESP8266
  board: d1_mini
  

# Enable logging
logger:
  baud_rate: 0
  
# Enable Home Assistant API
api:

ota:
  password: !secret ota password
wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Waterking Fallback Hotspot"
    password: !secret fallback password

captive_portal:
  
  
sensor:
  - platform: adc
    pin: A0
    name: "Wasserstandcm"
    id: levelraw
    update_interval: 2s
    filters:
      - multiply: 3.3
      - sliding_window_moving_average:
          window_size: 30
          send_every: 30
      - calibrate_linear:
            - 0.61 -> 0.0
            - 0.76 -> 0.075
            - 0.8 -> 0.09
            - 0.81 -> 0.1
            - 0.8411 -> 0.12
            - 0.99 -> 0.172
            - 1.04 -> 0.22
            - 1.2 -> 0.25
            - 1.8 -> 0.5
            - 2.4 -> 0.75
            - 2.66 -> 0.9
            - 2.983 -> 1.0
            - 3.2 -> 1.19
      - multiply: 100
    accuracy_decimals: 1
    unit_of_measurement: cm
    icon: "mdi:car-coolant-level"
            
  - platform: adc
    pin: A0
    name: "Cistern Volt"
    update_interval: 5s
    filters:
      - multiply: 3.3
      - median:
          window_size: 7
          send_every: 4
          send_first_at: 3
  
  - platform: template
    name: "Cistern litre"
    lambda: |-
      return id(levelraw).state;
    
    filters:
      - calibrate_linear:
          - 4 -> 80
          - 10 -> 200
          - 12.5 -> 300
          - 15 -> 400
          - 17.5 -> 500
          - 20 -> 600
          - 25 -> 850
          - 27.5 -> 1000
          - 40 -> 1700
          - 45 -> 2000
          - 60 -> 3000
          - 70 -> 3600
          - 80 -> 4000
          - 85 -> 4400
          - 90 -> 4700
          - 95 -> 4900
          - 100 -> 5100
    unit_of_measurement: l
    accuracy_decimals: 0

  - platform: template
    name: "Idraw"
    lambda: |-
      return id(levelraw).state; 
Code language: YAML (yaml)

The median smoothes the values, as the signal is somewhat noisy. I have not yet found out why. The voltage supply of the step-up converter is stable. However, the noise is in the range of 0.5 cm fill level, which is negligible. The accuracy of the sensor itself is specified as 0.2 – 0.5 % FS. At a fill level of 0 – 1 metre, the 0.5 cm noise is exactly 0.5 % …

[Update] A 1 uF capacitor between ground and A0 provides some noise reduction and is included in the circuit diagram.

[Update 2] The A/D converter of the ESP8266 is not suitable for such measurements and does not work linearly. The Espressif data sheets say the same. That’s why I’m now using an ADS1115 AD converter, which has eliminated the noise. However, I have to recalculate the values and the cistern is currently full. An update will be coming soon.

The calibrate_linear filter converts the voltage into the actual fill level, because the sensor is not completely linear. I have determined the first values with my test setup and am now gradually correcting them with the values from the cistern. The – multiply: 100 filter ensures that the output is in centimetres.

Wasserstandsensor Home Assistant
The circuit on a perfboard in a junction box

I then query the ADC a second time to obtain an output in volts, which I can use to gradually correct the linear filter with the real fill levels.

The second function starts with – platform: template

Here I get the value in centimetres with return id(levelraw).state; and then convert it to the fill level in litres with another – calibrate_linear filter.

TL – 136 Flüssigkeitsstandsender Wasser Ölstandsensor Detektor 24VDC 420mA Signalausgang(0-2m), Sender
  • Mehrschichtiger wasserdichter Schutz IP68, 45-Grad-Schrägwinkel-Anti-Schock, abnehmbarer Anti-Blocking-Schutz.
  • Eingangspegelgeber, hochpräzise Diffusion von Silizium, genauere Überwachung des Wasserstandes.
  • Das gemessene Medium ist Wasser, Öl und andere Flüssigkeiten, die Edelstahl nicht angreifen.
LAOMAO 5X Step-up Boost Power Converter XL6009 für Arduino Raspberry DIY-Projects basteln
  • Es handelt sich hierbei um ein Step-UP, Spannungsregler Aufwärtswandler oder Boost-Converter.
  • Die Ausgangsspannung ist nach dem Umwandlung immer größer als die Eingangsspannung.
  • Die Platine wandelt Spannungen von 3V-32V, einstellbar an dem Potentiometer in 5V – 35V Volt um.
Kemo M167N Füllstandsanzeige für Wassertanks batteriebetrieben. Fernmessung bis 100 Meter. Für Regenwasser, Klärkammern, Gülletanks. Mit LED Anzeigen
  • batteriebetriebene füllstandanzeige
  • misst füllstände von wassertanks wie regenwasser, klärkammern oder gülletanks
  • anzeige erfolgt nach knopfdruck über 10 led’s
Strom zu Spannung Wandler Modul 0-20mA 4-20mA 0-3.3V 0-5V 0-10V Signalumformer DC DC Konverter Platine
  • BREITER AUSGANGSVOLATFE-BEREICH – Der Strom-Spannungs-Wandler hat einen weiten Versorgungsspannungsbereich und die Ausgangsspannung unterstützt mehrere Bereiche
  • EINSTELLBAR – Der Strom-Spannungs-Wandler verwendet eine ausgeklügelte Produktionstechnologie, der 0-Punkt und der Vollbereich können selbst eingestellt werden
  • KUNSTSTOFFMATERIAL – Das Konvertermodul besteht aus hochwertigem Kunststoff und hat eine hohe Stabilität, gute Linearität und Industriequalität

Convert filling height to volume with level curve

My Rewatec cistern has a rather complex shape, so the fill levels in litres are not linear over the fill level. Rewatec sent me a fill level curve on request. This allows the fill level to be converted as a function of the fill level. As mentioned before: With 5,000 litres, it doesn’t matter whether 20 litres more or less are displayed. The rest is just an auxiliary function that can be omitted.

Fill level curve of the cistern

At the moment it is also very dry here, so the water level in the cistern is at a very low level of 10 – 25 centimetres and therefore 150 – 1000 litres.

Level progression over 10 days with irrigation and little rainfall

However, you can easily see the inflows and outflows and can therefore also determine how many litres 5 minutes of lawn watering is. In our case, we get about 150 litres per watering. You can also easily recognise rainfall and the rapid rise in the level.

Füllstand Zisterne Home Assistant
Level rise during rain

As we also have two recessed and connected rain barrels with 1,500 litres each, I will also be installing a sensor here soon.

The two recessed rainwater barrels will also be fitted with a TL-136

Overall, the solution with the TL-136 liquid level transmitters is a simple and sufficiently accurate solution for measuring fill levels. The sensors are robust and easy to control. They can be easily corrected with the linear filters of the ESPHome platform, so that an accuracy in the range of 1 % is possible. This is more than sufficient for use in rainwater barrels and cisterns.

Fill level display in Home Assistant

The values obtained can be used to dynamically control the watering time, for example by shortening the watering time when there is only a little water left in the cistern.

Update 2023 – more reliable and accurate measurement

As announced last year, I have optimised the water level sensor. The problem with the original project was the poor ADC of the ESP8266, which was very noisy. In addition, the circuit with the simple measuring resistor was not particularly reliable, which was also correctly noted here in the comments. Due to the winter season and other projects, the update took a little longer than planned.

As already described, I am now using an ADS1115 4-channel ADC. You only need one of the 4 channels of the ADS1115, so you still have 3 ADCs left for other tasks.

After a few tests, I also decided in favour of the inexpensive current transformer / transducer. This small module not only has the advantage that the input of the ADS1115 never sees more than 3.3 volts. All jumpers on the module are removed for this purpose. You can also set the zero point (sensor not immersed) and the maximum output voltage. This allows you to maximise the measuring range, even if you only have to measure up to a maximum of 70 cm with a 0-1 metre sensor, for example. I have desoldered the terminals so that I can solder the module to my strip grid board.

Simplified circuit diagram of the new version with ADS1115 (click to enlarge!)

Following a tip in the comments, I had to refresh my knowledge of 4-20 mA current loops (that was almost 30 years ago and I no longer had it to hand): These current loops are very robust against interference and can be 100 m or more long. This means you can extend the TL136 sensor into the house, where the associated electronics are installed in a warm and dry place

The wiring is very simple. The ADS1115 is connected to the Wemos via I2C bus, the output of the transducer is connected to an input (ADC0 in my case) of the ADS1115.

TL136 Wasserstandssensor
First tests and series of measurements with the new electronics

Using the trimmer labelled “Zero” in the circuit diagram, set the output voltage of the module (green cable in the diagram) to almost 0 volts when the sensor is not immersed. Now immerse the TL136 sensor to the maximum depth at the maximum fill level and set the voltage at the output (green cable in the diagram) to just under 3.3 volts using the “Span” trimmer. This makes optimum use of the possible measuring range and gives the maximum resolution.

I again took a series of measurements in 10 cm steps and noted the corresponding voltages. As before, this is used to calculate the filling height in centimetres and from this the filling quantity according to the manufacturer’s filling diagram.

Thanks to the transducer and the ADS1115, you are rewarded with a very precise (although already excessive for the application) and noise-free measurement. The residual noise is a maximum of 0.1 % and thus corresponds to the tolerance of the TL136 sensor.

Here is a comparison of the old method with the new one, which probably speaks for itself:

Zoomed in sharply, you can see that the deviation is now only – 1mm:

The remaining ADC channels of the ADS1115 can be used, for example, for simple soil moisture sensors etc.

As there were still GPIOs free on the Wemos anyway, I also provided an input for 1-wire sensors. The inexpensive DS18B20 temperature sensors can be used, for example, to record the ground temperature, the temperature in the shed or the water temperature in the cistern. Several of these 1-wire sensors can be operated in parallel at one input.

Parts list:

The new code with ADS1115 and 1-Wire (the 1-Wire circuit is not included in the circuit diagram – you can do it yourself if you need it 😉 !) looks like this for me:

esphome:
  name: cistern
  platform: ESP8266
  board: d1_mini
  

# Enable logging
logger:
  baud_rate: 0
  
# Enable Home Assistant API
api:

ota:
  password: !secret ota_password

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  use_address: cistern.local


  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Waterking Fallback Hotspot"
    password: !secret fallback_password

captive_portal:

# Configure i2c bus on D1 and D2
i2c:
  id: bus_a
  sda: D2
  scl: D1
  scan: True

# 1-wire sensors on pin D4
dallas:
  - pin: D4

# Set up ADC, ADDR pin is connected to VCC, therefore address 0x49
ads1115:
  - address: 0x49
    id: ads1115_49

# ADC channel A0 for measured value acquisition 
sensor:
  - platform: ads1115
    multiplexer: 'A0_GND'
    gain: 4.096
    name: "Water level cistern cm"
    id: levelraw
    update_interval: 2s
    unit_of_measurement: cm
    accuracy_decimals: 1
    icon: "mdi:car-coolant-level"
# Smooth measured values:
    filters:
      - sliding_window_moving_average:
          window_size: 20
          send_every: 20
# Convert voltages to fill level according to measurement series      
      - calibrate_linear:
          - 0.0 -> 0.0
          - 0.3 -> 10
          - 0.69 -> 20
          - 1.0 -> 30
          - 1.35 -> 40
          - 1.75 -> 50
          - 2.03 -> 60
          - 2.42 -> 70
          - 2.7 -> 80
          - 3.1 -> 90

# Calculate fill quantity according to fill level curve

  - platform: template
    name: "Cistern litres"
    lambda: |-
      return id(levelraw).state;
    
    filters:
      - calibrate_linear:
          - 4 -> 80
          - 10 -> 200
          - 12.5 -> 300
          - 15 -> 400
          - 17.5 -> 500
          - 20 -> 600
          - 25 -> 850
          - 27.5 -> 1000
          - 40 -> 1700
          - 45 -> 2000
          - 60 -> 3000
          - 70 -> 3600
          - 80 -> 4000
          - 85 -> 4400
          - 90 -> 4700
          - 95.5 -> 4980

    unit_of_measurement: l
    accuracy_decimals: 0

# 1-wire temperature sensor 

  - platform: dallas
    address: 0xef0516905a21ff28
    name: "Cistern Sens1"
    unit_of_measurement: °C
    accuracy_decimals: 1
 



Code language: YAML (yaml)

If you wish, you can also connect a display to show the water level, temperature etc. via the I2C bus or the Wemos SPI bus pins D5, D6 and D7. An LC display of type 1602/HD44780 or a MAX7219 7-segment display are suitable here. I also use the latter in my “Waterking” irrigation controller, which also displays the water level in the cistern.

Letzte Aktualisierung am 2025-12-14 / Affiliate Links / Bilder von der Amazon Product Advertising API

Abonnieren

Leave a Reply to nachbelichtet Cancel reply

Your email address will not be published. Required fields are marked *

2 responses to “Measure water level in cisterns and tanks with Home Assistant, ESPHome and TL-136 pressure sensor – UPDATE!”

  1. Filip

    hello, thank you for your work and your project.
    I built the circuit just like you. I need advice.
    Why do I see negative voltages in the esphome console?
    are in the range (-0.92xxx) – (-0.98xxx)
    I have everything connected according to your scheme.
    thank you.

    1. Did you build the new version with the ADS1115?