Capacitive level measurement for water tanks in campers and motorhomes with ESPHome and Home-Assistant

Water tanks are often permanently installed in campers and are difficult to access. Reliable measurement of the fill level is therefore important, regardless of whether it is fresh, gray or waste water.

Previous solutions often require contact with water and are limited to an old analog display. In 2025, this will really be better.

I was looking for a good solution to meet my requirement of being able to read all sensors etc. in one interface in Home Assistant.

The different types of level measurement

I have tested these modern sensors and was unfortunately dissatisfied with all of them:

Ultrasonic sensor

This sensor emits sound waves that are reflected by the water surface. The time it takes for the waves to return enables an accurate calculation of the fill level.

The classic HC-SR04 ultrasonic sensor was out of the question here. Although it is very inexpensive, it does not have a housing and would corrode sooner or later if it came into contact with water.

Last updated on 12.11.2025 / Advertising / Images from the Amazon Product Advertising API

Better suited: The A02YYUW as a waterproof ultrasonic sensor. Quite expensive, but at least gave me quite reliable readings.

Offer
Ultrasonic distance sensor UART-controlled 3-450 Cm range DC 3.3 V-5 V Waterproof sensor, distance detector 3 to 450 Cm Low-power design IP67 for robots
  • Precise distance measurement: With a range of 3 cm to 450 cm, this ultrasonic distance sensor provides accurate and reliable measurements that are not affected by the environment. It ensures precise distance detection for various applications.

Last updated on 12.11.2025 / Advertising / Images from the Amazon Product Advertising API

The basic problem: The sensor needs a clear view of the water surface, which means that condensation quickly forms on the sensor, resulting in unreliable readings. Another problem: Due to the rather narrow format of my water tank, the sound waves were reflected by the side walls, resulting in incorrect measurements.

TOF sensors (Time-of-Flight)

These sensors work in a similar way to ultrasonic sensors, but use light instead of sound. Here I have tested the TOF10120 sensor. It is officially supported by ESPHome and can therefore also be easily read out.

Mounting the TOF sensor

It is cheaper than the ultrasonic sensor, but ultimately had similar problems. The readings were good as long as no water came into contact with the sensor. In the end, I quickly discarded this idea too.

Offer
TOF10120 Laser distance sensor 100-1800mm UART I2C output Laser distance meter distance sensor Laser joint distance measurement
  • 【Features】: Single power supply unit; UART I2C interface for device control and data transmission; Lead-free, RoHS-compliant.

Last updated on 12.11.2025 / Advertising / Images from the Amazon Product Advertising API

Other measurement options

Pressure sensors measure the hydrostatic pressure at the bottom of the tank. By measuring the pressure at the bottom of the tank, the fill level can be calculated. This method is probably very accurate, but also requires a tank probe that remains permanently in the tank and therefore also comes into contact with the drinking water. I wanted to avoid that. In addition, this seemed to me to be the most expensive solution, as I could only find one sensor that was suitable for configuration with ESPHome.

Offer

Last updated on 12.11.2025 / Advertising / Images from the Amazon Product Advertising API

Also exciting: A newer solution from VOTRONIC with a tank sensor. I don't know whether this could be read out with ESPHome. But maybe I'll test it in the future.

VOTRONIC Tank sensor FL (for level measurement of water and liquids containing water) Votronic 5530 Tank sensor FL
  • Permissible operating voltage: 12V and 24V DC (suitable for continuous operation) - For mounting on the top or side of the tank - Suitable for fresh and waste water tanks

Last updated on 12.11.2025 / Advertising / Images from the Amazon Product Advertising API

My experience with the various systems

In practice, ultrasonic and TOF sensors in particular have presented a number of challenges:

  • Condensation will sooner or later distort the measured values.
  • The moving water surface while driving makes precise measurements almost impossible.
  • Intervention in the tank necessary. Without at least a small hole in the top of the tank, no measurement was possible.

The smart do-it-yourself solution: XKC-Y25-NPN Capacitive sensors on the outer wall of the tank

After a lot of experimenting, I found the perfect solution: XKC-Y25-NPN capacitive sensors in combination with an ESP for reading and transmitting to Home Assistant. This combination has been working very reliably for me for over three years. And since there is no contact with water, it is also absolutely wear-free.

