欢迎光临
我们一直在努力

简单理解:电机SimpleFOC闭环控制与开环控制的文件和代码差异

一、新增文件对比

1. 核心控制库文件(闭环控制新增)

SimpleFOC/ 目录下的所有文件:

  • MagneticSensor.c/h:磁性编码器接口
  • FOCMotor.c/h:FOC 电机控制基类
  • BLDCmotor.c/h:无刷电机控制实现
  • pid.c/h:PID 控制器实现
  • lowpass_filter.c/h:低通滤波器
  • foc_utils.c/h:FOC 算法工具函数

2. 传感器驱动文件(闭环控制新增)

Hardware/ 目录下的编码器通信文件:

  • iic.c/h:I2C 通信驱动(用于 AS5600 编码器)
  • spi2.c/h:SPI 通信驱动(用于 TLE5012B 编码器)

3. 配置文件(闭环控制新增)

传感器配置相关代码:

  • user/MyProject.h:编码器类型定义(M1_AS5600/M1_TLE5012B)

二、新增代码对比

控制类型核心代码
开环控制 仅需初始化 GPIO 和 PWM
闭环控制 新增传感器、FOC 和 PID 初始化

// 编码器初始化
#if M1_AS5600
I2C_Init_(); // AS5600 I2C初始化
printf("AS5600\\r\\n");
#elif M1_TLE5012B
SPI2_Init_(); // TLE5012B SPI初始化
printf("TLE5012B\\r\\n");
#endif

// 传感器初始化
MagneticSensor_Init(); // 初始化磁性编码器

// FOC和PID初始化
Motor_initFOC(); // 初始化FOC算法
PID_init(); // 初始化PID控制器

2. 主循环新增代码

表格

控制类型核心代码
开环控制 仅需输出 PWM 信号
闭环控制 新增 FOC 算法执行和反馈处理

// 闭环控制核心流程
move(target); // 设置目标值(位置/速度)
loopFOC(); // 执行FOC算法,处理传感器反馈

3. 控制参数新增代码

控制类型核心代码
开环控制 仅需设置电压或 PWM 占空比
闭环控制 新增控制模式和 PID 参数配置

// 闭环控制参数
voltage_power_supply=12; // 电源电压
pole_pairs=7; // 电机极对数
voltage_limit=6; // 电压限制
velocity_limit=20; // 速度限制
voltage_sensor_align=2.5; // 传感器对齐电压
torque_controller=Type_voltage; // 力矩控制器类型
controller=Type_velocity; // 控制模式(速度/位置/力矩)

4. 串口命令处理新增代码

控制类型核心代码
开环控制 仅需处理电压或 PWM 命令
闭环控制 新增目标值设置和反馈处理

// 闭环控制命令处理
case 'T': // T6.28 设置目标值(位置/速度)
target=atof((const char *)(USART_RX_BUF+1));
printf("RX=%.4f\\r\\n", target);
break;

三、核心功能差异代码(闭环控制特有)

1. 传感器反馈处理

// MagneticSensor.c 中的位置读取函数
float getAngle() {
// 读取编码器原始值
// 转换为角度值
return angle;
}

// 计算速度
float getVelocity() {
// 根据位置变化计算速度
return velocity;
}

2. FOC 算法实现

// FOCMotor.c 中的FOC初始化
void Motor_initFOC() {
// 传感器零位校准
// 电流采样初始化
// FOC参数计算
}

// 执行FOC算法
void loopFOC() {
// 读取电机位置
// 计算电角度
// 电流采样和变换
// SVPWM计算和输出
}

3. PID 控制器

// pid.c 中的PID计算
float PIDoperator(PID_s *pid, float error) {
// 计算比例、积分、微分项
// 限幅处理
// 返回控制输出
return output;
}

四、核心差异总结

类别新增内容作用
文件 SimpleFOC 目录下的 FOC 算法文件 实现磁场定向控制和 PID 调节
文件 Hardware 目录下的编码器驱动 实现传感器通信(I2C/SPI)
代码 传感器初始化和配置 获取电机实际位置和速度
代码 FOC 算法初始化和执行 计算最优电压矢量,提高控制效率
代码 PID 控制器初始化和运算 实时校正控制误差,提高精度
代码 多模式控制逻辑 支持速度、位置、力矩模式切换

