0. 本章你能得到什么
前面 5 章我们把所有核心算法拆解开讲完了:
- Clark / Park / 反 Park
- Id=0 电流环
- SVPWM 输出
但单独算法跑不起来电机 。本章把所有模块串成一套可直接工程化的 FOC 整机系统,包含:
- 硬件信号处理
- 电流采样 & 偏置校准
- 电角度获取(霍尔 / 编码器 / SMO)
- 速度环 + 电流环双闭环架构
- FOC 安全启动逻辑
- 整机调度时序
- 真机常见故障与调试方法
学完这一章,你可以直接在 STM32 上跑出顺滑、安静、有力的 FOC 控制。
1. FOC 整机数据流总框架(一张图看懂全部)
采样 → 校准 → Clark → Park → 电流环PI → 反Park → SVPWM → PWM输出
↑ |
| |
角度获取 ← 霍尔/编码器/观测器 硬件驱动
完整控制层级:
- 速度环(外环):给定目标转速 → 输出 Iq 指令
- 电流环(内环):跟踪 Id=0、Iq = 指令 → 输出 Vd/Vq
- 调制层:Vα/Vβ → SVPWM → 三相 PWM
2. 电流采样与硬件预处理(FOC 稳定性根基)
2.1 采样拓扑
- 三相下桥臂串联采样电阻
- 运放差分放大 / 同向放大
- 单电源偏置:1.65V 或 2.5V
2.2 电流物理意义
ADC 原始值 → 减去偏置 → 得到实际电流:

2.3 上电自动校准(必须做)
电机静止、PWM 关闭时,连续采 N 点平均,得到零电流偏置。
#define CALIB_TIMES 1024
void Current_Offset_Calib(void)
{
uint32_t sum_u = 0, sum_v = 0;
for(int i=0; i<CALIB_TIMES; i++)
{
sum_u += ADC_GetValue(ADC_U);
sum_v += ADC_GetValue(ADC_V);
}
Offset_U = sum_u / CALIB_TIMES;
Offset_V = sum_v / CALIB_TIMES;
}
2.4 实时电流计算
Iu = (ADC_GetValue(ADC_U) - Offset_U) * Current_Gain;
Iv = (ADC_GetValue(ADC_V) - Offset_V) * Current_Gain;
Iw = -Iu - Iv;
3. 电角度 θ 获取(FOC 的 "方向盘")
没有正确角度,FOC 必抖、必啸叫。
3.1 霍尔传感器方式(最常用、最简单)
3 个霍尔信号 H1/H2/H3 对应 6 个扇区,每个扇区 60° 电角度。
霍尔状态表:
101 → 扇区1
100 → 扇区2
110 → 扇区3
010 → 扇区4
011 → 扇区5
001 → 扇区6
再根据转速做线性插值,得到平滑 θ。
3.2 编码器方式(高精度)
- ABZ 正交编码
- 机械角度 → 电角度:

