1. 项目概述
FOC(Field Oriented Control,磁场定向控制)作为现代电机控制领域的核心技术,正在逐步取代传统的六步换相和方波控制方案。这次分享的代码实现了一套完整的FOC有感电机控制系统,特别适合需要精确转矩控制的中小功率应用场景。
这套代码最核心的价值在于:它用简洁高效的实现方式,解决了工业现场常见的几个痛点问题——低速抖动、启动失步和动态响应滞后。我在多个实际项目中验证过这套方案的可靠性,从电动工具到医疗设备都能稳定运行。
2. FOC控制原理精要
2.1 磁场定向的本质
FOC的核心思想是把三相交流电机等效为直流电机来控制。通过Clarke变换将三相电流转换为两相静止坐标系(α-β),再经过Park变换旋转到与转子磁场同步的d-q坐标系。这样,转矩电流(Iq)和励磁电流(Id)就实现了完全解耦。
关键提示:在实际编码时,Park变换的角度必须与转子位置严格同步,这也是为什么"有感"方案(使用编码器)比无感方案更可靠的根本原因。
2.2 电流环的关键参数
代码中电流环采用PI控制器,比例系数Kp和积分时间Ti的整定直接影响系统响应:
- Kp过大 → 电流震荡
- Kp过小 → 响应迟缓
- 经验公式:Kp = L/R * 带宽频率(L为电机电感,R为相电阻)
实测中发现,医疗设备等对噪声敏感的应用,建议带宽设在500Hz以内;而电动工具类可以放到1kHz以上。
3. 代码架构解析
3.1 硬件抽象层设计
code复制typedef struct {
void (*PWM_SetDuty)(uint8_t ch, float duty);
float (*ADC_GetCurrent)(void);
uint16_t (*ENC_GetPosition)(void);
} FOC_HAL_t;
这种硬件抽象设计使代码可以快速移植到不同平台。我在STM32和GD32平台上都验证过,只需修改底层驱动函数指针即可完成移植。
3.2 核心控制流程
- 位置采样(编码器计数)
- 电流采样(至少两相)
- Clarke/Park变换
- PI调节器运算
- 逆Park/SVPWM生成
- PWM输出更新
特别注意:电流采样时机必须与PWM中心对齐,否则会引入严重谐波。代码中通过定时器触发ADC实现了硬件级同步。
4. 关键实现技巧
4.1 编码器校准
上电时自动执行的编码器校准流程:
c复制void FOC_CalibrateEncoder(void) {
// 强制输出固定电压矢量
PWM_SetVector(1.0f, 0.0f);
delay_ms(500);
// 记录极对数对应的机械角度间隔
uint16_t pos1 = ENC_GetPosition();
PWM_SetVector(0.5f, 0.866f); // 旋转60度
delay_ms(500);
uint16_t pos2 = ENC_GetPosition();
pole_pairs = (360 * ENC_RESOLUTION) / (6 * (pos2 - pos1));
}
这个方法巧妙利用了SVPWM的矢量特性,无需额外硬件就能完成极对数检测。
4.2 死区补偿
在低转速时,MOSFET的死区时间会导致明显的转矩脉动。代码中采用预补偿方案:
c复制void FOC_ApplyDeadtimeComp(float *u, float *v, float *w) {
float deadtime_volt = DEADTIME_NS * BUS_VOLTAGE / PWM_PERIOD_NS;
*u += (*u > 0) ? deadtime_volt : -deadtime_volt;
*v += (*v > 0) ? deadtime_volt : -deadtime_volt;
*w += (*w > 0) ? deadtime_volt : -deadtime_volt;
}
实测补偿后,低速(<100rpm)转矩波动降低约60%。
5. 性能优化实战
5.1 定点数加速
在M4内核MCU上,将浮点运算转换为Q15格式定点数后,循环周期从85μs缩短到32μs:
c复制// 浮点版本
float i_alpha = ia;
float i_beta = (ia + 2*ib) * ONE_BY_SQRT3;
// 定点优化版
int16_t i_alpha_q = ia_raw;
int16_t i_beta_q = __SMULWB(ia_raw + 2*ib_raw, ONE_BY_SQRT3_Q15);
注意:Park变换中的三角函数需要预先建立查找表,Q15格式的sin/cos表仅需512字节ROM空间。
5.2 观测器降噪
针对编码器信号噪声,采用滑动平均滤波+速度观测器的二级滤波:
code复制speed_est = (pos_filtered - last_pos) / dt;
speed_est = 0.8*speed_est + 0.2*last_speed; // 低通滤波
这个技巧使得在0.1rpm分辨率下仍能保持速度信号稳定。
6. 典型问题排查
6.1 电机啸叫
现象:运行时伴随高频噪声
- 检查1:SVPWM频率是否过低(建议>15kHz)
- 检查2:电流环带宽是否过高(用示波器看IQ振荡)
- 检查3:PID参数是否激进(适当降低Kp)
6.2 启动抖动
现象:上电初始位置识别失败
- 对策1:增加编码器零位校准流程
- 对策2:启动时采用开环强制对齐(代码中FOC_AlignRotor()函数)
- 对策3:检查电源电压是否足够(带载启动需要更高电压)
7. 扩展应用方向
这套基础框架还可以扩展更多高级功能:
- 位置环控制:在电流环外层增加位置PID
- 弱磁控制:通过注入负Id电流实现高速扩展
- 在线参数识别:自动测量R/L/Ke等电机参数
我在自动化产线输送带项目中就曾基于此代码增加电子齿轮功能,通过Modbus实时调整速比,精度达到±0.05%。
