e-foc

April 13, 2026 · View on GitHub

Quality Gate Status Coverage Duplicated Lines (%) Vulnerabilities

e-foc

An embedded motor control application implementing Field-Oriented Control (FOC) for BLDC and PMSM motors with strict real-time and memory constraints. Built for deterministic execution on resource-constrained microcontrollers.

Overview

This project provides a production-ready motor control implementation designed for embedded systems with no heap allocation, deterministic execution, and minimal memory footprint. It demonstrates FOC algorithms with complete hardware integration for ST and TI microcontrollers.

Features

Core Capabilities

  • Field-Oriented Control (FOC): Complete implementation for BLDC and PMSM motors
  • Space Vector Modulation (SVM): Efficient PWM generation
  • PID Control: Anti-windup implementations for current and velocity loops
  • Sensored Control: Encoder and Hall sensor feedback integration
  • Auto-Tuning: Resistance and Inductance estimation
  • Real-Time Performance: Deterministic execution with no heap allocation

Embedded Constraints

  • Zero Heap Allocation: All memory statically allocated at compile-time
  • Fixed Memory Footprint: Uses infra::BoundedVector, infra::BoundedString instead of standard containers
  • Minimal Stack Usage: No recursion, predictable call depths
  • Platform Abstraction: PlatformFactory interface with ST and TI implementations

Simulation & Testing

  • C++ Simulator: Mathematical models for motor evaluation and curve plotting
  • Unit Tests: Comprehensive GoogleTest coverage for control algorithms
  • Hardware-in-the-Loop Ready: Mockable interfaces for testability

Getting Started

Prerequisites

  • CMake 3.24 or later
  • Compatible toolchain for embedded targets (ARM GCC)
  • Development board: EK-TM4C1294XL (TI) or STM32F407G-DISC1 (ST)
  • Basic understanding of motor control and embedded systems

Quick Start

  1. Clone the repository with submodules
git clone --recursive https://github.com/embedded-pro/e-foc.git
cd e-foc
  1. Build for host simulation
cmake --preset host
cmake --build --preset host-Debug
  1. Run tests
ctest --preset host
  1. Build for embedded target (example: TI EK-TM4C1294XL)
cmake --preset EK-TM4C1294XL
cmake --build --preset EK-TM4C1294XL-Debug

Project Structure

e-foc/
├── core/                            # FOC library code (no application entry points)
│   ├── foc/                         # Field-Oriented Control
│   │   ├── interfaces/              # Abstract FOC interfaces (Foc.hpp, Driver.hpp, Units.hpp)
│   │   ├── implementations/         # Clarke/Park, SVM, torque/speed/position loops, Runner
│   │   └── instantiations/          # Concrete wiring of FOC components
│   ├── platform_abstraction/        # Platform abstraction interfaces and shared adapters
│   │   ├── PlatformFactory.hpp      # Abstract factory for peripherals
│   │   ├── AdcPhaseCurrentMeasurement.hpp
│   │   ├── CanBusAdapter.hpp
│   │   ├── QuadratureEncoderDecorator.hpp
│   │   └── MotorFieldOrientedControllerAdapter.hpp
│   ├── services/                    # Application-level services
│   │   ├── alignment/               # Motor alignment and offset detection
│   │   ├── cli/                     # Command-line interface service
│   │   ├── electrical_system_ident/ # Resistance/inductance estimation
│   │   ├── mechanical_system_ident/ # Friction and inertia estimation
│   │   └── non_volatile_memory/     # NVM persistence service
│   └── state_machine/               # FOC motor lifecycle state machine (Idle/Calibrating/Ready/Enabled/Fault)
├── integration_tests/               # BDD integration tests (Cucumber/Gherkin)
│   ├── features/                    # Gherkin .feature files
│   ├── steps/                       # Step definitions
│   ├── hooks/                       # Before/After scenario hooks
│   ├── main/                        # Test executable entry point
│   └── support/                     # Fixture, mocks, and bridge
├── targets/                         # Application entry points and platform implementations
│   ├── sync_foc_sensored/           # Synchronous FOC with encoder feedback
│   ├── hardware_test/               # Hardware validation application
│   └── platform_implementations/   # Platform-specific PlatformFactory implementations
│       ├── host/                    # Host simulation (GoogleTest stubs/mocks)
│       ├── st/                      # STM32 platform implementation
│       └── ti/                      # TI Tiva C platform implementation
├── tools/                           # Host-side developer tools
│   ├── simulator/                   # C++ motor simulators (torque, speed, position control)
│   └── can_commander/               # CAN bus command interface tool
├── infra/                           # Infrastructure submodules
│   ├── embedded-infra-lib/          # Bounded containers, build helpers, toolchain CMake
│   ├── numerical-toolbox/           # PID, filters, fixed-point algorithms
│   ├── can-lite/                    # CAN protocol library
│   └── hal/                         # Hardware abstraction layer (ST, TI)
├── documentation/                   # Architecture, design, theory, and requirements docs
└── build/                           # Build artifacts (generated, not committed)