关键点回顾

  • 闭环控制相比开环控制,核心新增了传感器反馈、FOC 算法、PID 调节三大模块;
  • 新增文件主要集中在SimpleFOC/(控制算法)和Hardware/(传感器驱动)目录;
  • 新增代码覆盖初始化、主循环、参数配置、串口命令四大环节,实现了 “检测 – 计算 – 校正” 的闭环逻辑。

  • SimpleFOC闭环控制的main.c

    #include "stm32f10x.h" // 引入STM32F10x系列单片机底层驱动库
    #include <stdlib.h> // 引入标准库,用于atof等函数
    #include "MyProject.h" // 引入自定义工程头文件,包含外设和FOC相关声明

    /************************************************
    SimpleMotor开发板
    闭环控制 演示
    1、力矩模式
    2、速度模式
    3、位置模式
    =================================================
    本程序仅供学习,引用代码请标明出处
    使用教程:https://blog.csdn.net/loop222/article/details/120471390
    《SimpleFOC移植STM32(四) —— 闭环控制》
    创建日期:20230208
    作 者:loop222 @郑州
    ************************************************/
    /******************************************************************************/
    #define LED_blink GPIOC->ODR^=(1<<13) // 定义LED翻转宏,操作GPIOC的13引脚输出寄存器取反
    /******************************************************************************/
    float target; // 定义控制目标值(力矩/速度/位置)
    /******************************************************************************/
    void commander_run(void); // 声明串口指令处理函数
    /******************************************************************************/
    void GPIO_Config(void) // GPIO初始化配置函数
    {
    GPIO_InitTypeDef GPIO_InitStructure; // 定义GPIO初始化结构体变量

    // 使能GPIOA、GPIOB、GPIOC时钟和AFIO复用功能时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO, ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); // 禁用JTAG,释放相关引脚

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; // 配置PC13引脚(LED)
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; // 输出速度10MHz
    GPIO_Init(GPIOC, &GPIO_InitStructure); // 初始化GPIOC13引脚
    GPIO_ResetBits(GPIOC,GPIO_Pin_13); // PC13置低,上电点亮LED

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // 配置PB9引脚(电机1使能)
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; // 输出速度10MHz
    GPIO_Init(GPIOB, &GPIO_InitStructure); // 初始化GPIOB9引脚
    GPIO_ResetBits(GPIOB,GPIO_Pin_9); // PB9置低解除使能(Motor_init中使能)
    }
    /******************************************************************************/
    int main(void) // 主函数入口
    {
    unsigned int count_i=0; // 定义循环计数变量

    GPIO_Config(); // 调用GPIO初始化函数
    uart_init(115200); // 初始化串口,波特率115200
    #if M1_AS5600 // 条件编译:如果使用AS5600编码器
    I2C_Init_(); // 初始化I2C总线(AS5600通信)
    printf("AS5600\\r\\n"); // 串口打印编码器类型
    #elif M1_TLE5012B // 条件编译:如果使用TLE5012B编码器
    SPI2_Init_(); // 初始化SPI2总线(TLE5012B通信)
    printf("TLE5012B\\r\\n"); // 串口打印编码器类型
    #endif
    TIM2_PWM_Init(); // 初始化TIM2,生成PWM波驱动电机
    TIM4_1ms_Init(); // 初始化TIM4,1ms中断(用于计时)

    delay_ms(1000); // 延时1秒,等待系统稳定
    MagneticSensor_Init(); // 初始化磁编码器(AS5600/TLE5012B)

    voltage_power_supply=12; // 设置电源供电电压12V
    pole_pairs=7; // 设置电机极对数为7(按实际电机配置)
    voltage_limit=6; // 设置电压限制6V(<12/1.732=6.9)
    velocity_limit=20; // 设置速度限制20rad/s(开环/位置环使用)
    voltage_sensor_align=2.5; // 设置传感器对齐电压2.5V(云台电机2-3V)
    torque_controller=Type_voltage; // 设置力矩控制模式为电压模式
    controller=Type_velocity; // 设置闭环控制模式为速度模式(可改为位置/力矩)
    target=0; // 初始化控制目标值为0

    Motor_init(); // 初始化电机硬件和参数
    Motor_initFOC(); // 初始化FOC算法相关配置
    PID_init(); // 初始化PID控制器参数(内部已预设)
    printf("Motor ready.\\r\\n"); // 串口打印电机就绪信息

    systick_CountMode(); // 切换SysTick为计数模式(禁用delay_us/ms)

    while(1) // 主循环
    {
    count_i++; // 计数变量自增

    if(time1_cntr>=200) // 每200ms(1ms中断*200)执行一次
    {
    time1_cntr=0; // 重置计时变量
    LED_blink; // 翻转LED状态(心跳灯)
    }
    if(time2_cntr>=1000) // 每1000ms执行一次
    {
    time2_cntr=0; // 重置计时变量
    //printf("%d\\r\\n",count_i); // 调试用:打印计数(当前注释)
    count_i=0; // 重置计数变量
    }
    move(target); // 执行目标值更新(位置/速度/力矩)
    loopFOC(); // 执行FOC核心算法(电流采样/解耦/PWM输出)
    commander_run(); // 检查串口指令并处理
    }
    }
    /******************************************************************************/
    void commander_run(void) // 串口指令处理函数
    {
    if((USART_RX_STA&0x8000)!=0) // 判断串口接收是否完成(最高位为1表示完成)
    {
    switch(USART_RX_BUF[0]) // 根据接收缓冲区第一个字符判断指令
    {
    case 'H': // 指令H:打印测试信息
    printf("Hello World!\\r\\n"); // 串口打印Hello World
    break; // 退出switch
    case 'T': // 指令T+数值:设置目标值(如T6.28)
    target=atof((const char *)(USART_RX_BUF+1)); // 转换字符串为浮点型目标值
    printf("RX=%.4f\\r\\n", target); // 串口回显接收到的目标值
    break; // 退出switch
    case 'D': // 指令D:禁用电机
    M1_Disable; // 执行电机禁用操作(宏定义)
    printf("OK!\\r\\n"); // 串口打印确认信息
    break; // 退出switch
    case 'E': // 指令E:使能电机
    M1_Enable; // 执行电机使能操作(宏定义)
    printf("OK!\\r\\n"); // 串口打印确认信息
    break; // 退出switch
    }
    USART_RX_STA=0; // 重置串口接收状态标志
    }
    }
    /******************************************************************************/

    总结

  • 代码核心功能:基于 STM32F10x 的 SimpleFOC 闭环控制程序,支持力矩 / 速度 / 位置三种模式,通过串口指令控制电机目标值,1ms 中断实现计时,200ms 翻转 LED 作为心跳灯。
  • 关键配置项:需根据实际电机修改pole_pairs(极对数)、voltage_sensor_align(对齐电压)等参数,controller变量可切换控制模式(力矩 / 速度 / 位置)。
  • 串口指令:支持 H(测试)、T + 数值(设置目标值)、D(禁用电机)、E(使能电机)四种指令,接收完成后需重置USART_RX_STA确保下次接收正常。
  • 赞(0)
    未经允许不得转载:171主机测评 » 简单理解:电机SimpleFOC闭环控制与开环控制的文件和代码差异
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址