Jadeshay liquid level sensors 5-12V water level sensor, level indicator water tank level sensor Non-contact NPN output interface IP67 Waterproof
  • 【The durable】 liquid level sensor is suitable for the outer wall of non-metallic pipes without direct contact with liquids and is not corroded by corrosive liquids such as strong acid and alkali and is not affected by scaling or other debris.

Last updated on 12.11.2025 / Advertising / Images from the Amazon Product Advertising API

How capacitive measurement works

The sensors work through the tank wall and can detect liquids in plastic, glass or ceramic containers up to 20 mm thick. The measuring principle is based on the change in electrical capacitance. When the water level reaches the height of the sensor, the capacitance changes - the sensor switches. Each sensor can therefore signal: "Yes, there is water behind the wall at my height - or not".

By combining several sensors, it is possible to say, for example, that the tank is at least 75% full.

I decided to use 5 sensors, which I stuck to the outside of the tank at 10%, 25%, 50%, 75% and 100% of the fill level. This precision is sufficient for me personally, but theoretically you could also use 10 sensors and measure in 10% increments.

In practice, it is particularly interesting when the fill level is critical, i.e. low for fresh water and high for gray water. For this reason, I also reduce the distances in the low % positions.

The advantages of my solution

  • Non-contact measurement: the sensors are attached to the outside of the tank
  • No contamination: No contact with drinking water
  • Maintenance-free: no moving parts, no corrosion
  • Smart home integration: Full integration into Home Assistant

A major disadvantage

  • Measurement only in stages: The number of sensors determines how precise the measurement can be.

Reading out the values

I then connected all the sensors to a D1 Mini:

Offer
AZDelivery D1 Mini NodeMcu with ESP8266-12F WLAN Module CH340G Lua compatible with Arduino including e-book!
  • ✅ D1 Mini NodeMCU with ESP8266-12F. A versatile board that is characterized by its technical data.

Last updated on 12.11.2025 / Advertising / Images from the Amazon Product Advertising API

Power supply

I used a step-down converter, such as the one from Bauer Electronics, to convert the usual 12V in the camper to the 5V required by the D1:

DC-DC 8V-32V to 5V voltage converter 3A 15W | 12-V 5-V buck converter power supply 24-V voltage regulator voltage stabilizer voltage limiter step-down volt Input: 8-32V Output: 5V | 15W | 3A
  • The modules are widely used in the fields of motor vehicles, photovoltaics, industrial plants, trucks, boats, agricultural machinery, camping, mobile facilities, hobby and DIY as well as home and garden.

Last updated on 12.11.2025 / Advertising / Images from the Amazon Product Advertising API

How to install it

Positioning sensors on the tank

Correct positioning is crucial for meaningful measured values. Like this, for example:

  • 0% (empty): Approx. 5 cm above the bottom of the tank
  • 20%: At 1/5 of the tank height
  • 40%: At 2/5 of the tank height
  • 60%: At 3/5 of the tank height
  • 80%: At 4/5 of the tank height
  • 100% (full): Approx. 5 cm below the top edge

Tip: I first tested the position with masking tape. If everything fits, you can then simply use double-sided adhesive tape for mounting.

The sensors switch on one after the other when the fill level rises.

Cabling

Each XKC-Y25-NPN sensor has three connections:

  • Brown: VCC (+5V supply voltage)
  • Blue: GND (ground)
  • Black: Signal (to the GPIO of the ESP32)

More information can be found in the data sheet.

Calibration for special tank shapes

Important tip: If your water tank has a special shape (e.g. tanks above the wheel arch with sloping walls), I recommend the following calibration method:

  1. Empty tank completely
  2. Fill step by step - use a measuring cup or canister so you know exactly how many liters are already in the tank
  3. Mounting - Glue the first sensor to the tank wall at e.g. 10%, etc.

In my opinion, this seemed to be the simplest and most practical solution for calculating the fill level.

Integration in Home Assistant

Once all the sensors have been installed and wired to the D1 Mini, it's time to configure the software. I use ESPHome and the following code for configuration:

