If your septic tank or wastewater treatment system has ever overflowed without warning, you know the problem: the standard buzzer alarm only works if someone is home and within earshot. This guide shows you how to build a WiFi-connected high-level sensor that sends an instant Telegram message to your phone — wherever you are — using an ESP32, a float switch, and about €20 in parts.

No soldering required. No monthly subscription. No SIM card.


What You Will Build

A compact waterproof sensor unit that:

Complete septic tank alarm unit with float switch and 3D-printed enclosure
Complete unit: controller box, cable run, and float switch
Full assembly of DIY septic alarm showing enclosure, conduit and float switch
The cable runs through conduit to protect it from damage

Parts List

ComponentSpec / NotesApprox. Cost
ESP32 development boardAny 38-pin or 30-pin variant — ESP32-WROOM-32 is ideal€4–7
Float switchIP68 rated, normally-open (NO), cable length 1–2 m. See note below on cable length.€5–15
Power supplyHLK-PM03 (3.3 V / 600 mA) — or 5 V USB adapter outdoors€3–5
EnclosureIP65 waterproof junction box, min. 100×68×50 mm€4–6
Pull-up resistor10 kΩ, 0.25 W€0.10
Cable glandPG7 or PG9, to suit float switch cable diameter€0.50
Total~€20–30
⚠️ Float switch quality matters. Always buy an IP68-rated unit with a stainless steel or polypropylene body. Cheap unrated switches corrode quickly in the aggressive environment of a septic tank. Cable length: on Amazon you will often see 5 m or 10 m versions (€10–15) — these are designed for sump pumps where the controller is far from the tank. For a septic alarm where the ESP32 enclosure sits right on the tank lid, a 1–2 m cable is sufficient and costs €5–8. Avoid paying extra for cable you will coil up and stuff in a box.

How It Works

A float switch is a simple device: a small float contains a magnetic reed switch. When the water rises, the float tilts and the switch changes state. We use a normally-open (NO) float switch — the circuit is open when the float hangs down (low water), and closes when the float rises with the water level.

The ESP32 monitors the switch pin. When it detects the switch closing, it connects to your WiFi and sends a Telegram alert. When the float drops again, it sends a second message confirming the level has normalised. The ESP32 does nothing in between — it just polls the pin every 200 ms, consuming minimal power.

The HLK-PM03 power module converts 230 V mains to 3.3 V directly — one compact component, no intermediate voltage stage needed. If you prefer to avoid mains wiring inside the enclosure, power the ESP32 via a 5 V USB phone charger mounted indoors.


Wiring Diagram

  230 V AC (Live)    ──── HLK-PM03 (L)
  230 V AC (Neutral) ──── HLK-PM03 (N)
                                │
                       HLK-PM03 (+3.3V) ──── ESP32 (3V3 pin)
                       HLK-PM03 (GND)   ──── ESP32 (GND pin)

  Float switch wire 1 ──── ESP32 GPIO 4
  Float switch wire 2 ──── ESP32 GND

  GPIO 4 ──────── 10kΩ resistor ──── 3.3V   ← pull-up

The 10 kΩ pull-up resistor holds GPIO 4 HIGH when the float switch is open (normal / low water). When the float rises and the switch closes, GPIO 4 is pulled to GND — this is the trigger condition the code looks for.

Inside the DIY septic alarm enclosure showing WiFi module, power supply and terminal blocks
Inside: WiFi module on perfboard, HLK power module (red), terminal block for float switch wires
3D-printed enclosure for septic tank alarm with USB power port
3D-printed enclosure with USB power port — all components protected from moisture
Mains safety: If you are connecting to 230 V mains, this work must comply with Irish electrical regulations (ETCI rules). If you are not a qualified electrician, power the ESP32 from an external USB adapter instead and run only the low-voltage float switch cable into the enclosure. Never work on live mains circuits.

Step 1 — Create a Telegram Bot

  1. Open Telegram and search for @BotFather
  2. Send the command /newbot
  3. Choose a name (e.g. "Septic Alarm") and a username ending in _bot
  4. BotFather replies with your bot token — a string like:
    7123456789:AAGxxxxxxxxxxxxxxxxxxxxxx
    Save this — you will need it in config.py
  5. Start a conversation with your new bot (search for its username, press Start)
  6. Get your chat ID — open this URL in a browser (replace with your actual token):
    https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates
    After sending any message to the bot, the JSON response will contain your numeric chat ID, e.g. "id": 123456789
Tip: To notify multiple family members, create a Telegram group, add your bot to it, and use the group's chat ID instead of a personal chat ID. Everyone in the group receives every alert simultaneously.

Step 2 — Flash MicroPython onto the ESP32

If your ESP32 does not already have MicroPython installed:

  1. Download the latest MicroPython firmware for ESP32 from micropython.org
  2. Install esptool: pip install esptool
  3. Erase the flash: esptool.py --chip esp32 erase_flash
  4. Flash the firmware:
    esptool.py --chip esp32 write_flash -z 0x1000 esp32-generic-firmware.bin
  5. Use Thonny IDE (free, beginner-friendly) to connect to the board and upload files

Step 3 — The Code

Upload two files to the ESP32: config.py with your settings, and main.py which runs automatically on boot.

