STM32-FOC: Field-Oriented Control for BLDC Motors

repository·master·Indexed 42 days ago

https://github.com/sirojudinmunir/stm32-foc

A low-level, from-scratch implementation of Field-Oriented Control (FOC) for BLDC motors on STM32F4 microcontrollers. Built using STM32 HAL/LL drivers and FreeRTOS, it supports torque, speed, and position control modes. Key features include Clarke & Park Transforms, SVPWM generation, sensorless mode via Sliding Mode Observer and High Frequency Injection, and a USB CDC interface for real-time tuning, PID parameter management, and monitoring.

Tokens
3K
Snippets
12
Records
16
Agent score
54%

What's inside STM32-FOC

  1. Overview of STM32-FOC

    master

    STM32-FOC is a low-level implementation of Field-Oriented Control (FOC) for BLDC motors using an STM32F4 microcontroller. It is built from scratch using STM32 HAL/LL drivers and FreeRTOS, avoiding high-level motor control libraries to provide a platform for precision motor control experimentation.

    Key capabilities include:

    • Control Modes: Torque, Speed, and Position control.
    • Feedback: Position feedback via AS5047 encoder and phase current sampling via ADC.
    • Advanced Algorithms: Clarke & Park Transforms, SVPWM generation, and Sensorless mode (using Sliding Mode Observer & High Frequency Injection).
    • Automation: Encoder auto-calibration and self-commissioning for PI gain auto-tuning.
    • Interface: USB CDC for real-time tuning and monitoring.
  2. Development Tools for STM32-FOC

    master

    To develop with or build upon this project, the following toolchain is used:

    • Build System: PlatformIO
    • Configuration: STM32CubeMX
    • Drivers: STM32Cube HAL & LL Drivers
    • RTOS: FreeRTOS (via PlatformIO package)
    • Debugging: VS Code + Serial Monitor
    • Hardware Design: Altium Designer (Hardware files available in STM32-FOC-hardware.zip)
    • Application: Actuator Control App (available in controller_app.zip)
  3. Configure FOC control modes

    master

    The system operates in several distinct modes by setting the hfoc.control_mode field. The behavior of the control loop changes based on this selection:

    ModeDescription
    TORQUE_CONTROL_MODEControls motor torque by setting hfoc.Is_ref (current reference).
    SPEED_CONTROL_MODEControls motor speed (RPM) using sp_input as the target.
    POSITION_CONTROL_MODEControls motor position (angle) using sp_input as the target.
    AUDIO_MODEOperates the motor in an audio-related loop.
    CALIBRATION_MODETriggers the automatic calibration sequence (resistance, inductance, and encoder calibration).
    POWER_UP_MODEPerforms open-loop voltage control for a safe startup.
  4. Initialize the FOC controller and motor hardware

    master

    To set up the Field-Oriented Control (FOC) system, you must initialize the motor configuration, the FOC core structure, and the hardware drivers. The process involves:

    1. Load Configuration: Read motor parameters (Rs, Ld, Lq, etc.) from flash memory using flash_read_config(&m_config).
    2. Initialize FOC Core: Use control_init() to set up PID controllers for current (Id/Iq), speed, position, and field weakening based on the loaded m_config.
    3. Initialize Hardware:
      • Call bldc_init() to configure the DRV8302 gate driver (PWM, MOC, Gain, etc.).
      • Call magnetic_encoder_init() to set up the AS5047P magnetic encoder via SPI.
      • Start ADC conversions for current sensing (hadc1, hadc2) and voltage sensing (hadc3).
    4. Set Initial Mode: Set hfoc.control_mode to a starting state, such as TORQUE_CONTROL_MODE or POWER_UP_MODE for a soft start.
    flash_read_config(&m_config);
    control_init();
    bldc_init();
    magnetic_encoder_init();
    
    // Start ADC for sensing
    HAL_ADCEx_InjectedStart_IT(&hadc1);
    HAL_ADCEx_InjectedStart_IT(&hadc2);
    HAL_ADCEx_InjectedStart_IT(&hadc3);
    
    // Set initial mode
    hfoc.control_mode = TORQUE_CONTROL_MODE;
  5. Organize project-specific libraries in PlatformIO

    master

    To add private, project-specific libraries to this project, place each library in its own subdirectory within the lib/ folder. PlatformIO will automatically compile these as static libraries and link them into your executable.

    Each library should follow this structure: lib/<library_name>/src/<source_files>

    Example directory structure:

    |--lib
    |  |--Bar
    |  |  |--docs
    |  |  |--examples
    |  |  |--src
    |  |  |     |- Bar.c
    |  |  |     |- Bar.h
    |  |  |     |- library.json (optional)
    |  |--Foo
    |  |     |- Foo.c
    |  |     |- Foo.h
    |--platformio.ini
    |--src
       |- main.c
    |--lib
    |  |--Bar
    |  |  |--src
    |  |  |     |- Bar.c
    |  |  |     |- Bar.h
    |--Foo
    |     |- Foo.c
    |     |- Foo.h
  6. Perform motor parameter calibration

    master

    The system can automatically estimate motor parameters (Resistance $R_s$ and Inductance $L_d, L_q$) and tune PID controllers.

    To trigger calibration:

    1. Set hfoc.control_mode = CALIBRATION_MODE.
    2. Set the start_cal flag to 1.

    The calibration_seq() function will then:

    • Calibrate the encoder.
    • Measure resistance ($R_s$) using measure_R().
    • Measure inductance ($L_d, L_q$) using measure_L().
    • Update the Smooth Observer (SMO) parameters.
    • Run flash_auto_tuning_torque_control() to optimize PID gains and save them to flash.
    hfoc.control_mode = CALIBRATION_MODE;
    start_cal = 1;
  7. Use private libraries in your source code

    master

    Once your libraries are placed in the lib/ directory, you can use them in your main application by including their header files. The PlatformIO Library Dependency Finder (LDF) will automatically scan your source files and resolve the dependencies.

    To use libraries Foo and Bar in src/main.c:

    #include <Foo.h>
    #include <Bar.h>
    
    int main (void)
    {
      // Your code using Foo and Bar
    }
    #include <Foo.h>
    #include <Bar.h>
    
    int main (void)
    {
      ...
    }
  8. Manage PID Parameters via CLI

    master

    You can read and write PID parameters for different control loops using the pid command.

    Available Control Loops (<control>):

    • id: direct current control
    • iq: quadrature current control
    • speed: speed control
    • position: position control

    Available Parameters (<param>):

    • kp: proportional gain
    • ki: integral gain
    • kd: derivative gain
    • deadband: error deadband (min error)
    • max: max output

    Command Syntax:

    • Read all parameters: pid <control>
    • Read specific parameter: pid <control> <param>
    • Write parameter: pid <control> <param> <value>
    pid speed kp 10.5
    pid id max 100
  9. Use the Command Line Interface (CLI) for Motor Control

    master

    The project provides a USB CDC interface for real-time motor tuning and monitoring via a Command Line Interface. Use the following commands to interact with the controller:

    Control Modes and Setpoints

    • mode <mode>: Change control mode.
      • 0: torque/current control
      • 1: speed control
      • 2: position control
    • sp <value>: Change the setpoint.

    Calibration and Parameters

    • calib: Run self-commissioning.
    • motor_param: Read motor parameters.
    • save: Save current configuration to flash memory.
    • set_default: Reset settings to defaults.
    mode 1
    sp 500
    calib
    save
  10. Configure Real-time Plotting Variables

    master

    Use the plot command to add or remove variables from the real-time serial plotter.

    Syntax: plot <action> <param>

    • <action>: add or rm

    Available Parameters (<param>):

    • Currents (A): ia, ib, ic, i_alpha, i_beta, id, iq
    • Voltages (V): va, vb, vc, v_alpha, v_beta, vd, vq, v_bus
    • Motion/Angle: rpm (speed), e_rad (electrical angle), m_deg (mechanical angle)
    plot add id
    plot add rpm
    plot rm v_alpha
  11. Estimate motor resistance and inductance

    master

    Manual estimation functions are available for characterizing the motor:

    • measure_R(float vdc): Injects a DC voltage vdc to estimate the stator resistance m_config.Rs. Returns -1 if bus voltage is too low.
    • measure_L(float f, float amp): Injects an AC signal at frequency f and amplitude amp to estimate $L_d$ and $L_q$. It also streams the resulting $V_d, V_q, I_d, I_q$ data via USB for analysis.

    Note: Both functions require hfoc.v_bus to be above 10.0V.

    // Estimate resistance at 1.0V
    measure_R(1.0f);
    
    // Estimate inductance at 1000Hz and 1.2A
    measure_L(1000.0f, 1.2f);