FOC 调试现场最常听到的一句话是"电流环跑起来了,但电机就是不转"或者"低速一加载就抖"。这类问题十有八九不是代码写错了,而是对 Ud/Uq 的物理含义、控制频率的选取逻辑、以及高频注入(HFI)注入频率与 PWM 载波之间的关系没吃透。我自己在无感 FOC 上踩过的坑,几乎全部集中在这三个点上:坐标系搞反、频率设错、注入信号和采样时机打架。这篇就把这三件事从头到尾捋一遍,从 FOC 中断的时序开始,讲到 Ud/Uq 的坐标变换、控制频率与带宽的取舍,再到 HFI 高频注入的频率设计和转子初始位置检测的实操细节。适合已经能跑通有霍尔 FOC、正准备上无感方案,或者无感方案低速段一直调不好的朋友。看完你至少能搞清楚:为什么你的电流环带宽上不去、为什么注入频率不能随便设、以及 Ud/Uq 到底在控制什么。
1. 从 FOC 中断的时序说起:一次控制周期里到底发生了什么
很多人调 FOC 是"抄一份代码,改改参数",但一旦出问题就完全不知道从哪查。根因在于没搞清楚一个 FOC 中断周期内,硬件和软件各自在什么时刻做了什么。把时序理清楚,后面 Ud/Uq、控制频率、HFI 注入频率的所有疑问都会迎刃而解。
1.1 一个 PWM 周期内的采样、计算与更新
以最常见的中心对齐 PWM 为例,一个 PWM 周期内定时器会产生两次比较匹配(上溢和下溢附近),通常我们在这两个时刻触发 ADC 采样。为什么选这两个点?因为中心对齐模式下,这两个时刻刚好落在 PWM 波形的"谷底",此时功率管开关动作产生的电流纹波最小,采样到的相电流最接近真实值。这就是所谓的"双电阻采样"或"单电阻采样"的经典时机。
采样完成后进入 ADC 中断,在中断里完成:相电流读取 → Clarke 变换 → Park 变换(需要电角度)→ 电流 PI 调节 → 反 Park 变换 → SVPWM 占空比计算 → 更新比较寄存器。这一整套流程必须在下一次 PWM 更新事件之前算完,否则占空比就会延迟一个周期生效,电流环相位裕度直接恶化。
这里有个关键点:控制频率通常等于 PWM 频率,也就是一个 PWM 周期执行一次完整的电流环。但有些方案会做"PWM 频率 = 2 倍控制频率",即一个控制周期跨两个 PWM 周期,这样能降低 CPU 负担,代价是电流环带宽受限。我实测下来,对于几十 kHz 载波的主流方案,控制频率和 PWM 频率取 1:1 是最省心的。
1.2 中断里最容易被忽略的两个时间开销
第一个是 ADC 采样到转换完成的时间。很多 MCU 的 ADC 采样保持需要几百纳秒到 1 微秒,如果你在中断里才启动 ADC 再等结果,这段时间是纯浪费。正确做法是在 PWM 触发 ADC 后,中断里直接读已经转换好的结果。
第二个是 Park 变换用的电角度。这个角度必须和当前采样时刻的转子位置对应,而不是和计算完成时刻对应。如果你用的是编码器或霍尔,角度读取和电流采样之间要保证时间对齐;如果是无感观测器,观测出的角度本身就有延迟,这个延迟在高速时会造成明显的角度误差,需要在算法里做补偿。
提示:判断你的时序有没有问题,最简单的办法是在中断里翻转一个 GPIO,用示波器看这个 GPIO 的翻转时刻和 PWM 波形的关系。如果翻转点离 PWM 更新点太近,说明你的计算时间已经逼近极限了。
1.3 控制频率和电流环带宽的真实关系
这是被问得最多的问题之一。理论上,数字控制系统的电流环带宽一般取控制频率的 1/10 到 1/20。比如 20kHz 控制频率,电流环带宽做到 1kHz 到 2kHz 是比较稳妥的。为什么不能更高?因为采样和计算的延迟会在环路里引入相位滞后,带宽越高,相位裕度越小,越容易振荡。
我见过有人把 PI 参数调得很激进,带宽冲到 5kHz,结果空载看着挺好,一加负载电流就开始高频振荡。这就是相位裕度不够的典型表现。所以调电流环之前,先确认你的控制频率,再按 1/10 到 1/20 去估带宽,然后反推 PI 参数,比盲目试参数靠谱得多。
2. Ud/Uq 到底在控制什么:别再把坐标系搞反了
Ud/Uq 是 FOC 里最基础也最容易搞混的概念。我见过太多人把 Uq 当成励磁分量、Ud 当成转矩分量,结果电机要么不转,要么发热严重。这一节把 Ud/Uq 的物理意义、和电流的关系、以及实际控制中的处理方式讲透。
2.1 d 轴和 q 轴的物理定义
在 PMSM 的转子磁场定向控制里,d 轴定义为转子永磁体磁链的方向,q 轴超前 d 轴 90 度电角度。这个定义决定了:d 轴电流产生的是励磁方向的磁动势,q 轴电流产生的是转矩。
对于表贴式永磁同步电机(SPMSM),交直轴电感基本相等(Ld ≈ Lq),磁阻转矩为零,所以转矩完全由 q 轴电流决定,d 轴电流理论上应该控制为 0(除非要做弱磁)。对于内置式永磁同步电机(IPMSM),Ld < Lq,存在磁阻转矩,这时候可以给一个负的 d 轴电流来利用磁阻转矩,提高效率,这就是 MTPA(最大转矩电流比)控制的由来。
所以 Ud/Uq 不是"电压的两个分量"这么简单,它们对应的是 d 轴和 q 轴上需要施加的电压,用来驱动相应的电流。控制的目标是让 Id 和 Iq 跟踪给定值,Ud/Uq 只是达成这个目标的手段。
2.2 电压方程里每一项的含义
PMSM 在 dq 坐标系下的电压方程是这样的:
Ud = Rs * Id + Ld * dId/dt - ωe * Lq * Iq Uq = Rs * Iq + Lq * dIq/dt + ωe * (Ld * Id + ψf)逐项拆解:
Rs * Id和Rs * Iq是电阻压降,低速时占主导。Ld * dId/dt和Lq * dIq/dt是电感上的感应电压,电流变化越快这项越大。-ωe * Lq * Iq和+ωe * (Ld * Id + ψf)是旋转反电动势和交叉耦合项,转速越高这项越大。
这里最关键的是最后两项。ωe * ψf就是永磁体产生的反电动势,它随转速线性增长。当转速升高,反电动势可能接近甚至超过母线电压,这时候就需要弱磁,也就是给负的 Id 来抵消一部分 ψf。而ωe * Lq * Iq和ωe * Ld * Id是交叉耦合项,高速时它们会造成 d 轴和 q 轴之间的相互干扰,好的电流环会做前馈解耦来补偿。
2.3 为什么你的 Ud/Uq 输出看起来"不对"
调试时经常遇到的现象:给定 Iq 是正的,但电机反转;或者 Ud 一直是正的很大值,电机却不转。这通常是几个原因:
第一,电角度方向搞反了。如果编码器或观测器给出的角度递增方向和实际转子旋转方向相反,Park 变换出来的 Id/Iq 就是错的,整个控制就乱了。判断方法很简单:手动转一下电机,看电角度是递增还是递减,和你的旋转方向定义是否一致。
第二,d/q 轴定义和电机实际不符。有些电机的相序定义和你的软件约定不一致,导致 d 轴和 q 轴对调。这时候你会看到给 Iq 电机不转,给 Id 反而转了。
第三,Ud/Uq 的限幅没做对。SVPWM 能输出的最大电压矢量幅值是母线电压除以根号 3(约 0.577 倍母线电压),如果你不做限幅,PI 输出饱和后积分项会累积,导致恢复时严重超调。
注意:Ud/Uq 的限幅应该是圆限幅,即 sqrt(Ud² + Uq²) ≤ Umax,而不是分别对 Ud 和 Uq 限幅。分别限幅会导致电压矢量方向畸变,电流波形失真。
3. 控制频率怎么选:不是越高越好
控制频率的选取是个权衡问题。频率高,电流环带宽可以做得更高,动态响应快;但频率高也意味着 CPU 负担重、开关损耗大、ADC 采样窗口变窄。这一节讲清楚怎么根据应用场景选控制频率。
3.1 控制频率与 PWM 频率的关系
前面提到,最常见的是控制频率等于 PWM 频率。但这里有个细节:PWM 频率决定了开关损耗和电流纹波,控制频率决定了电流环的更新速率。两者可以解耦。
比如一些大功率应用,为了降低开关损耗,PWM 频率只有 4kHz 到 8kHz,但控制频率可以做到 16kHz,方法是利用 PWM 周期内的多次采样,或者用更高的控制中断频率但只在特定时刻更新占空比。不过这种做法对时序要求很高,新手不建议碰。
对于大多数中小功率应用,PWM 频率取 10kHz 到 20kHz 是主流。10kHz 以下人耳能听到啸叫,20kHz 以上开关损耗明显增加。我一般推荐 16kHz 或 20kHz,兼顾了噪声、损耗和控制性能。
3.2 带宽、响应速度与稳定性的三角关系
电流环带宽决定了电流跟踪给定的速度。带宽越高,电流响应越快,但稳定性越差。这三者的关系可以用一个经验公式来理解:
电流环带宽 ≈ 控制频率 / (10 ~ 20)假设控制频率 20kHz,带宽取 1kHz 到 2kHz。如果你需要更快的电流响应,比如用于高性能伺服,那就得提高控制频率,比如做到 40kHz,带宽才能上到 2kHz 到 4kHz。
但带宽不是越高越好。带宽高意味着对噪声更敏感,电流采样噪声会被放大,导致电流波形毛刺增多。而且带宽高对电角度精度要求也更高,角度误差在高速时会被放大。所以选带宽要结合你的实际需求:一般工业应用 500Hz 到 1kHz 足够,高性能伺服可以到 2kHz 以上。
3.3 不同应用场景的频率选型参考
| 应用场景 | PWM 频率 | 控制频率 | 电流环带宽 | 说明 |
|---|---|---|---|---|
| 风机水泵 | 8-10kHz | 8-10kHz | 300-500Hz | 对动态要求低,重效率 |
| 通用工业 | 10-16kHz | 10-16kHz | 500Hz-1kHz | 平衡性能与成本 |
| 高性能伺服 | 16-20kHz | 16-20kHz | 1-2kHz | 动态响应优先 |
| 高速电机 | 20-40kHz | 20-40kHz | 2-4kHz | 基波频率高,需高载波 |
| 低速大扭矩 | 10-16kHz | 10-16kHz | 500Hz-1kHz | 重点在低速观测 |
这张表是我自己项目里总结的经验值,实际选型还要看 MCU 算力、功率器件能力和电机参数。比如你的 MCU 主频只有 100MHz,跑 20kHz 控制频率可能算力就不够了,那就得降到 10kHz 或者优化算法。
4. HFI 高频注入:低速无感的关键技术
高速无感靠反电动势观测,低速时反电动势太小,观测器失效,这时候就得靠高频注入(HFI)。HFI 的原理是往电机里注入一个高频电压信号,利用电机的凸极效应(Ld ≠ Lq)来提取转子位置信息。这一节讲 HFI 的注入频率怎么选、注入信号怎么设计、以及实际调试中的坑。
4.1 HFI 的基本原理:为什么凸极电机才能用
HFI 的核心假设是电机有凸极效应,也就是 Ld 和 Lq 不相等。注入高频电压后,高频电流的响应幅值会随转子位置变化,因为 d 轴和 q 轴的高频阻抗不同。通过解调高频电流的幅值或相位,就能提取出转子位置。
对于表贴式电机(SPMSM),Ld ≈ Lq,凸极效应很弱,HFI 效果很差。这时候要么用其他方法(如 INFORM 法、旋转高频注入配合饱和凸极),要么就得接受低速性能受限。而内置式电机(IPMSM)凸极比通常在 1.5 到 3 之间,HFI 效果很好。
所以选 HFI 之前,先确认你的电机有没有凸极。如果是表贴式,别硬上 HFI,效果会让你失望。
4.2 注入频率与 PWM 频率的关系
这是 HFI 调试中最关键的一个参数。注入频率通常取 PWM 频率的 1/2 到 1/10。为什么?
注入频率太高,接近 PWM 频率,会和高频开关噪声混在一起,难以分离;注入频率太低,又会被电流环的带宽滤掉,提取不到有效信号。经验值是注入频率取 PWM 频率的 1/4 到 1/6 比较合适。
比如 PWM 频率 10kHz,注入频率取 1.5kHz 到 2.5kHz。这个频率既在电流环带宽之外(电流环带宽通常 500Hz 到 1kHz),又远低于 PWM 频率,方便用带通滤波器提取。
注入信号的幅值也要注意。幅值太小,信噪比不够;幅值太大,会产生转矩脉动和噪声。一般取额定电压的 5% 到 15%。我实测下来,10% 左右是个不错的起点。
4.3 旋转注入与脉振注入的选择
HFI 有两种主流注入方式:
旋转高频注入:在 αβ 坐标系注入一个旋转的电压矢量,频率为 ωh。这种方法实现简单,但会产生转矩脉动,而且对凸极位置的正负判断需要额外处理。
脉振高频注入:在估计的 d 轴方向注入高频电压,通过 q 轴高频电流的响应来判断角度误差。这种方法转矩脉动小,而且可以直接得到角度误差信号,适合做闭环跟踪。
我一般推荐脉振注入,虽然实现稍复杂,但性能更好,尤其是低速重载时。脉振注入的信号流程是:在估计 d 轴注入Uh * cos(ωh * t),然后提取 q 轴电流中的高频分量,经过解调和低通滤波后得到角度误差,送入 PLL 或锁相环跟踪转子位置。
4.4 转子初始位置检测的实操细节
HFI 最典型的应用就是转子初始位置检测。上电时转子位置未知,如果直接开环启动,可能会反转或者启动失败。用 HFI 可以在不转动电机的情况下检测出转子位置。
实操步骤:
- 在估计 d 轴注入高频电压,幅值和频率按前面说的选。
- 采样 q 轴高频电流,解调出包含位置误差的信号。
- 用 PLL 跟踪,让估计角度收敛到实际角度。
- 收敛后,估计角度就是转子初始位置。
这里有几个坑:
第一,收敛时间。PLL 的带宽决定了收敛速度,带宽太低收敛慢,带宽太高会振荡。一般取几十 Hz 到一百 Hz 比较合适,收敛时间在几百毫秒量级。
第二,凸极的极性判断。HFI 只能判断出转子的轴线方向,但分不清 N 极和 S 极,也就是有 180 度电角度的模糊。解决方法是在估计的 d 轴正反两个方向分别注入,利用磁饱和效应判断极性。具体做法是注入正负脉冲,比较电流响应的幅值,幅值大的方向是 N 极。
第三,负载影响。如果电机带载启动,负载转矩会影响初始位置检测的精度。这时候可以适当增大注入幅值,提高信噪比。
提示:初始位置检测完成后,不要立刻切到高速观测器,而是先用 HFI 闭环跑一段低速,等转速稳定后再平滑切换到反电动势观测。切换过程要做角度和速度的平滑过渡,否则会冲击。
5. 从 HFI 到高速观测器的平滑切换
低速用 HFI,高速用反电动势观测器,这是无感 FOC 的标准架构。但两者怎么切换,切换点怎么选,是另一个容易出问题的地方。
5.1 切换点的选择依据
切换点通常选在反电动势足够大、观测器能稳定工作的转速。这个转速一般是额定转速的 5% 到 10%。太低,反电动势信噪比不够;太高,HFI 的转矩脉动和噪声已经不可接受。
具体怎么定?我的做法是:先在 HFI 模式下把转速慢慢升上去,同时观察反电动势观测器的输出。当观测器的估计角度和 HFI 的估计角度基本一致时,说明观测器已经能跟上,这时候就是切换点。
5.2 混合观测与加权过渡
直接硬切换会有冲击,因为两个观测器的估计角度可能有偏差。常用的做法是加权过渡:在切换区间内,用权重系数把两个观测器的角度和速度按比例混合。
θ_est = (1 - k) * θ_hfi + k * θ_bemf ω_est = (1 - k) * ω_hfi + k * ω_bemf其中 k 从 0 平滑过渡到 1。过渡区间可以取切换点附近 ±20% 的转速范围。这样切换过程平滑,不会造成转矩冲击。
5.3 切换过程中的常见问题
最常见的问题是切换后转速波动或者失步。原因通常是两个观测器的角度有稳态偏差,或者速度估计不一致。解决方法是在切换前先做角度对齐,把两个观测器的角度偏差补偿掉。
另一个问题是切换点附近来回切换,造成系统不稳定。这是滞环没做好,应该设置一个切换区间,进入高速用高阈值,退回低速用低阈值,中间有滞环避免频繁切换。
6. 调试实战:一个完整的中断服务函数该怎么写
讲了这么多原理,最后落到代码上。这一节给一个 FOC 中断服务函数的骨架,把前面讲的时序、Ud/Uq 计算、HFI 注入都串起来。
6.1 中断服务函数的执行顺序
void FOC_ISR(void) { // 1. 读取相电流(ADC 已由 PWM 触发完成转换) ia = ADC_ReadPhaseA(); ib = ADC_ReadPhaseB(); ic = -(ia + ib); // 2. Clarke 变换 i_alpha = ia; i_beta = (ia + 2*ib) * ONE_BY_SQRT3; // 3. 获取电角度(HFI 或观测器) theta = Get_Electrical_Angle(); // 4. Park 变换 id = i_alpha * cos(theta) + i_beta * sin(theta); iq = -i_alpha * sin(theta) + i_beta * cos(theta); // 5. 电流 PI 调节 ud = PI_Id(id_ref - id); uq = PI_Iq(iq_ref - iq); // 6. 前馈解耦(可选,高速时建议加) ud -= omega_e * Lq * iq; uq += omega_e * (Ld * id + psi_f); // 7. 电压限幅(圆限幅) Limit_Voltage_Circle(&ud, &uq, U_max); // 8. 反 Park 变换 u_alpha = ud * cos(theta) - uq * sin(theta); u_beta = ud * sin(theta) + uq * cos(theta); // 9. SVPWM 计算并更新比较寄存器 SVPWM_Update(u_alpha, u_beta); // 10. HFI 注入(如果使能) if (hfi_enable) { HFI_Inject_And_Demodulate(); } }这个顺序是有讲究的。电流采样必须在最前面,因为后面所有计算都依赖它。角度获取要在 Park 变换之前。前馈解耦放在 PI 之后、限幅之前,这样解耦项也参与限幅。HFI 注入放在最后,因为它不影响本周期的电流环,只影响下一周期的角度估计。
6.2 几个容易写错的地方
第一,Clarke 变换的系数。不同文献的系数不一样,有的是 2/3,有的是 1。关键是 Park 变换和反 Park 变换要配套,保证正反变换能还原。我习惯用等幅值变换,Clarke 系数取 2/3,这样电流幅值不变。
第二,电角度的单位。三角函数库一般用弧度,但有些编码器输出的是角度制,转换时别忘了乘 π/180。
第三,SVPWM 的扇区判断。扇区判断错误会导致输出电压矢量方向错误,电机直接不转或者抖动。建议先用开环测试 SVPWM,给定固定的 u_alpha 和 u_beta,用示波器看三相占空比是否正确。
6.3 用示波器验证 FOC 时序的实操方法
调试 FOC,示波器是必备的。我一般会看这几个信号:
- 三相 PWM 波形:看死区、看占空比是否对称。
- 相电流波形:看正弦度、看毛刺。
- 中断 GPIO 翻转:看中断执行时间。
- 电角度和电流的相位关系:用 DAC 输出电角度和 iq,看是否正交。
如果相电流波形有周期性毛刺,通常是采样时刻不对,或者死区补偿没做好。如果电流波形正弦度差,可能是电角度不准或者 PI 参数不对。这些都要结合波形一点点排查。
7. 那些文档里不会写的踩坑经验
最后分享几个我在实际项目中踩过的坑,都是文档里不会写、但实际调试中一定会遇到的。
7.1 电流采样偏置的温漂问题
电流采样运放的偏置电压会随温度漂移,导致采样到的电流有直流偏置。这个偏置在 Park 变换后会变成 Id 和 Iq 的直流分量,造成转矩脉动。解决方法是在上电时做偏置校准,运行中定期校准,或者用高通滤波器滤掉直流分量。我一般在上电时校准一次,运行中如果发现 Id 有直流偏置,再触发一次校准。
7.2 死区补偿的时机
死区是为了防止上下桥臂直通,但死区会造成输出电压偏差,尤其在低速小电流时明显。死区补偿要根据电流方向来补偿,但电流过零时方向判断不准,容易造成补偿错误。我的做法是在电流过零附近不补偿,或者用平滑过渡,避免补偿抖动。
7.3 HFI 注入带来的噪声和振动
HFI 注入会产生可听噪声和轻微振动,这是原理决定的,无法完全消除。但可以通过优化注入频率来避开人耳敏感频段(2kHz 到 5kHz),或者用随机注入频率来分散噪声。如果应用对噪声敏感,可以考虑用其他低速观测方法,比如 INFORM 法或者基于饱和凸极的方法。
7.4 参数辨识的重要性
FOC 的性能很大程度上取决于电机参数(Rs、Ld、Lq、ψf)的准确性。这些参数会随温度和电流变化,尤其是 Ld 和 Lq 会随电流饱和而变化。如果参数不准,前馈解耦和 MTPA 都会失效。建议在调试前先做参数辨识,运行中如果发现性能下降,再重新辨识。
注意:参数辨识时电机要处于静止或者已知状态,辨识过程中不要加载,否则会影响辨识精度。
7.5 从有感到无感的过渡建议
如果你已经跑通了有霍尔或者有编码器的 FOC,想上无感,我的建议是分步走:先用有传感器跑通电流环和速度环,确认基本控制没问题;然后加上观测器,但先不切换,只是对比观测器角度和传感器角度;等观测器角度能稳定跟踪后,再切换到无感。这样每一步都有验证,出问题容易定位。
HFI 的调试也是类似,先在开环下验证注入和解调能正确提取位置,再闭环跟踪,最后再和高速观测器切换。每一步都验证到位,比一次性全上要靠谱得多。
这套流程我在好几个项目里用过,从风机到伺服都适用。核心就一句话:把每个环节的时序和物理意义搞清楚,调试就不是碰运气,而是有章可循的工程过程。