Create a custom actuator type
Author a new FixoActuatorType in the Studio
The four built-in actuator types — RC servo, DC motor, stepper motor, relay — cover most cases, but not all. This guide walks through authoring a new FixoActuatorType for hardware that doesn't fit the built-ins (e.g. a brushless ESC with a calibration pulse, a servo with an unusual pulse range, a stepper driver that takes a pre-divided clock). The result is a fixo.json plus .hpp pair the Fixo Studio picks up automatically.
Prefer duplicate-to-edit
The fastest path is Duplicate an existing built-in, rename, edit. The Studio's Actuator Type Manager has the button. The walkthrough below covers the field-by-field choices either way.
Before you start
You need:
- A working OctoMY™ install with the Fixo Studio reachable
- Familiarity with C++ templates — actuator type sources are header-only template specialisations
- An idea of the actuator's pin layout (how many pins, what each is for) and wire encoding (how its value is packed into bytes)
Step 1: Open the Actuator Type Manager
- Open the Fixo Studio activity (Hub utilities or Agent configuration menu).
- Pick the Hardware group.
- Open Actuator Type Manager. The list shows built-in types greyed out and any custom ones you've already authored.
Step 2: Duplicate the closest built-in (recommended)
- Select the built-in that's nearest to what you want — e.g. for a brushless ESC, start from
dc_motor(PWM-driven, has a direction option you'll repurpose for arming). - Click Duplicate. A new entry appears named
Copy of dc_motor. - Click Rename. Use kebab-case, e.g.
bldc-esc. - Double-click the new entry to open the type editor.
If you'd rather start blank, click New instead and skip to Step 3.
Step 3: Fill in the metadata
In the type editor's metadata form:
| Field | Example | Notes |
|---|---|---|
| Type id | bldc-esc |
Stable kebab-case id; what other JSON references |
| Title | "BLDC ESC" | Human-readable; shows in dropdowns |
| Description | "Brushless ESC with arming pulse" | One-line; shows in tooltips |
| Main header | bldc-esc.hpp |
The .hpp the firmware generator includes |
The Studio creates the file under <personality>/fixo/actuator-types/bldc-esc/ automatically.
Step 4: Set pin count and pin purposes
Below the metadata form:
| Field | Description |
|---|---|
| Pin count | How many physical pins one instance occupies |
| Pin purposes | One label per pin; pinCount entries |
Examples:
| Actuator | pinCount |
pinPurposes |
|---|---|---|
| RC servo | 1 | ["pwm"] |
| DC motor (H-bridge) | 2 | ["pwm", "direction"] |
| Brushless ESC (one-line) | 1 | ["pwm"] |
| Stepper (step/dir) | 2 | ["step", "direction"] |
The names are conventions; the C++ template you write knows which name maps to which pin role.
Step 5: Define the wire value representation
The wire valueRep tells the numex protocol how to pack this actuator's value into bytes:
| Field | Example | Description |
|---|---|---|
totalBits |
16 | Total bits used on the wire |
fractionalBits |
0 | For fixed-point; 0 = integer |
isSigned |
false |
Two's-complement when true |
isFloat |
false |
IEEE-754 when true (16, 32, or 64 bits only) |
For an RC servo with 500–2500 µs pulse range you'd typically use {16, 0, false, false} — a uint16 covers it with room to spare.
Step 6: Write the C++ template source
The C++ source editor uses WidgetCodeEditor with syntax highlighting, line numbers, auto-indent on Enter, Tab indentation, and Ctrl+Shift+Up/Down to move lines. The minimal shape for an actuator template:
#pragma once
#include <fixo/board/Board.hpp>
#include <fixo/types/ValueRep.hpp>
namespace fixo {
template<typename Board, uint8_t PinPwm>
struct BldcEsc {
static constexpr ValueRep valueRep = {16, 0, false, false};
static void setup() {
Board::pinModePwm(PinPwm);
// arming pulse — 1 ms for ~3 seconds
Board::pwmWriteMicros(PinPwm, 1000);
}
/// value: 0..1 normalised throttle
static void write(double value) {
if (value < 0) value = 0;
if (value > 1) value = 1;
Board::pwmWriteMicros(PinPwm, 1000 + value * 1000);
}
};
} // namespace fixo
Key conventions:
- Header-only (no
.cpp). The firmware generator emits#include "your-type.hpp"and instantiates the template with the preset's pin assignments. - Take the board as a template parameter so the same template compiles for both Uno and Mega —
Boardprovides the HAL primitives (pinModePwm,pwmWriteMicros, etc.). - Take pin numbers as
uint8_ttemplate parameters — this lets the optimiser inline pin access. - Expose
valueRepas astatic constexprmatching the JSON. - Implement at least
setup()andwrite(double).tick()is optional for actuators that need periodic updates.
Live errors
The type editor compiles your source after each pause with the LLVM diagnostic engine running against a small synthetic preset. Errors and warnings appear in the panel under the editor; click a row to jump to the offending line. Lines with diagnostics get a coloured gutter mark in the source editor.
The synthetic preset is the smallest valid firmware that uses your type
— one board (uno), one stanza, and one actuator of the type you're
editing. You don't need an open preset to get diagnostics; the generated
source mirrors what would land in a real firmware build.
If a diagnostic doesn't match anything in your source, the most common causes are a missing pin-purpose declaration or an out-of-range input range. Both are visible in the synthesized preset and surface as errors before the editor's source even gets reached.
Step 7: Save and use
- Click Save. The Studio writes the JSON and source to
<personality>/fixo/actuator-types/bldc-esc/and reloadsFixoLibraryso the type appears in the registry. - Open a preset in the Preset Editor.
- Add an actuator; in the Type dropdown your new
bldc-escis now an option alongside the built-ins. - Build — the firmware generator will pick up your
bldc-esc.hppautomatically.
If the firmware build fails with a clang error, check the Build & Inject view's diagnostics. The most common issues:
| Symptom | Cause |
|---|---|
unknown member ‘pwmWriteMicros’ |
The board template doesn't expose that primitive — check your target board's HAL header |
| Loud type errors with template names | Your Board parameter doesn't match the boards the generator instantiates with — make sure your template parameters match the convention |
| Linker error about a symbol | You wrote a .cpp instead of header-only — move the implementation to the header |
Step 8: Share the type (optional)
The whole <personality>/fixo/actuator-types/bldc-esc/ folder is portable. Zip it and copy it to another node, or use Export in the Actuator Type Manager to write a single file the destination can Import. See Share a preset between nodes.
See also
- Fixo Data Model — FixoActuatorType — what the fields mean
fixo.jsonschema — actuator-type — the file-format reference- Create a custom lobe type — sister how-to with placement + output ports
- Fixo Studio — manager and editor surface