esp_simplefoc 组件实战指南:在 ESP-IDF 中基于 Arduino-FOC 实现无刷电机磁场定向控制
【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution
esp_simplefoc 是 Espressif ESP IoT Solution 仓库(components/motor/esp_simplefoc)中面向 ESP 芯片的 FOC(Field-Oriented Control,磁场定向控制)组件,基于 Arduino-FOC 移植而来,专门针对支持 LEDC 与 MCPWM 外设的 ESP 芯片设计。本文以该组件的官方使用文档(docs/zh_CN/motor/foc/esp_simplefoc.rst)为主体,结合仓库内源码与测试用例,完整讲解从组件引入、FreeRTOS 配置、电机与 MOS 驱动器参数设定、角度传感器绑定、控制器模式选择到初始化与循环控制的完整落地流程,读完即可在 ESP-IDF 工程中驱动三相无刷电机。
一、组件定位与核心特性
esp_simplefoc 是一个在 ESP-IDF 环境下使用的 C++ 组件,其 API 与 Arduino-FOC 保持一致的接口风格,便于沿用已有的 SimpleFOC 工程经验。根据组件的 README.md 与官方使用文档,它具备以下能力:
- 电压控制:支持对电机进行基于电压矢量的控制输出。
- 上位机控制:可通过 SimpleFOCStudio 调整和配置电机控制参数,方便在线调试。
- 多电机控制:最高支持四路无刷电机控制,驱动模式(LEDC / MCPWM)既可手动选择,也可由系统决定。
- 兼容 SimpleFOC 例程:API 与 Arduino-FOC 控制例程兼容,迁移成本低。
- IQMath 加速:采用 Espressif 的 IQMath 定点数学库大幅加速 FOC 运算(依赖声明见 idf_component.yml 中的
espressif/iqmath: "^1.11.0")。
FOC 是一种面向无刷直流电机的磁场定向控制算法,通过对定子电流进行 dq 坐标解耦,实现对扭矩、速度与位置的平滑控制。esp_simplefoc 在此基础上提供了力矩、速度、角度以及对应的开环控制模式。
支持的芯片与依赖
从 idf_component.yml 可以看到,组件当前版本为 1.3.0,支持的目标芯片包括:
| 目标芯片 | 说明 |
|---|---|
| esp32 | 经典双核 ESP32 |
| esp32s2 | 单核 Xtensa |
| esp32s3 | 双核 Xtensa,带向量指令 |
| esp32c3 / esp32c6 / esp32h2 | RISC-V 系列 |
组件要求 ESP-IDF 版本不低于 5.0,并依赖以下公共组件:
i2c_bus(版本1.*):用于 I2C 角度传感器接入;espressif/arduino-foc(版本>=2.3.0~3):提供 FOC 核心算法与基础类;espressif/iqmath(版本^1.11.0):提供定点数学运算加速。
从组件的 CMakeLists.txt 可以看出其构建策略:所有源码(含 esp_hal_bldc_3pwm.cpp、esp_hal_bldc_6pwm.cpp、esp_hal_stepper.cpp 及三个角度传感器适配)在编译时统一纳入,其中 6PWM(MCPWM)驱动仅在CONFIG_SOC_MCPWM_SUPPORTED定义时参与编译,也就是说芯片是否支持 MCPWM 会直接影响可用驱动类型。
二、将组件添加到你的工程
2.1 通过组件管理器引入
推荐使用 ESP-IDF 组件管理器的add-dependency命令添加依赖,在 CMake 构建阶段组件会被自动下载:
idf.py add-dependency "espressif/esp_simplefoc"也可以在工程中手动创建idf_component.yml并在dependencies一节中声明:
dependencies: espressif/esp_simplefoc: version: "1.*" public: true2.2 引入头文件
组件将 Arduino-FOC 的各类核心头文件统一汇总到一个入口头文件 esp_simplefoc.h 中,该头文件一次引入电机类、驱动器、通信调试与角度传感器等全部能力:
#include "esp_simplefoc.h"从该头文件可以看出,组件实际暴露的能力包括:
- 电机类:
BLDCMotor、StepperMotor; - 驱动器:
BLDCDriver3PWM、BLDCDriver6PWM、StepperDriver2PWM、StepperDriver4PWM; - 通信与调试:
Commander、SimpleFOCDebug; - 传感器:
GenericSensor、AS5600、MT6701、AS5048a; - 电流采样:
GenericCurrentSense、LowsideCurrentSense。
三、FreeRTOS 系统时钟配置(必需步骤)
FOC 是一个对控制周期敏感的应用,官方文档与组件 README 都强调一个硬性要求:必须将 FreeRTOS 的configTICK_RATE_HZ设置为 1000,否则可能出现电机运行异常。
配置方法:运行idf.py menuconfig,进入(Top) → Component config → FreeRTOS → Kernel,将configTICK_RATE_HZ从默认的 100 修改为 1000。
这一要求同样体现在组件的测试工程配置中,test_apps/sdkconfig.defaults 明确写入了:
CONFIG_FREERTOS_HZ=1000同时在测试配置中还关闭了任务看门狗(CONFIG_ESP_TASK_WDT_EN=n)、将 CPU 主频设置为 240 MHz(CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y)、并把定时器任务栈加深到 4096(CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096)。这些配置对保证 FOC 实时控制循环稳定运行同样具有参考价值。
四、电机参数配置
在实例化BLDCMotor时,需要根据实际的三相无刷电机填写参数:
| 参数 | 含义 | 默认值 |
|---|---|---|
pp | 电机极对数 | 必填,按实际电机填写 |
R | 电机相电阻(Ω) | NOT_SET |
KV | 电机 KV 值 | NOT_SET |
L | 电机相电感(H) | NOT_SET |
其中R、KV、L主要用于电机参数辨识与高级控制,可后续通过 SimpleFOCStudio 或代码回填。对于极对数为 14 的三相无刷电机,实例化为:
BLDCMotor motor = BLDCMotor(14);测试工程 test_esp_simplefoc.cpp 中的开环控制用例正是使用 14 极对电机验证的:
BLDCMotor motor = BLDCMotor(14);五、MOS 驱动器控制参数与引脚配置
5.1 参数说明
| 参数 | 含义 | 默认值 |
|---|---|---|
pwm pin | PWM 输出引脚,需按 MOS 驱动器电路确定 | 必填 |
enable pin | 驱动器使能脚,若驱动器需手动使能则填写 GPIO | NOT_SET |
voltage_power_supply | MOS 驱动器供电电压(V) | 必填 |
voltage_limit | 驱动器电压限制(V),应略低于供电电压 | 必填 |
5.2 3PWM 驱动实例化
对于 3PWM 模式的 12V MOS 驱动器,实例化与参数设置如下:
BLDCDriver3PWM driver = BLDCDriver3PWM(4, 5, 6); driver.voltage_power_supply = 12; driver.voltage_limit = 11; driver.init({1, 2, 3}); motor.linkDriver(&driver);这里BLDCDriver3PWM(4, 5, 6)的 4、5、6 是三个相(A/B/C)的 PWM 输出引脚,而driver.init({1, 2, 3})中的 1、2、3 则是LEDC 通道号。这一点需要特别留意:3PWM 驱动支持 LEDC 与 MCPWM 两种底层外设,初始化函数的入参决定了选用哪种外设。
5.3 LEDC 与 MCPWM 两种驱动模式
从 esp_hal_bldc_3pwm.h 的源码可以看到组件定义了显式的驱动模式枚举:
enum class DriverMode { mcpwm = 0, /*!< Foc hardware drive mode:MCPWM */ ledc = 1, /*!< Foc hardware drive mode:LEDC */ };BLDCDriver3PWM提供三种初始化重载:
int init() override; // 系统自动选择模式 int init(int _mcpwm_group); // 显式使用 MCPWM,参数为 MCPWM group 编号(需芯片支持) int init(std::vector<int> _ledc_channels); // 显式使用 LEDC,参数为 LEDC 通道号数组即官方文档中driver.init({1, 2, 3})实际就是第三种重载——使用 LEDC 通道 1、2、3。而文档描述“支持手动选择 LEDC 或 MCPWM 外设来控制 MOS 驱动器,最高可实现四路无刷电机控制”,对应源码中的模式枚举与多实例能力。
该头文件中还定义了 LEDC/MCPWM 的默认参数,可作为理解底层配置的参考:
- LEDC:
_LEDC_FREQUENCY = 20 kHz,_LEDC_DUTY_RES = 9 bit(最大占空比 511),低速模式、LEDC_TIMER_0; - MCPWM:默认频率 20 kHz(最大 50 kHz),时基分辨率 10 MHz。
对于支持 MCPWM 的芯片(如 ESP32、ESP32-S3),可在init时传入 mcpwm group 编号改用 MCPWM 输出;组件 CMakeLists.txt 中的CONFIG_SOC_MCPWM_SUPPORTED条件编译也印证了这一点。此外驱动还提供enable()/disable()/deinit()以及setPhaseState()等接口,其中使能极性由enable_active_high控制,默认高电平有效。
测试用例中 6PWM 驱动(BLDCDriver6PWM(1, 2, 3, 4, 5, 6))的验证代码位于 test_esp_simplefoc.cpp,同样受CONFIG_SOC_MCPWM_SUPPORTED宏保护,进一步佐证了 6PWM 与 MCPWM 的绑定关系。
六、角度传感器配置
esp_simplefoc 当前内置三款角度传感器的适配,位于 components/motor/esp_simplefoc/port/angle_sensor:
| 传感器 | 接口 | 说明 |
|---|---|---|
AS5048a | SPI | 高分辨率磁编码器 |
MT6701 | I2C / SPI | 同时支持两种总线 |
AS5600 | I2C | 低成本磁编码器,常用于入门 |
以 AS5600 为例,实例化并绑定到电机:
AS5600 as5600 = AS5600(I2C_NUM_0, GPIO_NUM_1, GPIO_NUM_2); as5600.init(); motor.linkSensor(&as5600);构造函数中I2C_NUM_0为 I2C 外设编号,GPIO_NUM_1、GPIO_NUM_2分别为 SDA、SCL 引脚。
测试工程对三款传感器均有对应用例,例如 AS5600 的 I2C 用例(test_esp_simplefoc.cpp):
TEST_CASE("test as5600", "[sensor][as5600][i2c]") { AS5600 as5600 = AS5600(I2C_NUM_0, GPIO_NUM_12, GPIO_NUM_13); as5600.init(); for (int i = 0; i < 10; ++i) { ESP_LOGI(TAG, "angle:%.2f", as5600.getSensorAngle()); vTaskDelay(1000 / portTICK_PERIOD_MS); } as5600.deinit(); }注意测试代码针对不同目标芯片使用了不同引脚组合,在实际工程中请以你的硬件接线为准。MT6701 的 SPI 用例演示了其 SPI 构造签名:MT6701(SPI2_HOST, cs, sck, miso, mosi)(其中 miso 可传 -1 表示不使用),AS5048a 的用法与之类似。
七、控制器模式选择
根据应用需求,可在MotionControlType中选取以下控制方式:
| 控制方式 | 说明 |
|---|---|
torque | 力矩控制 |
velocity | 速度控制(闭环) |
angle | 角度控制(闭环) |
velocity_openloop | 速度开环控制 |
angle_openloop | 角度开环控制 |
提示:在硬件验证阶段,可优先选择开环控制方案,快速验证电机与驱动器接线是否正确,再切换到闭环控制。
测试用例中的开环验证即展示了该用法(test_esp_simplefoc.cpp):
motor.velocity_limit = 200.0; motor.voltage_limit = 12.0; motor.controller = MotionControlType::velocity_openloop; motor.init(); for (int i = 0; i < 5000; ++i) { motor.move(1.2f); vTaskDelay(1 / portTICK_PERIOD_MS); }八、FOC 初始化与循环控制
完成上述参数设置后,按以下流程启动电机:
motor.init(); // 电机硬件初始化 motor.initFOC(); // FOC 初始化与校准(包含角度传感器零点、极对数估计等) while (1) { motor.loopFOC(); // FOC 控制循环(电流/角度解算) motor.move(target_value); // 施加控制目标(速度/角度/力矩) command.run(); // 处理上位机(Commander)命令 }注意:若
initFOC估计出的极对数与实际填入的极对数不符,请排查电机极对数设置,并尽可能缩小磁环与角度传感器之间的间距,以提高角度读取的可靠性。
控制循环中的command.run()对应Commander组件(头文件见 esp_simplefoc.h 中的communication/Commander.h),它使你能通过串口配合 SimpleFOCStudio 在线调整控制参数,这正是组件“支持上位机控制”特性的落地通道。
九、编译烧录与运行
完成配置与代码编写后,执行:
idf.py build flash完成首次下载后即可观察电机实际运行效果。若需配合 SimpleFOCStudio 在线调参,请确保串口波特率设置(测试用例中使用Serial.begin(115200))与上位机一致。
十、源码级参考与延伸阅读
- 组件入口与能力清单:esp_simplefoc.h
- 3PWM 驱动器头文件(模式枚举、默认频率/分辨率、初始化重载):esp_hal_bldc_3pwm.h
- 构建与条件编译逻辑:CMakeLists.txt
- 依赖与支持目标芯片:idf_component.yml
- 传感器适配源码:AS5600 / MT6701 / AS5048a(port/angle_sensor)
- 测试用例(传感器读写、6PWM 驱动、开环控制):test_esp_simplefoc.cpp
- 测试工程 FreeRTOS 配置:sdkconfig.defaults
仓库中同时提供了可直接运行的官方示例工程(examples/motor 目录),包括:
foc_openloop_control:开环控制示例,适合快速验证硬件;foc_velocity_control:速度闭环控制示例;foc_knob_example:旋钮(Knob)交互式 FOC 示例。
这些示例与组件的examples字段一一对应(见 idf_component.yml),可作为从示例到自研工程迁移的起点。esp_simplefoc 的 API 接口与 Arduino-FOC 保持一致,因此也完全可以参照 Arduino-FOC 的 API 文档扩展使用。组件源码以 Apache License 开源(详见 license.txt)。
【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考