4. Park / Clark 全局统一坐标系(重中之重)
整个 FOC 必须一套坐标系走到黑:
- α 轴对齐 U 相
- θ 为 d 轴与 U 相夹角
- 旋转方向:逆时针为正
- 所有变换公式符号不能混用
任何一处符号反了,都会:
- 电机无力
- 电流巨大
- 低速抖动
- 飞车
5. 双闭环控制架构(速度环 + 电流环)
5.1 电流环(内环,最快)
-
频率:通常 10kHz / 16kHz / 20kHz(与 PWM 同周期)
-
输入:Iα, Iβ, θ
-
输出:Vα, Vβ
Id_ref = 0
Iq_ref = 速度环输出Vd = PID_Id(0, Id)
Vq = PID_Iq(Iq_ref, Iq)
5.2 速度环(外环,慢)
-
频率:1kHz 左右
-
输入:目标转速、实际转速
-
输出:Iq 电流限幅指令
Speed_Err = Speed_Target - Speed_Real
Iq_Ref = PID_Speed(Speed_Err)
5.3 限幅保护(必须加)
- Iq 最大限幅:防止过流
- 速度限幅:防止飞车
- 电压限幅:防止过调制
6. FOC 安全启动流程
电机不能一上电就进 FOC,必须按步骤来:
阶段 1:硬件初始化
- GPIO、ADC、TIM_PWM、中断、看门狗
- 电流偏置校准
阶段 2:角度对齐(关键)
给固定矢量,强制转子锁死到已知角度:
Vq = 0
Vd = 额定电压10%~20%
保持300ms~500ms
让转子磁极对准 d 轴,θ=0 对齐。
阶段 3:开环拖动(低速启动)
- 固定 Iq 小电流
- 角度 θ 手动匀速递增
- 让转子跟着磁场转起来
- 达到一定转速后切闭环 FOC
阶段 4:闭环运行
切换到:
- 霍尔 / 编码器真实角度
- 双闭环正常工作
阶段 5:故障保护
- 过流
- 过压 / 欠压
- 过温
- 启动失败
- 丢步 / 失步
任一触发 → 立即关 PWM。
7. 中断调度时序(MCU 实际运行逻辑)
典型 STM32 方案:
-
PWM 中心对齐中断(最高优先级)
- ADC 同步采样电流
- FOC 算法计算
- 更新 SVPWM 占空比
-
定时中断 1ms
- 速度计算
- 速度环 PI
- 保护逻辑
-
主循环
- 按键、指令、通信
- 调试打印、监控
8. 完整 FOC 主函数伪代码
// 全局变量
float Iu, Iv, Iw;
float Ialpha, Ibeta;
float Id, Iq;
float Vd, Vq;
float Valpha, Vbeta;
float theta;
float speed_real;
float Iq_Ref;
void FOC_MainLoop(void)
{
// 1. 初始化
Hardware_Init();
Current_Offset_Calib();
// 2. 转子对齐
align_rotor();
// 3. 开环拖动
open_loop_drag();
// 4. 正式闭环
while(1)
{
// 速度环 1ms
if(flag_1ms)
{
flag_1ms = 0;
speed_real = Get_Speed();
Iq_Ref = PID_Calc(&PID_Speed, Speed_Target, speed_real);
}
}
}
// PWM中断 = FOC核心计算
void PWM_Center_IRQHandler(void)
{
// 1. 采样电流
Iu = (ADC_U - Offset_U) * Gain;
Iv = (ADC_V - Offset_V) * Gain;
Iw = -Iu - Iv;
// 2. Clark
Clark(Iu, Iv, Iw, &Ialpha, &Ibeta);
// 3. 角度获取
theta = Get_Elec_Angle();
// 4. Park
Park(Ialpha, Ibeta, theta, &Id, &Iq);
// 5. 电流环PI
Vd = PID_Calc(&PID_Id, 0.0f, Id);
Vq = PID_Calc(&PID_Iq, Iq_Ref, Iq);
// 6. 反Park
InvPark(Vd, Vq, theta, &Valpha, &Vbeta);
// 7. SVPWM
SVPWM_Calc(Valpha, Vbeta);
}
9. 真机上电 90% 必遇问题(调试宝典)
9.1 电机一叫就抖,不转
- 角度方向反了
- Hall 顺序接反
- Park 公式符号错误
9.2 电机能转,但无力、发热大
- Id 没有置 0
- 电流采样增益不对
- 角度有偏差
- SVPWM 扇区计算错误
9.3 低速抖,高速正常
- 角度插值不够平滑
- 电流环 PI 参数太弱
- 死区太大
- 采样噪声大
9.4 上电直接过流
- 运放相位反
- PWM 输出极性反
- 上下管直通
- 采样偏置未校准
9.5 转着转着丢步、失控
- 速度环参数过大
- 电流限幅太小
- 角度跳变
- 电源压降太大
10. PI 参数调试顺序(黄金步骤)
-
先调电流环
- Kp 从小到大
- 直到电流无超调、响应快
-
再调速度环
- 先 I=0,调 Kp
- 再加 Ki 消除静差
-
最后优化低速平滑性
- 角度滤波
- 电流滤波
- 死区补偿
11. 本章总结
FOC 不是堆算法,而是系统工程:
- 电流采样是根基
- 角度是方向盘
- 双闭环是核心
- 启动逻辑是安全底线
- 统一坐标系是灵魂
按本章流程做出来的 FOC:
- 启动顺滑无冲击
- 低速安静无啸叫
- 高速有力不抖动
- 效率高、发热小