Skip to content
okhsunrogPublic

About

Field-Oriented Control (FOC) motor firmware for STM32, in Rust + Embassy

Topics

Resources

Stars

25 stars

Watchers

2 watching

Forks

Latest commit

 

History

635 Commits

Folders and files

Repository files navigation

OxiFOC

Field-Oriented Control (FOC) firmware for STM32 motor controllers, written in Rust with Embassy. Device-host communication uses ergot.

Core Architecture (oxifoc-core)

All FOC algorithms and motor control logic live in oxifoc-core — a no_std library with no hardware dependencies. Platform crates provide trait implementations for their specific hardware (ADC, PWM, sensors).

Trait Abstraction

graph TD
    FocDriver["<b>FocDriver&lt;P, C, Ph, S&gt;</b><br/>Integrates everything<br/>Mode management · Current limiting"]

    FocDriver --> PhasePwm["<b>PhasePwm</b><br/>set_duties · disable · enable<br/>set_phase_states (six-step)"]
    FocDriver --> CurrentSensor["<b>CurrentSensor</b><br/>read_currents · calibrate<br/>update_duties (reconstruction)"]
    FocDriver --> PhaseProvider["<b>PhaseProvider</b><br/>get() → angle, velocity<br/>injection() → HFI carrier<br/>update(vαβ, iαβ, dt)"]
    FocDriver --> SinCos["<b>SinCos</b><br/>sin_cos(θ) → (sin, cos)<br/>LibmSinCos · FastSinCos · CordicSinCos"]

    FocDriver --> FocController["<b>FocController&lt;M, S&gt;</b><br/>Clarke · Park · PI · Inv. Park<br/>Dead time comp · Voltage clamping"]
    FocController --> Modulator["<b>Modulator</b><br/>to_duties(vα, vβ) → [u16; 3]<br/>SvpwmModulator"]

    PhaseProvider --> PhaseManager["<b>PhaseManager&lt;H, E&gt;</b><br/>Source selection · Health tracking<br/>Observer fallback · Open-loop override"]
    PhaseManager --> AngleSensor["<b>AngleSensor</b><br/>HallSensor · Encoder · NoSensor"]
    PhaseManager --> Observer["<b>Observer slot</b><br/>BackEmfObserver"]
    PhaseManager --> Hfi["<b>HFI slot</b><br/>HfiObserver<br/>carrier + polarity probe"]
Loading

Platform crates implement PhasePwm (TIM1 complementary PWM), CurrentSensor (shunt ADC reading), and SinCos (CORDIC hardware or software libm). Everything else is shared.

Phase Source Selection

PhaseManager supports multiple angle estimation strategies with runtime switching (host command cmd/phase_source; the active source is reported back via slow telemetry). Both software estimators run concurrently in dedicated slots and are armed automatically from stored motor parameters at boot:

Source Use Case
Hall Direct Hall sensor angle
Encoder Incremental encoder
Observer Back-EMF sensorless (high speed)
Hfi High-frequency injection sensorless (zero/low speed)
HallToObserver Hall at low speed, velocity-blended crossover to observer, automatic fallback on Hall failure
HfiToObserver HFI at standstill, velocity-blended crossover to observer
Manual / OpenLoop Calibration and detection

Motor Detection

Automated parameter measurement, platform-agnostic via DetectionHardware trait:

graph LR
    R["<b>Resistance</b><br/>2-point differential<br/>R = ΔV/ΔI (MESC-style)"] --> L["<b>Inductance</b><br/>Rotating HFI + FFT<br/>Separates Ld/Lq via 2nd harmonic"]
    L --> F["<b>Flux Linkage</b><br/>Spin-down back-EMF<br/>Driven fallback: e⃗ = V⃗ − R·i⃗ − jωL·i⃗"]
    F --> PI["<b>PI Auto-tune</b><br/>Kp = L·ω_bw<br/>Ki = R·ω_bw"]
    R --> Hall["<b>Hall Calibration</b><br/>Electrical revolution sweep<br/>State→angle mapping"]
Loading

Each step uses conservative PI gains (DETECTION_PI_KP/KI) delivered via ControlMode::OpenLoop { pi_gains }. Detection accuracy validated against 10 simulated motors (detection_report example).

Virtual Motor

VirtualMotor simulates a PMSM electrically and mechanically (R, Ld, Lq, flux linkage, inertia, friction). Combined with FocController, it enables closed-loop testing of the full detection pipeline and FOC control without hardware.

cargo run -p oxifoc-core --example detection_report --features virtual-motor,std

Control Modes