config.py — your settings

# ── WiFi ────────────────────────────────────────────────────
WIFI_SSID     = "YourNetworkName"
WIFI_PASSWORD = "YourWiFiPassword"

# ── Telegram ─────────────────────────────────────────────────
BOT_TOKEN = "7123456789:AAGxxxxxxxxxxxxxxxxxxxxxx"
CHAT_ID   = "123456789"

# ── Hardware ──────────────────────────────────────────────────
FLOAT_PIN   = 4       # GPIO pin connected to float switch
DEBOUNCE_MS = 2000    # ms to wait before confirming a state change

# ── Alert messages ────────────────────────────────────────────
MSG_HIGH   = "⚠️ SEPTIC ALERT: High water level detected. Please check your system."
MSG_NORMAL = "✅ Septic level back to normal."

main.py — the main program

import machine
import network
import urequests
import utime
import config

def connect_wifi():
    """Connect to WiFi, return True if successful."""
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    if wlan.isconnected():
        return True
    print("Connecting to WiFi...")
    wlan.connect(config.WIFI_SSID, config.WIFI_PASSWORD)
    timeout = 15
    while not wlan.isconnected() and timeout > 0:
        utime.sleep(1)
        timeout -= 1
    if wlan.isconnected():
        print("Connected:", wlan.ifconfig()[0])
        return True
    print("WiFi connection failed")
    return False

def send_telegram(message):
    """Send a message via Telegram Bot API."""
    if not connect_wifi():
        return
    url = "https://api.telegram.org/bot{}/sendMessage".format(config.BOT_TOKEN)
    payload = {
        "chat_id": config.CHAT_ID,
        "text": message
    }
    try:
        r = urequests.post(url, json=payload)
        print("Telegram status:", r.status_code)
        r.close()
    except Exception as e:
        print("Send failed:", e)

def main():
    # GPIO 4 with internal pull-up
    # Reads HIGH (1) = switch open = normal level
    # Reads LOW  (0) = switch closed = HIGH WATER
    pin = machine.Pin(config.FLOAT_PIN, machine.Pin.IN, machine.Pin.PULL_UP)
    last_state = pin.value()
    print("Monitoring started. Pin state:", last_state)

    while True:
        state = pin.value()

        if state != last_state:
            # Debounce: wait, then re-read to confirm
            utime.sleep_ms(config.DEBOUNCE_MS)
            state = pin.value()

            if state != last_state:
                last_state = state
                if state == 0:
                    print("HIGH WATER")
                    send_telegram(config.MSG_HIGH)
                else:
                    print("Level normal")
                    send_telegram(config.MSG_NORMAL)

        utime.sleep_ms(200)

main()

Step 4 — Test Before Installing

Always test on the bench before mounting inside the tank:

  1. Power the ESP32 via USB and open Thonny — you should see "Connected: 192.168.x.x" in the console
  2. Manually tilt the float switch upward to simulate high water — the Telegram alert should arrive within 5–10 seconds
  3. Release the float — the "level normal" message should follow
  4. Verify the debounce works: quickly flick the switch several times — it should only send one message, not several
Local fallback: If you want an alarm even when the internet is down, wire a passive buzzer between GPIO 5 and GND and add two lines to main.py: buzzer = machine.Pin(5, machine.Pin.OUT) and toggle it when state == 0. A passive 5V buzzer costs under €1.

Step 5 — Install in the Tank

  1. Decide on the trigger height — typically 100–150 mm below the outlet pipe, or wherever your treatment plant's alarm level is specified
  2. Feed the float switch cable through the cable gland into the IP65 enclosure
  3. Connect float switch to GPIO 4 and GND (polarity does not matter for a reed switch)
  4. Seal the cable gland and mount the enclosure on the tank lid or nearby wall
  5. Connect power (mains via HLK-PM03, or USB from an indoor socket)
  6. Confirm a test message arrives before sealing the enclosure lid

Only the float switch and its cable go inside the tank. The ESP32 enclosure stays outside — mounted on the tank lid or a nearby wall.


Possible Improvements


Troubleshooting

SymptomLikely causeFix
No WiFi connection Wrong SSID/password, or 5 GHz network ESP32 supports 2.4 GHz only — check your router band settings
Telegram message not arriving Wrong token or chat ID Re-check config.py — both values are case-sensitive
False triggers / constant alerts Float vibrating, or DEBOUNCE_MS too short Increase DEBOUNCE_MS to 5000; secure the float cable so it cannot swing
Alert fires but tank looks fine Float switch mounted too high Lower the mounting position by 50–100 mm
ESP32 rebooting repeatedly Power supply too weak for WiFi transmit ESP32 peaks at ~500 mA during WiFi TX — replace cheap USB cable or charger
Works in test, fails after installation Float cable too short, or pinched in lid Check cable has enough slack; ensure lid closes without pinching

Total Cost

ItemCost
ESP32 board€5
IP68 float switch (1–2 m cable)€5–8
HLK-PM03 power module€3
IP65 enclosure€5
Resistor, cable gland, terminals€2
Total~€20–26
Monthly running cost€0

Questions about the DIY build? Send a message via the contact form — happy to help troubleshoot.