I run a pond filter housing with an ultrasonic distance sensor watching the water level, and a Home Assistant automation that cuts the pump when the reading sits between 86 and 89 percent for ten minutes straight. That threshold-and-delay approach has already saved me twice in the last week from watching my pond slowly drain into an overflowing filter housing. But it is a confidence interval, not a guarantee, and a ten minute wait is a long time when water is actively spilling out of a housing lid.

The suspected root cause is a partially clogged return hose – reduced flow back to the pond lets the filter housing fill faster than it can drain, and eventually water rises over the outlet and starts overflowing internally. While I track that down, I wanted a second, faster line of defense: a sensor that reacts to actual rising water at the top of the housing, not an inferred trend from a distance reading. I only have about 4 centimeters of clearance up there, so whatever I install needs to be small, immune to the algae and debris that pond water carries, and fast enough to matter.

Why the ultrasonic sensor alone isn’t enough

My existing setup measures distance to the water surface and only trips after the reading holds inside a narrow band for ten minutes. That filtering is there on purpose – ultrasonic readings on a splashing, algae-covered surface are noisy, and a short dip or spike shouldn’t cut the pump. It works well as an early warning, but it is fundamentally a trend detector, not a water-is-here-right-now alarm. I wanted something that sits exactly at the height I never want the water to reach, and reacts the moment it gets touched, with no interpretation involved and more important, no water spilling from the pond.

Picking a point sensor for the last 4 cm

For a discrete water-reached-this-exact-point trigger, two technologies fit a 4 cm gap:

  • A mini or side-mount float switch – a simple mechanical reed switch, potential-free, no calibration. Compact side-mounted versions only need a couple of centimeters of clearance rather than a tall vertical throw, so they physically fit. The downside is that it is a moving part sitting in a pond filter housing, and the same algae and debris I suspect is clogging my return hose can eventually gum up the float or hinge.
  • A non-contact capacitive sensor, like the XKC-Y25 series – it mounts on the outside of the housing wall and detects the water through the plastic via capacitance, with nothing touching the liquid at all.

Given that fouling and debris are already my prime suspect for the overflow itself, I did not want to introduce a second sensor with the same failure mode. I went with the non-contact option.

Why the XKC-Y25 fits this job

The XKC-Y25-V, and the NPN variant, is a small capacitive sensor that mounts against the outside wall of a non-metallic container – plastic, glass, or ceramic up to roughly 13 to 20 millimeters thick – and outputs a simple digital high or low signal when it senses liquid on the other side. A few things make it a good match here:

  • Nothing touches the pond water, so there is no probe or float to foul.
  • Response time is around 500 milliseconds, fast enough to act as a real interrupt rather than a trend.
  • The digital output reads straight into a GPIO pin, no ADC or calibration curve required.
  • My filter housing is plastic, so the sensor can sit entirely on the outside at the exact height I never want water to reach – it does not need to occupy any of my 4 cm of internal clearance at all.
  • Powered by the ESP Home device without need for capacitors or resistors.

The sensor is available on i.e. Amazon: https://www.amazon.nl/dp/B0C1ZVZF2L for appr 13 euro

XKC Y25-NPN 5-12V

Wiring it into ESPHome

I am running this on its own small ESP8266 board rather than adding it to an existing device, since this is a safety-critical trigger and I want it isolated from anything else that could be mid-update or busy. The sensor’s digital output goes straight to a GPIO configured as a binary sensor, with a short debounce filter so a single splash does not trip it, and an on_press action that calls Home Assistant directly to cut the pump.


esphome:
  name: atoms3-filter-water-detector
  friendly_name: AtomS3 Pond Filter Water Detector

esp32:
  board: m5stack-atoms3
  framework:
    type: arduino

# Leave empty (no encryption/key) per your standard setup
api:
  encryption:
    key: ******************************

ota:
  platform: esphome
  password: !secret ota_password

wifi:
  ssid: !secret wifi_iot_ssid
  password: !secret wifi_iot_password
  manual_ip:
    static_ip: 192.168.20.38
    gateway: 192.168.20.1
    subnet: 255.255.255.0
    dns1: 192.168.1.1

logger:

binary_sensor:
  - platform: gpio
    name: "Pond Filter Water Detector"
    id: pond_liquid_level_detected
    pin:
      number: GPIO39
      mode:
        input: true
        pullup: true
      inverted: true
    device_class: moisture
    filters:
      - delayed_on: 200ms
      - delayed_off: 200ms

That one second delay is there purely to ignore a stray splash – it is a fraction of the ten minute window my existing ultrasonic automation uses, so this sensor acts as the fast-reacting layer underneath the slower, trend-based one.

Adding a hardware-level failsafe

Because the consequence of this failing is an emptied pond, I do not want the only protection to depend on Wi-Fi, Home Assistant, or ESPHome staying up. On top of the software automation, I am looking at wiring the point sensor’s output in series with the pump’s relay coil, so a high water signal can physically interrupt power to the pump even if the network or automation stack is down. That sits alongside the Home Assistant automation as a second, independent layer rather than replacing it.

Still chasing the root cause

The point sensor and the ultrasonic automation are both safety nets, not a fix. My working theory remains a partially clogged or kinked return hose reducing outflow enough for the housing to back up – a pattern that fits the sometimes nature of the problem, since a partial blockage can worsen gradually or get briefly disturbed and clear on its own. Pulling the hose and checking for a biofilm buildup or a low point where debris settles is next on the list.

Top view of pond filter:

Pond filter top view

 

Sensor location on right side or housing:

Sensor location

 

ESP Home – Atom S3 Lite device with jumper wires.

Atom S3 Lite with jumperwires

Home Assistant entity:

HA entity

HA entity activities

 

The wire scheme is below. Be aware the coloring, it’s different than you might expect.

The MODE pin below is not connected. In my case water needs to be detected where in default state there is no water. It’s basically the NO, or NC setting. In the yaml you can see I inverted the signal. So In Home Assistant, the default value is “Dry” and it becomes “Wet” when the water is rising.

Dry state, led on the sensor is OFF. Wet state, led on the sensor is ON.

XKC Y25-NPN 5-12V Atom S3 Lite
Brown VCC 5V
Yellow OUT G39
Blue GND GND
Black MODE not connector
Related Posts

Privacy Preference Center