enum ControlMode {
    Stopped,                        // PWM disabled
    CurrentControl { iq, id },      // Torque/field control
    OpenLoop { angle, current, velocity, pi_gains },  // Detection/calibration
    DirectVoltage { vd, vq, angle },// Bypass PI (HFI measurement)
    Coast,                          // All FETs off (flux measurement)
    SixStep { duty },               // Trapezoidal (bringup)
    VelocityControl, PositionControl, // TODO
}

Fast Telemetry

Lock-free ISR → host streaming via bbqueue:

ISR (20kHz) → decimation (atomic period) → bbqueue (2KB) → async drain → ergot topic → host

46 bytes/sample (ia/ib/ic/id/iq/vd/vq/angle/erpm/duty/hall/seq). Zero overhead when disabled. Overflow drops samples silently.

Network Architecture

All devices communicate via ergot — a lightweight embedded networking protocol with automatic routing and address assignment.

Every motor controller runs as a Router — when standalone it acts as a root, when connected to another controller it becomes a bridge. Host apps and peripherals connect as Edge devices. This means identical firmware regardless of network topology.

Motor Controller (Root Router)
├── PC ─────────────────── Edge (USB / UART / RTT)
├── Secondary Motor Ctrl ─ Bridge Router (CAN FD)
│   └── ...               (its own edge devices)
├── BMS ──────────────── Edge (CAN FD)
└── ESP32-C6 ──────────── Bridge Router (UART + BLE)
    ├── ESK8 Remote ───── Edge (BLE, ESP32-C6)
    └── Android App ───── Edge (BLE)

Roles are determined by topology, not firmware — disconnect two controllers and each becomes its own root. The host app discovers and addresses all devices in the network automatically through the routing tree.

Hardware

Board MCU Current Sensing Communication Gate Driver
Cheap FOCer 2 STM32F405RG DRV8301 (10 V/V) USB + UART DRV8301 SPI
Flipsky VESC 6 MK5 STM32F405RG DRV8301 (20 V/V) USB + UART DRV8301 SPI
NUCLEO-G474RE + IHM08M1 STM32G474RE External op-amps USB + LPUART L6398

All platforms: 20 kHz center-aligned PWM, TIM1-triggered injected ADC, Hall polling via TIM6 (5 us, 7-read majority voting), persistent config in internal flash (sequential-storage + postcard).

Host Tools

GUI (oxifoc-host-slint) — Slint desktop app with GPU-accelerated real-time charts (WGPU). The Monitor offers Focus, Compare, Overview, and 2 × 2 layouts without scrolling the chart workspace. Focus and Compare let you choose chart groups; the current chart can overlay any combination of Ia, Ib, Ic, Id, and Iq on a shared ampere axis. Click Focus or double-click a chart to enlarge it, then use Back or Esc to restore the previous layout. Use Pause/Resume on each chart, scroll/pinch or the on-plot buttons to zoom, drag to pan while paused, and hover for cursor measurements. Motor control, detection wizard, config read/write.

CLI (oxifoc-host-cli) — Command-line monitor, motor control, detection.

Virtual device (oxifoc-virtual) — Simulated motor controller over TCP/UDP. Host tools connect exactly as to real hardware.

Transports: Serial (UART VCP), RTT (probe-rs), TCP (virtual), UDP (virtual), USB (nusb).

Building

just check                # fmt + clippy + tests (workspace + all device firmware)
just build-f405-cf2       # Build Cheap FOCer 2 firmware
just flash-f405-cf2       # Build and flash Cheap FOCer 2 via probe-rs
just build-f405-vesc6-mk5 # Build Mini V6 MK5 firmware
just flash-f405-vesc6-mk5 # Build and flash Mini V6 MK5 via probe-rs
just gui                  # Run Slint GUI
just cli -- list          # Run CLI

The two F405 variants use separate artifact directories: oxifoc-f405/target/cf2 and oxifoc-f405/target/vesc6-mk5.

Device firmware requires Rust nightly (thumbv7em-none-eabihf). Host crates build with stable Rust.

Testing

cargo test --workspace                              # Host tests
cargo test -p oxifoc-core --features virtual-motor  # Virtual motor + detection
cd tests/stm32f405 && cargo test                    # On-target (requires hardware)

Development Status

Known gaps and planned work are tracked in docs/TODO.md; safety-layer roadmap in docs/safety.md.

License

Licensed under either of:

at your option.

About

Field-Oriented Control (FOC) motor firmware for STM32, in Rust + Embassy

Topics

Resources

Stars

25 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages