Well Guardian: About the Project

Inspiration

Groundwater is invisible until it's gone. Millions of households rely on private or shared wells for their water supply, but the well itself gives almost no feedback about how much water is really down there, how fast it's being drawn down, or whether it's safe to keep collecting. People either play it too safe and ration water they don't need to, or draw too aggressively and end up with a dry well and no warning.

We wanted a tool that turns a plain hole in the ground into something you can actually reason about — not a black box, and not a full-blown hydrology suite either, but something quantitative enough to trust and simple enough to check before you fill a bucket.

What it does

Well Guardian is a rain-aware groundwater dashboard. For each well it tracks:

  • Water level — from a live ultrasonic sensor reading or a manual entry
  • Extraction rate — how fast the level is falling, in %/day
  • Safe extractable amount today — how many liters can be drawn without pushing the well below its safe minimum
  • Rain forecast & estimated recharge — how much of the day's rain will actually refill this well, given its catchment area
  • Estimated time to recovery — if the well is past its safe minimum, when it's expected to be safe again

All of that rolls up into a single, plain-language recommendation:

"You can safely collect up to 42 liters today" "Reduce water usage — recharge is low" "Stop collecting water — well needs recovery. Next safe collection time: ~2 days"

Wells are set up through a guided flow (no raw hydrology numbers required) — pick a catchment size preset, calibrate the sensor's empty/full distance, and the app derives everything else. Since usually only one physical sensor exists but a household may care about more than one well, non-instrumented wells are clearly labeled "DEMO DATA."

How we built it

Sensing. An HC-SR04 ultrasonic sensor (or a Makeblock ultrasonic sensor on an mBot/mCore board) measures the distance from the well mouth down to the water surface. The Arduino sketch streams that as plain serial text (WELL_ID=01,DIST=45.2), and the web app reads it directly from the browser over the Web Serial API — no backend relay, no extra app, just plug in over USB and go. When there's no sensor attached, the same reading can be typed in manually, so the math and advice logic don't care where the number came from.

The water model. We treat the well as a cylinder. Given a diameter $d$ and a measured distance-to-water $D$ (against a calibrated empty distance $D_0$), the water column height is

$$ h = \operatorname{clip}\big(D_0 - D,\ 0,\ \text{depth}\big) $$

and the extractable volume above the safe minimum $h_{\text{min}}$ is

$$ V_{\text{extractable}} = \big(h - h_{\text{min}}\big) \cdot \pi \left(\frac{d}{2}\right)^{2} $$

converted from cm³ to liters. To stay conservative, the app never recommends drawing more than a third of that buffer in a single day, plus whatever recharge is expected from rain in the next 24 hours:

$$ V_{\text{safe/day}} = \frac{V_{\text{extractable}}}{3} + R_{24h} $$

Recharge from rain. Rainfall depth $P$ (mm) over the well's catchment area $A_c$ (m²), scaled by an infiltration coefficient $c$ (how much of that rain actually reaches the aquifer vs. runs off), gives expected recharge in liters:

$$ R = P \cdot A_c \cdot c $$

Recovery simulation. When a well is below its safe minimum, we forward-simulate the hourly forecast, adding recharge hour by hour until the projected water column crosses back above the safe threshold (plus a small buffer), and report how many days out that is — or say plainly that it's unknown if there's no rain in the forecast window.

Weather & geocoding. Forecasts and hourly precipitation come from Open-Meteo (free, no API key), geocoded from the well's location name. When a well needs to "stop collecting," the app also surfaces nearby alternative water sources using the Overpass API against OpenStreetMap data.

The app itself. A four-page app (Dashboard, Wells, Rain, Settings) built with React + TanStack Start + Vite, styled with Tailwind and Radix/shadcn components, and scaffolded/iterated on with Lovable. Wells and their readings auto-save to local storage on every change — no manual save step, and everything reloads on relaunch.

Challenges we ran into

  • The mBot toolchain fought us. The official Makeblock MakeBlockDrive library doesn't compile on current Arduino IDE versions (a bool → void* conversion error deep in MeSuperVariable.cpp), so we had to track down and switch to a community-maintained fork just to get a single distance reading off the board.
  • Serial data is messy in practice. Cables that are charge-only, ports that get grabbed by the Arduino IDE's own Serial Monitor, sensors angled at a surface that scatters the echo and returns garbage — the parser and UI both needed to handle "out of range" and dropped readings gracefully instead of treating every glitch as a real measurement.
  • Being quantitative without being dishonest. It was tempting to build something that looks like a scientific groundwater model, but a single distance reading and a rain forecast don't actually support that. We deliberately scoped the model to a simple cylinder + linear recharge estimate, and say so directly in the app: "Well Guardian is a decision-support estimate, not a scientific groundwater model, and does not predict land subsidence."
  • Iterating fast without losing the physical model. The project started as a single static HTML prototype to validate the Open-Meteo + math pipeline, then got rebuilt into the full multi-page app — porting the calculation logic over correctly (and re-verifying it against the original prototype) took care.

What we learned

  • How much can be inferred from one cheap sensor and a free weather API if the math is honest about its own uncertainty.
  • The Web Serial API makes "browser talks directly to a microcontroller" far more practical than we expected — no native app or backend needed.
  • Guided defaults (catchment-size presets, auto-computed safe minimums) matter more than raw configurability for something meant to be used by people who aren't hydrologists.

What's next

Multi-well hardware support (so more than one well can be "live" at a time), soil-specific infiltration coefficients instead of a single default, and push notifications when a well crosses into "reduce" or "stop" territory.

Built With

Share this project:

Updates

Submission history