Been meaning to write this up for a while, so here it is. Over the last few months I've built a full custom controller setup for my 130L planted, CO2 injected tank, running on three ESP32 boards working together. It replaced an ageing Up Aqua CO2/pH controller and turned into a genuinely complete automation system for water changes, dosing, CO2, top-off, and reservoir monitoring. Sharing the overview here in case it's useful or interesting to anyone else down a similar rabbit hole.
The short version
Three boards, each with its own job:
- Water change controller — drains, refills, remineralises, and doses the tank automatically, sitting mostly idle between weekly changes.
- Tank controller — the brains of day-to-day operation, running CO2/pH control, top-off monitoring, the reservoir, and a small front panel with live readouts.
- Alexa bridge — ties the whole thing into Alexa for voice control and equipment scenes, and handles the feeding routine.
They talk to each other over WiFi and three deliberate hardwired links for the communications that genuinely shouldn't depend on the network as they are safety critical.
Water changes
Weekly, fully automated. Connect a line from the WaterDrop filter, a drain line that goes outside to the garden or lawn (both with quick connects and manual valves for safety), choose your water change volume in litres, press start and it then:
- runs through safety prompts to ensure everything is connected and safety valves are set correctly.
-prompts to clean prefilters
-prompts to measure remineralisers (calculated on screen, based on your water change volume selection).
-it then drains and refills with RO water. It also turns off/ on smart plugs so skimmers, co2, heaters ect are off for draining then start to turn them on as water fill reaches certain thresholds.
- during refil it remineralises to target GH and KH from a container with a magnetic stirrer with a perialstatic dosing pump that fires at set percentages of fill.
- it then connects to my Chihiros dosing pumps and fires the dosing boosts to preload nutrients (again these doses are scaled with selected water change volume)
-all without me touching anything. In fact it now means I can mow the lawn during water changes!
- It doses potassium bicarbonate for KH, calcium and magnesium sulfate for GH, and boosts macros (nitrate, phosphate, potassium, micros), again, all scaled to my actual water change volume.
Everything's logged, every step confirmed before moving to the next, with a wizard-style setup so I can adjust the fill amount, KH target, and anything else on the fly.
I also get phone updates, the fill solenoid is connected with a flow rate sensor, temperature probe and TDS sensor. So every 10L I get an update on the flow rate, tds and temperature of that 10L fill and average so far, so I can spot any issues. It will also abort the water change, stop filter.
CO2 and pH
This was the original reason the whole project started. My old analogue controller had a pretty coarse hysteresis, and in low KH water even small CO2 swings move pH more than I'd like. The new controller runs a proper pH probe on a scheduled window, targets a specific pH with a tight, tunable hysteresis, and logs everything continuously. It also catches things a dumb timer never could, a sudden pH crash with the solenoid already closed pointed straight at a CO2 regulator dumping its tank, something I'd never have caught otherwise until it was a much bigger problem. The Atlas Ezo ph sensor setup is elite and far more accurate than my previous setup. I can also see live updates, get phone alerts for certain events and have set safety alets and shutoffs for events like rapid changes in ph.
I have also put a weight sensor under my CO2 bottle so it tells me how full/empty my co2 bottle is and predicts refill date based on useage (this is untested as it's still so new, I don't have the data for it to be accurate.)
Dosing
Being sick of the Chihiros app occasionally being unavailable this year, I have given over control of the scheduling and setup to my controller. I have my own dashboard and phone app that does this now and can send schedules and settings to the Chihiros pumps. It has taken some trial error and bluetooth sniffing apps to work this out but it is rock solid now.
Four channel dosing pump, fully scripted daily doses plus automatic post-water-change boosts, calculated from my actual verified nutrient targets rather than rough guesses. Doses are triggered automatically the moment a water change finishes.
Top-off and reservoir
For now, the auto top-off unit itself does the actual work, but the controller now watches the reservoir independently, a proper pressure-based level sensor for the real litre count, plus a simple mechanical float as a dumb, sensor-agnostic backup. If the float ever trips, ATO shuts down immediately and I get a notification, worded differently depending on whether the pressure sensor agrees with the float or not, since a disagreement between the two usually points at the pressure sensor itself needing a look rather than a genuinely empty reservoir. I have some optical sensors on the way, and hopefully by next week the controller is running the ATO independently.
Feeding
A small but genuinely nice touch. Feeding pauses CO2 injection, filter and skimmer automatically, it's voice activated or you can use a unit mounted button, and the front panel readouts switch to a simple "feeding" display while the filter's off, since the normal sensor numbers would be meaningless with no flow through the lines anyway.
Remote monitoring
Everything logs to a Grafana dashboard, I have pH, temperature, TDS, reservoir level se sors, it also logs CO2 state, with history of all controller actions that I can actually look back through rather than just a live snapshot. Genuinely useful for spotting slow trends, not just catching sudden problems.
Alexa integration
Voice control for scenes around water changes, changing settings and feeding, equipment turning off and on automatically at the right points in each process, and a physical feed button that fires the exact same routine as the voice command.
Safety, and why it mattered more than any single feature
If there's one thing I'd want someone building something similar to take away, it's this. Every automated system that can act on its own needs to fail toward safe, not just work correctly when everything's fine.
A few of the principles that ended up running through the whole build:
- Solenoids fail closed. Power loss means CO2 and water stay off, never on, by hardware design, not firmware logic that could have a bug in it.
- A tripped safety condition can't be quietly dismissed. If something raises an alert, like the backup float, you can acknowledge it, but the system won't let you clear it while the actual problem is still physically present. No accidentally waving away a real fault.
- The one link that has to work regardless of WiFi, does. CO2 and ATO pausing during a water change runs over a direct hardwired connection between boards, not the network. Everything else can be a bit more relaxed about connectivity; that one thing can't be.
- A backup sensor's only job is to disagree usefully. The float switch isn't there to be a second source of truth, it's there to catch the primary sensor being wrong. When they disagree, the alert tells me which one to actually go check.
- Never power anything from two sources at once. Learned that one the hard way, destroyed a board's regulator early on doing exactly that. So it now has wifi firmware updates for each board, to save the USB input power when updating by PC
None of this was designed perfectly the first time either, more caught through actually running it and paying attention than getting it right on paper up front. A few genuine bugs this build taught me: features that were fully coded but sitting behind a switch I'd forgotten to flip on, so they looked complete but never actually ran; a menu screen that could lose progress if you walked away at the wrong moment during a slow calibration step. Both fixed once they showed up in real use, which is really the whole point of building it in stages rather than all at once and hoping. I have spent weeks finding and squashing bugs before I have given over control of the tank to it.
Next on the list:
Heater/fan control, full ATO control, uninteruptable power unit uninterruptible that alerts me to power outages and turns on air pumps.
It is also in a pretty basic case and the cutouts are purposely oversized. I have ordered smoked acrylic to 'wrap' it in so it appears to be black rectangular box, with only the LED parameter readouts (temp, pH, TDS and ATO reservoir litres) visible through the smoke tinted acrylic and the two black control knobs that wake sleeping OLED screens, all other controls will be behind hinged flaps. I want to make sure all the sensors etc are wired correctly though before I wrap and anchor wiring.
The great thing is, every time I think of something I want to add, it is a coding session with the help of AI and finding the sensors or equipement required. I can wake up with an idea and genuinely have it implemented with an hour or two of soldering and coding. It fits my tank like a glove and is infinitely adaptable. menu setup and setting options all added as I think of them!
I will add some pictures below of the in progress build! I wanted to share in case anyone is thinking of doing the same, with the prices of ESP32s and the sensors (except for the Atlas Ezo chips! which are expensive but well worth it!) it is definitely a project in reach of anyone with a basic idea of code and soldering.