ESP32-based real-time water pH monitoring & auto-dosing system with a live web dashboard
AquaSync is an automatic system for keeping water pH stable, built with an ESP32, a pH 4502C sensor, and two dosing pumps (acid & base) controlled through an L298N motor driver. The system reads the water's pH periodically, and whenever the pH drifts outside the neutral range, the ESP32 automatically pumps the appropriate neutralizing solution (acid or base) in small, gradual doses (pulse dosing) until the pH stabilizes again.
All sensor data and pump status are sent in real time to a Flask-based web dashboard, so the water condition can be monitored directly from a browser β complete with a pH gauge, pump status, and reading history.
- π§ͺ Real-time pH readings averaged over 20 ADC samples for stable results
- βοΈ Hysteresis-based auto-dosing β prevents the pumps from rapidly toggling on/off near the threshold (threshold chattering)
- π§ Pulse dosing β solution is pumped for a short burst followed by a mixing delay, preventing overdosing
- π Safety interlock β the acid and base pumps can never be active at the same time
- πΆ WiFi auto-reconnect if the connection drops
- π₯οΈ Real-time web dashboard (auto-refreshes every 0.5 seconds) with a pH gauge, pump status, and a log of the last 5 readings
- π’ Online/offline status detection based on the time since the last data was received
The dashboard displays the real-time pH value, raw sensor voltage & ADC, the status of both pumps (base/acid), and a log of the last 5 pH readings along with the water condition (Acidic/Neutral/Basic).
| Component | Qty | Notes |
|---|---|---|
| ESP32 DevKit | 1 | Main microcontroller |
| pH 4502C sensor + probe | 1 | Analog water pH reading |
| L298N Motor Driver | 1 | Dual channel β drives 2 DC pumps |
| 12V DC Water Pump | 2 | Dosing pumps for base & acid solution |
| 12V Power Supply | 1 | Power for pumps & driver |
| pH buffer solutions (4.01 / 6.86 / 9.18) | - | For sensor calibration |
π The full pin mapping (GPIO to each component) is available in
docs/wiring.md.
ββββββββββββββββ ADC Sampling ββββββββββββββββββββ
β pH Sensor β ββββββββββββββββββββΆ β ESP32 (Loop) β
ββββββββββββββββ (20 samples/2 sec) ββββββββββββββββββββ
β
pH < 6.5? β pH > 8.5?
βΌ
βββββββββββββββββββββββ
β Pulse Dosing State β
β Machine (Hysteresis)β
βββββββββββββββββββββββ
β
Pump ON (2 sec) β OFF β Wait (5 sec)
β
βΌ
βββββββββββββββββββββββ
β HTTP POST /api/ β
β update β Flask Serverβ
βββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββ
β Web Dashboard β
β (auto-refresh 0.5s) β
βββββββββββββββββββββββ
Hysteresis logic used:
| Condition | Base Pump ON | Base Pump OFF | Acid Pump ON | Acid Pump OFF |
|---|---|---|---|---|
| pH Threshold | < 6.50 | β₯ 6.80 | > 8.50 | β€ 8.20 |
The "buffer" range between the ON and OFF values prevents the pumps from rapidly switching on and off when the pH sits right at the threshold.
aquasync-ph-stabilizer/
βββ firmware/
β βββ aquasync_firmware.ino # Main ESP32 code
βββ server/
β βββ app.py # Flask web server (dashboard + API)
β βββ requirements.txt
βββ docs/
β βββ wiring.md # GPIO pin mapping details
β βββ images/
βββ .gitignore
βββ LICENSE
βββ README.md
cd server
pip install -r requirements.txt
python app.pyThe server will run at http://<your-computer-IP>:5000. Open it in a browser to view the dashboard.
- Open the
firmware/aquasync_firmware.inofile in Arduino IDE - Install the required library:
ArduinoJson - Configure below based on your address
const char* WIFI_SSID = "YOUR_WIFI_SSID"; const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD"; const char* SERVER_URL = "http://<your-computer-IP>:5000/api/update";
- Upload
aquasync_firmware.inoto the ESP32 - Open the Serial Monitor (115200 baud) to view sensor reading logs
Use pH buffer solutions 4.01, 6.86, and 9.18 to calibrate the sensor, then adjust the PH_SLOPE and PH_INTERCEPT values in the firmware based on the voltage measured for each solution.
| Parameter | Default | Description |
|---|---|---|
PUMP_SPEED |
150/255 | Pump PWM speed |
DOSE_ON_MS |
2000 ms | Pump active duration per dose |
DOSE_WAIT_MS |
5000 ms | Mixing delay after a dose |
INTERVAL_SENSOR |
2000 ms | Sensor reading interval |
INTERVAL_HTTP |
500 ms | Data-sending interval to the server |
See the LICENSE file for details.
- Yunachz β GitHub