This project is an Arduino Nano-based reverse osmosis monitoring project for tracking drinking water flow, TDS, temperature, filter life, and Pure RO vs. remineralized water usage.
The project is designed for under-sink RO systems where water can be routed between plain RO water and remineralized water. It uses a small OLED dashboard, a real-time clock, EEPROM-backed usage storage, and sensor-driven diagnostics to give a practical view of system health and filter replacement timelines.
Status: Work in progress / prototype Platform: Arduino Nano / ATmega328P
-
Tracks product water flow using a Hall-effect flow sensor
-
Estimates daily, weekly, and lifetime water usage
-
Separates Pure RO and remineralized water usage
-
Tracks filter life for:
- Sediment / carbon pre-filters
- RO membrane
- Post-filter / remineralization stages
-
Uses corrected Pure RO TDS as an RO membrane end-of-life override
-
Applies RO waste-water processing logic for pre-filter and membrane life estimates
-
Reads TDS through an external analog TDS driver board
-
Reads water temperature through the MH-01 temperature output
-
Displays live system information on a 128x64 I2C OLED
-
Uses a DS3231 real-time clock for date-aware usage tracking
-
Stores usage and calibration data in EEPROM
-
Includes button-based navigation and reset/calibration flows
-
Supports OLED sleep/wake behavior to reduce display wear
-
Chirps a speaker/buzzer when any filter is within 7 estimated days of end of life
This build is based on an iSpring RCC7AK reverse osmosis system with a manual Pure RO / remineralized water routing path added after the standard post-filter stage.
-
iSpring RCC7AK
- Base reverse osmosis system.
- Includes the alkaline remineralization stage used for the remineralized water path.
-
Arduino Nano / ATmega328P
- Main controller for sensor reading, display updates, filter-life calculations, mode detection, and button navigation.
- Powered via USB.
-
0.96" I2C OLED Display / SSD1306 / 128x64
- Main telemetry dashboard.
- Displays flow, TDS, temperature, filter health, mode, diagnostics, and settings.
-
DS3231 RTC Module
- Real-time clock used for date-aware tracking.
- Supports the 7-day rolling usage average and filter replacement estimates.
- Shares the I2C bus with the OLED display.
-
3x Tactile Push Buttons
- Used for screen navigation, settings, calibration, and filter resets.
- Wired to Arduino pins
D3,D5, andD7. - Uses the Nano's internal pull-up resistors, so each button connects its input pin to
GNDwhen pressed.
-
Small Speaker / Piezo Buzzer
- Audible filter end-of-life reminder.
- Wired to Arduino pin
D11andGND. - Chirps for 10 seconds once per hour when any filter stage has 7 estimated days or fewer remaining.
- A piezo buzzer can usually be tested directly; use a resistor or transistor driver for a low-ohm speaker.
-
MH-01-G1-4 3-in-1 Flow / TDS / Temperature Sensor
-
Integrated inline sensor installed in the 1/4" RO tubing.
-
Provides:
- Hall-effect turbine flow sensing
- TDS electrode pair
- Water temperature sensing
-
Flow signal connects to Arduino pin
D2 / INT0.
-
-
Analog TDS Driver Board
- Conditions the raw TDS electrode pair from the MH-01 sensor into an Arduino-readable analog voltage.
- The MH-01 TDS electrode wires connect to the driver board input.
- The driver board analog output connects to Arduino pin
A7. - Do not connect the raw TDS electrode pair directly to the Arduino.
-
10k Linear Potentiometer
-
Mechanically linked to the handle of the manual 3-way valve.
-
Allows the Arduino to detect whether the system is routing:
- Pure RO water
- Remineralized water
-
Potentiometer wiper connects to Arduino pin
A0.
-
-
81kΩ / 82kΩ Resistor
- Used as a pull-up resistor for the temperature sensing voltage divider with the MH-01 green 50k NTC temperature wire.
- Works with the temperature signal on Arduino pin
A2.
-
1/4" L-Port 3-Way Ball Valve
-
Manual routing valve installed after Stage 5.
-
Sends water down one of two paths:
- Path A: through the Stage 6 alkaline filter for remineralized water
- Path B: through a bypass line for Pure RO water
-
-
2x 1/4" One-Way Check Valves
- Installed near the end of both Path A and Path B before the paths merge.
- Prevents backfeeding between the remineralized and Pure RO paths.
- Helps avoid dead-leg mixing so the Pure RO path stays isolated from remineralized water.
-
1/4" T-Junction Union
- Final merge point where Path A and Path B combine into one outlet line.
- The merged line feeds the countertop sink faucet.
-
Extra 1/4" RO Tubing
- Used for the bypass path, sensor placement, valve routing, and final faucet connection.
| Function | Arduino Nano Pin |
|---|---|
| Flow sensor pulse | D2 / INT0 |
| Left button | D3 |
| Select button | D5 |
| Right button | D7 |
| Speaker / buzzer | D11 |
| Valve position potentiometer | A0 |
| TDS analog output | A7 |
| Temperature signal | A2 |
| OLED SDA + RTC SDA | A4 |
| OLED SCL + RTC SCL | A5 |
| 5V power | 5V |
| Ground | GND |
The MH-01 sensor includes flow, TDS, and temperature functions, but the wiring should be verified against the specific seller harness before final assembly.
Known flow wiring from the seller diagram:
| Wire | Function |
|---|---|
| Red | Flow sensor VCC |
| Black | Flow sensor GND |
| Yellow | Flow pulse signal |
Flow formula:
Hz = 36 × Q
Q = flow rate in L/min
2160 pulses = 1 liter
TDS wiring:
MH-01 TDS red/blue electrode pair -> TDS driver board input
TDS driver board analog output -> Arduino A7
Do not connect the raw TDS electrode pair directly to an Arduino analog pin.
For membrane-health tracking, place the TDS probe where it reads Pure RO water after the membrane/post-filter path and before Stage 6 remineralization. If it reads remineralized water, Stage 4 will look falsely high.
Temperature wiring uses the green MH-01 wire as a 50k NTC thermistor signal with an 81k/82k pull-up from 5V to A2.
The project uses three buttons:
| Button | Purpose |
|---|---|
| Left | Up / decrease |
| Select | Options / select / confirm |
| Right | Down / increase |
Typical behavior:
- Short press select on the default screen to open Options
- Short press left/right to move through menu choices or adjust values
- Short press select to enter an option or confirm a pending action
- Long press select to go back up one menu level
- Back is also available as a menu item for discoverability
The OLED UI is designed around quick glanceability.
The screen turns on at boot to show the default dashboard, then turns off automatically after 5 minutes without flow, button activity, or valve-position movement. After it sleeps, water flow, any button press, or valve movement wakes it again. A button press that wakes the screen does not also trigger its normal action; press again once the screen is awake.
The dashboard uses a compact layout with bottom padding so enclosure tolerances do not cut off the last OLED rows.
Default screen:
- Shows Pure RO, Remin, or an intermediate mineral percentage as the larger top line
- Shows current flow in
mL/s, Pure RO TDS inppm, and whole-degree water temperature on one centered line; no flow displays0mL/s - Shows filter replacement estimates as a 3-row, 2-column Stage 1 through Stage 6 grid using compact units such as
1y9m,11m,3w4d, or6d
Options menu:
- Reset filters
- Cal valve
- Cal TDS
- Dismiss alarm, shown only while a filter end-of-life alarm is active
- Back
Reset filters allows stages 1 through 6 to be reset individually after a confirmation step.
Valve calibration captures the Pure RO and fully remineralized valve positions as sweet spots, not hard travel endpoints. Turning past either point folds back into mixed-water percentages instead of staying clamped at Pure RO or ReMin.
TDS calibration samples the built-in uncalibrated TDS reading for 30 seconds, taking one sample every 0.5 seconds. The averaged sensor value is then used while the user enters the handheld meter value, and the resulting correction factor is stored in EEPROM.
Current seed calibration is based on a same-sample comparison of 12 ppm from the handheld meter and 8 ppm from the sensor, giving a correction factor of 1.5.
Filter end-of-life alarms start when any stage reaches 7 estimated days remaining. The speaker/buzzer chirps for 10 seconds, then waits one hour before chirping again. Dismiss alarm stores the dismissal in EEPROM for the currently affected stages. Resetting a filter clears that stage's dismissal.
The flow sensor is installed after the RO storage tank, so it measures product water only.
For filter-life estimates:
Pre-filters and RO membrane:
1 L product water = 4 L processed water estimate
Post-filter and remineralization stages:
1 L product water = 1 L filter usage
This means daily usage statistics remain based on actual drinking water dispensed, while pre-filter and membrane life calculations account for RO waste-water production.
Initial replacement estimates use these assumptions until actual usage history builds up:
Remineralized water: 1 L/day
Pure RO water: 2 L/week
The firmware uses a smoothed daily average that blends the default assumptions with the most recent usage history, then gradually lets real usage dominate the estimate.
The OLED formats remaining filter life as compact years, months, weeks, or days instead of capping long estimates at 999+.
Stage 4, the RO membrane, also uses the corrected Pure RO TDS reading as an end-of-life override:
RO TDS under 18 ppm: use the normal flow-based estimate
RO TDS 18-21 ppm: treat Stage 4 as 7 days remaining and trigger the normal EOL alarm
RO TDS 22 ppm or higher: treat Stage 4 as 0 days remaining
The current thresholds are based on the measured tap-water baseline around 144 ppm; 22 ppm is roughly the same as 85% membrane rejection. Higher readings, including 29 ppm and above, are covered by the same immediate replacement state.
Recommended repo structure:
smart_ro/
firmware/
smart_ro/
smart_ro.ino
docs/
wiring.md
images/
hardware/
enclosure/
cad/
README.md
LICENSE
.gitignore
The Arduino sketch should live in a folder with the same name as the .ino file:
firmware/smart_ro/smart_ro.ino
Install these through the Arduino Library Manager:
- Adafruit GFX Library
- Adafruit SSD1306
- RTClib by Adafruit
The sketch also uses standard Arduino libraries:
- Wire
- EEPROM
- math
In Arduino IDE:
-
Open
firmware/smart_ro/smart_ro.ino -
Select board:
Arduino Nano -
Select processor:
ATmega328P, orATmega328P (Old Bootloader)if upload fails
-
Select the correct serial port
-
Compile and upload
Before relying on readings, calibrate and verify:
-
Flow sensor
- Confirm pulse output on D2
- Validate measured volume against a known container
-
TDS
- Confirm the MH-01 TDS electrode pair is connected to a proper TDS driver board
- Calibrate against known TDS solution or a trusted TDS meter
-
Temperature
- Test the green temperature wire with a multimeter
- Confirm it behaves like a 50k NTC thermistor
- Confirm the pull-up resistor is close to 81k/82k
-
Valve position
- Set the remineralization valve to fully closed
- Run the valve calibration flow
- Confirm that opening the valve changes the analog reading enough to detect remin mode
This is a hobbyist monitoring project, not a certified water-quality or plumbing safety device.
Before installing:
- Confirm all parts are compatible with potable water
- Use fittings rated for your RO system pressure
- Leak-test the system thoroughly
- Keep electronics protected from water
- Use proper strain relief on cables
- Do not power motors or valves directly from Arduino pins
- Use a separate power supply for any future motorized valve or actuator
Potential future improvements:
- Motorized Pure RO / Remin valve switching
- Built-in valve position feedback
- Automatic flushing / maintenance reminders
- Better TDS calibration workflow
- Serial diagnostic mode
- Enclosure design
- PCB version
- Home Assistant or MQTT integration
- Data logging to SD card or cloud endpoint
This project is intended to be open source under the MIT License.
See LICENSE for details.