Firmware for Zubax CF1 "Babel" implementing the ACTBAC (AmpDrive Control and Telemetry Bridge for Analog Controllers) concept from the Zubax Forum.
Discovers Zubax Telega ESCs on CAN bus, auto-configures registers, and outputs telemetry as PWM signals.
- PnP Node Allocation — assigns CAN node IDs to anonymous devices
- Auto-Discovery — detects Telega controllers via heartbeat
- Auto-Configuration — writes and verifies register settings
- Telemetry Output — force, velocity, voltage, current as PWM
- LED Status — visual feedback through blink patterns
┌───────────────────────────────────────────────────────────────────────────────┐
│ DISCOVERY │
│ │
│ ┌──────────┐ heartbeat ┌───────┐ tick ┌──────────┐ │
│ │ Discover │ ────────────► │ Found │ ────────► │ PreCheck │ │
│ └──────────┘ └───────┘ └──────────┘ │
│ ▲ │ │
│ │ timeout/blacklist │ read register │
│ │ ▼ │
│ ┌─────────────┐ tick ┌───────────────────────────────────┐ │
│ │ WrongDevice │ ◄───────── │ WaitPreCheckAck │ │
│ └─────────────┘ mismatch └───────────────────────────────────┘ │
│ │ │
│ ack ok ────────┴──────── all checked │
│ (next reg) │ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────┐ needs_config=false │
│ │ PreCheck │ │ │
│ └──────────┘ │ │
└────────────────────────────────┬──────────────────────┬───────────────────────┘
│ needs_config=true │
▼ │
┌────────────────────────────────────────────────────┐ │
│ CONFIGURATION │ │
│ │ │
│ ┌───────────┐ write reg ┌──────────────────┐ │ │
│ │ Configure │ ───────────► │ WaitConfigureAck │ │ │
│ └───────────┘ └──────────────────┘ │ │
│ ▲ │ │ │
│ │ ack ok (next) │ all done │ │
│ └────────────────────────────┤ │ │
│ ▼ │ │
│ ┌───────────────┐ │ │
│ │ ConfigureDone │ │ │
│ └───────────────┘ │ │
│ │ restart │ │
└─────────────────────────────────────┼─────────────┘ │
▼ │
┌─────────────────────────────────────────────────┐ │
│ REBOOT & VERIFY │ │
│ │ │
│ ┌────────────┐ 3 heartbeats ┌────────┐ │ │
│ │ WaitReboot │ ─────────────► │ Ensure │ │ │
│ └────────────┘ └────────┘ │ │
│ │ │ │
│ read reg │ │ │
│ ▼ │ │
│ ┌───────────────┐ │ │
│ │ WaitEnsureAck │ │ │
│ └───────────────┘ │ │
│ │ │ │
│ ack ok (next) │ all ok │ │
│ ┌───────┴───────┐ │ │
│ ▼ │ │ │
│ ┌────────┐ │ │ │
│ │ Ensure │ │ │ │
│ └────────┘ │ │ │
└──────────────────────────────────────────┼─────┘ │
│ │
▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ OPERATIONAL │
│ │
│ ┌───────┐ control high ┌─────────┐ 60s elapsed ┌──────┐ │
│ │ Ready │ ──────────────► │ Control │ ────────────► │ Done │ │
│ └───────┘ └─────────┘ └──────┘ │
│ ▲ │ │ │
│ │ control released │ control released │ │
│ └──────────────────────────┴────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Note: Heartbeat timeout in any state (except Discover, WrongDevice, WaitReboot)
returns to Discover. ACK timeout returns to Discover.
| State | Bootloader LED | Traffic LED |
|---|---|---|
| Discover | Fast alternating (200ms) | Alternating |
| WrongDevice | Fast sync (100ms) | Synced |
| Configuring | Double-blink (150ms) | Off |
| Ready | Slow heartbeat (1s) | Pulse on telemetry |
| Control | Very fast (50ms) | Pulse on telemetry |
| Done | Very fast (50ms) | Constant on |
| Parameter | Value | Description |
|---|---|---|
HEARTBEAT_TIMEOUT_US |
5s | Node considered lost if no heartbeat |
ACK_TIMEOUT_US |
2s | Register read/write response timeout |
BLACKLIST_TIMEOUT_US |
5s | Ignore wrong device for this duration |
REBOOT_TIMEOUT_US |
30s | Max wait for node to reboot |
REBOOT_HEARTBEAT_COUNT |
3 | Heartbeats to confirm reboot complete |
CONTROL_DURATION_US |
60s | Torque ramp duration before Done |
CONTROL_TICK_INTERVAL_US |
100ms | Rate limit for torque commands |
| Parameter | Value | Description |
|---|---|---|
NODE_ID |
42 | This device's CAN node ID |
PNP_BASE_NODE_ID |
125 | Starting ID for PnP allocation |
| Port ID | Name | Purpose |
|---|---|---|
| 7509 | Heartbeat | Device discovery & liveness |
| 384 | Register Access | Config read/write responses |
| 100 | Dynamics | Motor force/velocity telemetry |
| 111 | Compact Feedback | Voltage/current telemetry |
| 8166 | PnP Allocation | Node ID requests |
| Port ID | Name | Purpose |
|---|---|---|
| 2001 | Setpoint Rat Torque | Motor torque commands |
| 435 | Execute Command | Node restart |
| 8166 | PnP Allocation | Node ID responses |
# Build with defmt logging via RTT
make dev
# Build and flash with RTT output
make run-dev# Build optimized binary without RTT
make prod
# Build and flash production binary
make flash-prod
# Check binary sizes
make size| Target | Description |
|---|---|
make dev |
Build development firmware with RTT logging |
make run-dev |
Build and flash dev firmware, show RTT output |
make prod |
Build production firmware (optimized, no RTT) |
make flash-prod |
Build and flash production firmware |
make size |
Show binary sizes for dev and prod builds |
make clean |
Clean build artifacts |
| Profile | Features | Use Case |
|---|---|---|
dev |
RTT logging, defmt, probe-panic | Development & debugging |
production |
No RTT, halt-on-panic | Field deployment |
- Rust nightly with
thumbv7em-none-eabihftarget probe-rsfor flashingarm-none-eabi-ldlinkermakefor build commands