Why Fixo (and not a runtime-configurable alternative)
How Fixo's compile-time approach replaces the older runtime path
OctoMY™ has one hardware controller today — Fixo — that compiles your robot's actuator/sensor configuration into purpose-built firmware via embedded LLVM/Clang. Earlier releases also shipped a runtime-configurable path called Fluxo (originally ArduMY) and a Servotor32 binding. Both were retired in 2026 in favour of the single Fixo path. This page explains the reasoning so the choice doesn't look arbitrary.
Did You Know?
The name Fixo comes from Latin fixus — fixed, fastened. The retired runtime-config sibling was named Fluxo (Latin fluxus, flowing), reflecting the static/dynamic split. After Fluxo's removal the duality is gone, but the Fixo name stuck because it accurately describes how the firmware is generated.
What Fixo does differently
Fixo's job is to take a FixoPreset (board + actuators + sensors + lobes) and produce a purpose-built firmware binary for that exact configuration. The C++ optimizer inlines every actuator type, pin number, and sensor descriptor as a compile-time constant; dead code paths are eliminated; the resulting binary contains zero runtime configuration overhead.
Agent
│
├─ FirmwareGenerator : preset → C++ source
├─ FirmwareCompiler : LLVM/Clang → AVR ELF + native .so
├─ FirmwareFlasher : ELF → MCU flash
│
└──serial──▶ Arduino (purpose-built firmware)
│
├─ All actuator types are compile-time constants
├─ All pin assignments are compile-time constants
├─ Lobe logic is compiled in
└─ Reports sensor values via numex
Configuration changes require a rebuild + reflash — but with the embedded LLVM toolchain that takes seconds, not the minutes a traditional cross-compiler workflow would. The flash cycle itself is around five seconds for a typical binary.
Why we removed the runtime-configurable path
Fluxo (the previous dynamic-config path) worked but carried inherent costs on the constrained MCUs OctoMY targets:
- Config parser added ≈ 2 KB of code that all robots paid for
- Dynamic arrays used heap allocations on devices with only 2 KB SRAM, risking fragmentation
- Runtime type dispatch for actuator operations needed indirect calls
- Serial protocol overhead repeated the configuration on every reconnect
- Lobe limitations — compile-time-optimized lobes (inverse kinematics, gait) couldn't run because everything had to be data-driven
Fixo flips all of those: every value is a compile-time constant, the optimizer collapses unused branches, and the generated source can host whatever C++ a lobe author wants to write.
Note
The runtime-configurable path made sense in a world where compiling C++ on a developer machine was a multi-step toolchain dance. Once we vendored LLVM/Clang into the Agent itself, that ergonomic cost disappeared: the user clicks Build and the firmware lands on the board seconds later. With the cost gone, the runtime-config drawbacks weren't worth carrying.
What's still shared
A lot of what was once described as "shared between Fixo and Fluxo" survived the removal:
| Component | Where it lives now |
|---|---|
| Numex wire protocol | libnumex/ — the value/command protocol talks to whatever firmware is running |
| Board definitions | libboard/ — pin capabilities, flash sizes |
| Flash protocols | libfirmware/ — STK500v1/v2/AVR109 flashing |
| Actuator and sensor types | libfixo/ — now part of the Fixo type registries |
A robot still uses exactly one controller. There's just no longer a "controller type" decision to make: it's Fixo.
Hardware support
| Feature | Status |
|---|---|
| Actuator control (servo, motor, stepper, relay) | Stable |
| Sensor reading (digital, analog, encoder, limit-switch, tachometer) | Stable |
| Identity lobe (passthrough) | Stable |
| Wheeled / tracked drive lobes | Stable |
| Hexapod gait, limb placement, hovering | Stable (templates ship in the studio) |
| AVR backend (ATmega328P, ATmega2560) | Stable |
| Native backend (host-side testing via dlopen) | Stable infrastructure; native compilation pipeline lands per spec |
| Stanza switching with conflict-disabling | Stable (Phase 7) |
| Live sensor readback on Remote | Stable (Phase 7) |