esphome:
  name: waterlevel-d1
  friendly_name: waterlevel_d1

esp8266:
  board: d1_mini

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: ENCRYPTION_KEY

# Enable Over-The-Air updates
ota:
  - platform: esphome
    password: OTA_PASSWORD

wifi:
  ssid: !secret wifi_ywbab_ssid
  password: !secret wifi_ywbab_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Waterlevel-D1 Fallback Hotspot"
    password: AP_PASSWORD

captive_portal:

binary_sensor:
  - platform: gpio
    pin:
      number: GPIO5
      inverted: false
      mode: INPUT_PULLUP
    name: waterlevel_10
    id: waterlevel_10
    filters:
      delayed_on_off: 20ms
  - platform: gpio
    pin:
      number: GPIO4
      inverted: false
      mode: INPUT_PULLUP
    name: waterlevel_25
    id: waterlevel_25
    filters:
      delayed_on_off: 20ms
  - platform: gpio
    pin:
      number: GPIO12
      inverted: false
      mode: INPUT_PULLUP
    name: waterlevel_50
    id: waterlevel_50
    filters:
      delayed_on_off: 20ms
  - platform: gpio
    pin:
      number: GPIO14
      inverted: false
      mode: INPUT_PULLUP
    name: waterlevel_75
    id: waterlevel_75
    filters:
      delayed_on_off: 20ms
  - platform: gpio
    pin:
      number: GPIO13
      inverted: false
      mode: INPUT_PULLUP
    name: waterlevel_100
    id: waterlevel_100

# Example configuration entry
sensor:
  - platform: template
    name: "waterlevel_0_to_100"
    unit_of_measurement: "%"
    accuracy_decimals: 0
    update_interval: 5s
    lambda: |-
      std::array<bool, 5> states = {
        id(waterlevel_10).state,
        id(waterlevel_25).state,
        id(waterlevel_50).state,
        id(waterlevel_75).state,
        id(waterlevel_100).state
      };

      // Count active sensors from highest to lowest
      for (int i = 4; i >= 0; i--) {
        if (states[i]) {
          switch (i) {
            case 4: return 100;
            case 3: return 75;
            case 2: return 50;
            case 1: return 25;
            case 0: return 10;
          }
        }
      }

      return 0;  // No sensors active

If your displayed fill level jumps back and forth too frequently, the following setting in ESPHome can help:

  • delayed_on: 100ms - Sensor must detect water continuously for at least 100ms
  • delayed_off: 3s - Sensor must detect no more water for 3 seconds before it switches over

Display on the dashboard

I used the Fluid-Level-Background-Card in combination with the Big-Number-Card to display the measurement values

  - type: custom:fluid-level-background-card
    entity: sensor.waterlevel_d1_waterlevel_0_to_100
    card:
      type: custom:bignumber-card
      title: Water
      entity: sensor.waterlevel_d1_waterlevel_0_to_100
      scale: 30px
      from: bottom
    level_color:
      - 48
      - 30
      - 138

Automations

There are of course many different ideas. Here is an example of automatically switching off the pump when the fill level is low:

alias: Pumpe aus bei leerem Tank
trigger:
  - platform: state
    entity_id: binary_sensor.tank_leer
    to: 'off'
condition: []
action:
  - service: switch.turn_off
    target:
      entity_id: switch.wasserpumpe
  - service: notify.dein_smartphone
    data:
      title: "🚰 Wasserpumpe abgeschaltet"
      message: "Tank ist leer - Pumpe wurde zum Schutz ausgeschaltet."

Another option: Flow measurement

What I have not yet tested is a display using flow measurement. I find this, probably very precise, option very exciting. But here, too, the problem remains: the flow meter is not really food-safe and will become contaminated over time.

Last updated on 12.11.2025 / Advertising / Images from the Amazon Product Advertising API

Conclusion: Smart, affordable and reliable

With a total budget of less than 100 euros, you have a level measuring system that works without contact. I am not yet aware of any commercial solutions that offer this option.

After more than three years of continuous use, I can say that the system works absolutely reliably and offers real added value compared to conventional solutions thanks to additional automation.

Further contributions

Your comments

Write a comment

Your e-mail address will not be published. Required fields are marked with *