Key Design Principles

Memory Management

  • No Heap Allocation: All memory is statically allocated at compile-time
  • Bounded Containers: Uses infra::BoundedVector, infra::BoundedString instead of STL containers
  • Fixed Memory Footprint: Predictable RAM usage for resource-constrained systems

Real-Time Performance

  • Deterministic Execution: No dynamic allocation or unbounded loops in control paths
  • Minimal Branching: Optimized control loops for consistent timing
  • ISR-Safe Design: Interrupt service routines avoid virtual calls and complex operations

Architecture

  • Dependency Injection: Constructor injection for testability and flexibility
  • Platform Abstraction: Clean separation between application logic and hardware
  • Interface-Driven Design: Pure virtual interfaces enable mocking and testing

How to Run the Simulator

The simulator includes a Qt-based GUI for real-time visualization. Since the development environment runs inside a Dev Container, an X server on the host machine is required to display the GUI.

Host Setup

Windows

  1. Install VcXsrv (free) or X410 from the Microsoft Store.
  2. Launch VcXsrv with the following settings:
    • Multiple windows
    • Start no client
    • Disable access control (checked)
  3. Open the project in VS Code and reopen in the Dev Container.

Linux

  1. Allow Docker containers to access your X server:
    xhost +local:docker
    
  2. Open the project in VS Code and reopen in the Dev Container.

Note: The Dev Container sets DISPLAY=host.docker.internal:0.0 to forward GUI windows over TCP. On Linux, if you prefer Unix socket forwarding, you can override DISPLAY to :0 inside the container and add a bind mount for /tmp/.X11-unix.

Build & Run

Inside the Dev Container terminal:

cmake --preset host
cmake --build --preset host-Debug

Run the speed control simulator:

./build/host/bin/Debug/e_foc.tool.simulator.speed_control

Run the torque control simulator:

./build/host/bin/Debug/e_foc.tool.simulator.torque_control

Run with custom parameters (example):

./build/host/bin/Debug/e_foc.tool.simulator.speed_control --help

Troubleshooting

ProblemSolution
cannot open displayEnsure the X server is running on the host and "Disable access control" is enabled
Black window or no renderingSet LIBGL_ALWAYS_INDIRECT=1 (already configured in the Dev Container)
Windows firewall blocks displayAllow VcXsrv (vcxsrv.exe) through the Windows firewall for private networks

Documentation

Architecture

DocumentDescription
System ArchitectureHigh-level system architecture and component relationships

Design

DocumentDescription
FOC TransformsClarke and Park transform design
FOC Torque ControlTorque (current) control loop design
FOC Speed ControlSpeed control loop design
FOC Position ControlPosition control loop design
Alignment ServiceMotor alignment and offset detection service
CLI ServiceCommand-line interface service
Electrical Identification ServiceResistance and inductance estimation service
Mechanical Identification ServiceFriction and inertia estimation service
NVM ServiceNon-volatile memory persistence service
Integration Testing DesignFixture design, calibration flow, CAN bridge

Requirements

DocumentDescription
State Machine RequirementsLifecycle state transitions and NVM boot behaviour
FOC Torque Controller RequirementsTorque control loop functional requirements
CAN-to-State-Machine Integration RequirementsCAN command to state machine mapping requirements

Theory

DocumentDescription
FOC TheoryField-Oriented Control theory and control block diagrams
Motor AlignmentMotor alignment and offset detection theory
Resistance & Inductance EstimationParameter estimation theory
Friction & Inertia EstimationMechanical parameter estimation theory

Performance

DocumentDescription
Performance Optimization GuideHigh-performance embedded code, assembly analysis, cycle budgets

Development References

DocumentDescription
Copilot / Agent InstructionsDevelopment guidelines, patterns, and constraints
embedded-infra-libBounded containers and infrastructure library reference
numerical-toolboxReusable numerical algorithms (PID, filters, fixed-point)

Contributing

We welcome contributions! Please follow these guidelines:

Development Workflow

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Follow the coding standards in copilot-instructions.md.
  4. Ensure all tests pass
  5. Update CHANGELOG.md according to release-please conventions
  6. Commit your changes (git commit -m 'Add some AmazingFeature')
  7. Push to the branch (git push origin feature/AmazingFeature)
  8. Open a Pull Request

Critical Guidelines

  • NO heap allocation (new, delete, malloc, free)
  • NO standard containers (use infra::Bounded* alternatives)
  • Use fixed-size types (uint8_t, int32_t, etc.)
  • Mark all non-mutating methods as const
  • Write unit tests for new functionality
  • Follow .clang-format rules for code formatting

License

This project is licensed under the MIT License - see the LICENSE file for details.