Project Details
This project is a precision liquid dosing controller built around an ESP32 and multiple stepper-driven peristaltic pumps. The main idea was to build something more capable than a simple timer-based doser: a controller that can deliver measured doses, track what actually happened, expose live status over the network, and stay practical to use in real installations.
It is meant as a general-purpose dosing platform, but aquarium automation is one of the clearest real-world use cases. In that setup, separate channels can be used for alkalinity, calcium, magnesium, trace elements, or fertilizer, with each channel calibrated and scheduled independently. The same architecture also fits hydroponics, small lab setups, and other DIY fluid-handling systems where repeatability matters.
Hardware
At the core is an ESP32 running custom ESP-IDF firmware. The controller is designed for multiple pump channels, with each pump driven by a stepper motor rather than a basic DC motor. That makes it possible to control motion more predictably and build dosing around calibration and measured flow instead of rough timing assumptions.
The current hardware target assumes 16 MB flash, with enough room for two OTA firmware slots, the embedded web UI, and a dedicated history partition. The system can also support reduced configurations for smaller flash targets, but the main development target is the roomier layout because it leaves space for the interface, telemetry, and update workflow without squeezing the firmware too hard.
The board-level configuration includes motor-channel mapping, UART pin assignments, I2C devices, GPIO, and ADC configuration. Optional external RTC and EEPROM or FRAM support are included for better timekeeping and more robust persistence across resets or power loss. When external persistent storage is present, it is used for runtime-related backups more comfortably than relying on flash alone.
Pump Control And Safety Model
Each channel is treated as a configurable dosing pump with manual run support, scheduled run support, calibration data, tank-volume tracking, runtime history, and safety limits. The firmware supports both direct manual dosing and automatic dosing modes that depend on valid calibration data.
A key design choice is that the controller does not blindly resume an interrupted pump run after a reset or power loss. Persisted counters and state are restored, but an in-progress dose is not automatically continued. That behavior is intentional: for dosing applications, a missed partial dose is usually safer than an accidental overdose caused by uncertain restart conditions.
Safety limits can be applied per pump and globally. These include per-run, per-hour, and per-day limits, as well as an overall daily total. If a request would exceed those limits, or if an automatic mode lacks valid calibration data, the firmware rejects the run instead of guessing.
Driver Configuration
The stepper driver layer is based on a shared TMC2209 profile applied to all active pump channels. That profile is stored in board configuration and can be read and updated over the API. Instead of hiding the driver behind fixed hardcoded values, the project exposes the useful configuration points so the system can be tuned for real hardware.
The TMC2209 profile includes:
- sense resistor value
- run current
- hold current percentage
- StealthChop enable and threshold
- CoolStep enable and threshold
- StallGuard and CoolStep tuning fields
A fresh board configuration uses a conservative baseline profile:
{
"rsense_milliohm": 220,
"run_current_ma": 400,
"hold_current_percent": 10,
"stealthchop_enabled": true,
"stealthchop_threshold_rpm": 0,
"coolstep_enabled": false,
"coolstep_threshold_rpm": 0,
"coolstep_sg_threshold": 45,
"coolstep_semin": 4,
"coolstep_semax": 2,
"coolstep_seup": 1,
"coolstep_sedn": 1,
"coolstep_seimin": 0
}
Current calculation...
Read more »
Alexey Volkov
LED Lightwell
Jean-Philippe Jodoin
RT-Thread IoT OS