Acropora Reef

A mixed SPS reef tank, dosed and lit by a self-built automation system rather than fixed daily programs. Chemistry (calcium, magnesium, alkalinity) is held on a peristaltic doser with schedules recalculated from actual tank measurements, and the tank's two lighting fixtures follow real solar elevation, live cloud cover and real moon phase for a reference Coral Triangle reef -- the same weather-tracking philosophy as the Heliamphora growroom, applied to a saltwater tank instead. This page documents the dosing and lighting automation and its live measured output; the photos further down are just the tank itself.

Chemistry & Dosing

Calcium and magnesium are held by a self-built multi-channel peristaltic doser on a 750L system, built on top of ReefRhythm-SmartDoser (MIT licensed, ESP32-S3 + MKS SERVO42C stepper-driven pump firmware) rather than written from scratch. Testing against this tank's own MKS SERVO42C stepper drivers surfaced several real bugs in the upstream dosing math and driver protocol -- most seriously, a low-flow calibration curve that could extrapolate the wrong direction and silently skip the runtime-shortening safety check meant for near-zero doses, and an RPM-snap case where the driver's achievable minimum speed was used without rescaling the dose runtime to match, both of which meant a small requested dose could silently run closer to a full-size one. Also fixed a UART CRC check that summed decoded values instead of the actual transmitted bytes (rejecting valid replies for any multi-byte field), and an OTA versioning bug where a build with an unset version tag could make a real firmware fix silently fail to take effect even after a "successful" update. Full writeup of all 11 fixes: Firmware Changes. Rather than a fixed daily total, each pump's per-dose amount is recalculated from an actual measured reading against target -- e.g. calcium's current schedule holds roughly 289mL/day of a CaCl2·2H2O solution (130.55g/L) split into 46 small doses rather than a few large ones, keeping the swing between doses small since large single dumps of calcium/alkalinity risk a local precipitation spike. Magnesium runs the same way, dosing a Tropic Marin Bio-Magnesium stock solution. Alkalinity is buffered separately with a NaOH solution (74g/L). Firmware updates over the air rather than needing physical access -- the build hosted here (version v1.1.15-manual-20260920073258-manual-dose-indicator, sha256 1914ba1a...4215 in the manifest below) is built from the source tree with all the fixes above already applied, verified by matching that same sha256 against the local build output before publishing it -- not just documented fixes sitting unused in a checkout somewhere: micropython.bin, bootloader.bin, partition-table.bin, manifest.

Current dosing (recalculated as measurements change, not fixed)
ElementSolutionPer doseDoses/dayTotal/day
CalciumCaCl2·2H2O, 130.55g/L6.29 mL46~289 mL
MagnesiumTropic Marin Bio-Magnesium stock3.08 mL46~142 mL
Ionic balanceTropic Marin Part C, 47.4g/L6 mL40~240 mL
AlkalinityNaOH, 74g/L1 mL4343 mL

Lighting

2x ATI Straton Flex 153 fixtures (150cm), driven by a Python script rather than the manufacturer app's own static timeline editor. Intensity follows a real solar-elevation curve computed for a reference Coral Triangle reef (Raja Ampat, Indonesia -- consistent ~12h day length, no daylight-saving shifts), then time-shifted so sunrise and sunset land at sensible local hours rather than Indonesia's own clock. On top of that:

  • Live cloud cover from that same reef's real weather forecast dims the tank on overcast days, floored so a fully overcast day doesn't black it out -- real diffuse light still reaches a reef underwater too.
  • A moon-phase-driven night cycle replaces a flat "lights off" floor, brighter near full moon and dimmer near new moon, with a printed notice during the commonly-cited post-full-moon window some SPS species use as a spawning cue.
  • Spectrum blends smoothly through the day -- no discrete preset jumps anywhere, including the moon-to-daylight transition -- built around the ~470nm coral fluorescence excitation peak reported in the coral photobiology literature (Bay et al. 2010), with extra UV/violet at twilight eased back at midday.
  • Hard-capped at 65% of the fixtures' maximum output, and the whole schedule recomputes every 15 minutes via cron rather than running a fixed program once a day.

10.10.3.60 last updated 2026-09-20T09:15:13+00:00
10.10.3.84 last updated 2026-09-20T09:15:30+00:00

Today's Lighting Curve

The planned 0-65% intensity schedule for today, recomputed every 15 minutes from real solar elevation, the live cloud forecast, and moon phase -- this is what's actually queued up to run, not a measurement (see the PAR section below for that). Same curve drives both fixtures.

2026-09-20:
-2.9%19.5%41.9%00:0023:59Intensity

Measured Light Output (PAR)

Neither fixture has an actual photometric sensor. What's below instead comes from the fixture's own real measurement of LED driver current draw, run through ATI's own factory-calibrated current-to-PAR conversion at four fixed distances -- the exact same calculation the manufacturer's own app displays in its status bar, traced out of its source and pulled here directly. Treat it as a real, continuously-logged proxy for output good enough to catch genuine trends, not a lab-grade PUR reading: it's a per-single-lamp figure (ATI's own tooltip warns combined output from both fixtures together is "significantly higher"), and it's calibrated against ATI's factory spectrum rather than this tank's custom channel mix.

Latest reading per fixture
FixtureDriver drawEst. PAR @30cm@45cm@60cm@75cm
10.10.3.60 68 W 204 143 102 85
10.10.3.84 64 W 192 134 96 80

Estimated PAR @60cm, both fixtures, last 48 hours:
0.5 PAR55 PAR109.5 PAR2026-09-192026-09-20Fixture .60Fixture .84

The Tank