A neutral, technical overview of how the cocktail machine’s controller is structured.
The firmware runs on an ESP32 and is written in Rust (based on the ESP-IDF framework, i.e. with the standard library). It performs two very different tasks at the same time: serving a web interface and clocking the stepper motors precisely. So that the two do not interfere with each other, the tasks are split across the ESP32’s two processor cores.
Core 0 takes care of Wi-Fi and the web server, core 1 exclusively of the motors. This keeps the step pulses evenly timed, even while someone is loading the web interface.
The web server and the motor control do not share any memory directly; they communicate via two clearly separated paths:
Sender), the motor control takes them out (Receiver) and processes them in order. A slow web page can therefore never disturb the motor timing.mutex that the web server reads for the display.The entire interface is a single HTML file with embedded CSS and JavaScript. It is baked into the firmware at compile time (include_str!) and served when / is requested – so there is no separate web space and no build pipeline for the front end. The JavaScript talks exclusively to the firmware’s small HTTP interface, e.g.:
Everything that is taught in – slot positions, heights, times and the drinks – is serialised as JSON (with serde) and stored in the NVS flash of the ESP32. It therefore survives power cuts and restarts and is identical from every device on the Wi-Fi. Received values are checked against fixed limits and clamped before saving, so that no faulty input can create dangerous states.
A drink is a list of steps “slot × portions”. When it is triggered, the firmware turns this into a concrete command sequence for the two axes – roughly:
(if necessary) home Z → home X →
for each ingredient: X to slot → Sync → per portion: Z up, hold, short return stroke (or pump on) → Sync →
at the end: Z down → homing run → (optional dispensing position).
The Syncpoints make sure that the axes wait for each other at the right moments – for example, so that nothing is ever dispensed while the carriage is still moving.
Rust (Edition 2021) ESP-IDF (std) esp-idf-svc embedded-svc serde / serde_json anyhow HTML / CSS / vanilla JS
| File | Task |
|---|---|
src/main.rs | Start-up, Wi-Fi, web server with all endpoints, pin assignment, loading the configuration |
src/servo.rs | Motor control: step pulses, state machine, safety logic, pump |
src/settings.rs | Data model of the configuration and the blueprint “recipe → command sequence” |
src/config.rs | Central limits: travel distances, speed limits, recipe limits |
src/servo-control-migrated.html | The embedded web interface |