
1. 高频注入无感 FOC 的整体设计思路1.1 为什么低速段必须靠高频注入无感 FOC 在中小功率电机驱动里已经非常成熟反电动势观测器、滑模观测器这些方案在中高速段跑得都挺稳。但一旦转速掉到额定转速的百分之几反电动势幅值小到几乎淹没在采样噪声里观测器就彻底失效了。这时候如果还要闭环控制就必须换一种激励方式——高频注入HFIHigh Frequency Injection就是干这个的。它的核心思想很朴素既然转子凸极效应会让 d 轴和 q 轴的电感不一样那我就往定子绕组里打一个高频电压信号让高频电流的响应里带上转子位置的信息再把这个信息解调出来就能估计出转子角度。整个过程不依赖反电动势所以零速和极低速都能用。我见过不少刚接触 HFI 的朋友第一反应是“这不就是加个正弦波吗”。实际上难点根本不在“加信号”而在“怎么把位置信息从高频响应里干净地抠出来”。抠不干净估计角度就会抖抖了之后电流环跟着抖最后整机啸叫。所以这篇文章我会把 HFI 的信号链、IIR 滤波器的设计、位置估计的解调过程、以及磁极极性判断这几个环节从代码层面一层层拆开讲。1.2 整体信号链的拆解一套完整的 HFI 无感 FOC信号链大致是这样的在估计的 d 轴或者 αβ 轴上叠加一个高频电压矢量常见的是旋转电压注入或脉振电压注入高频电压激励下电机产生高频电流响应这个响应里包含转子位置误差信息采样三相电流经过 Clarke/Park 变换把高频分量提取出来用带通滤波或者同步解调的方式把高频电流里的位置误差信号分离通过低通滤波这里就会用到 IIR得到位置误差的直流分量用锁相环PLL或者反正切把误差收敛到零输出估计角度和估计转速在启动前或者启动瞬间还要做一次磁极极性判断确认估计出来的 N 极方向没搞反。这条链里IIR 滤波器出现在好几个位置电流采样后的抗混叠、高频提取后的低通、PLL 环路滤波。它的参数直接决定了带宽、相位延迟和噪声抑制能力是整个 HFI 能不能跑稳的关键之一。1.3 方案选型的几个取舍HFI 的注入方式主要有两类旋转电压注入和脉振电压注入。旋转注入是在 αβ 轴上打一个旋转的高频矢量实现简单但会产生转矩脉动噪声也大。脉振注入是在估计的 d 轴上打一个脉振信号q 轴不注入转矩脉动小很多缺点是位置误差信号的提取需要更精细的解调。我在实际项目里更倾向脉振注入尤其是对噪声敏感的应用。代价是解调部分代码复杂一点需要做同步解调把高频载波和位置误差分离。下面这张表是我总结的两种方式对比选型时可以直接参考对比项旋转电压注入脉振电压注入注入轴αβ 轴旋转矢量估计 d 轴脉振转矩脉动较大较小噪声表现高频啸叫明显相对安静解调复杂度低中高低速精度一般较好适用场景对噪声不敏感家电、风机等静音要求高选脉振注入的话注入频率一般取 PWM 频率的 1/4 到 1/2比如 10kHz 载波注入 2.5kHz 到 5kHz。注入幅值通常是额定电压的 10% 到 20%太小了信噪比不够太大了会引入额外损耗和噪声。2. 核心细节解析与实操要点2.1 高频注入信号的生成脉振注入的电压表达式在估计的 d 轴上是这样的Vd_inj Vh * cos(ωh * t) Vq_inj 0其中 Vh 是注入幅值ωh 是注入角频率。代码里通常不会真的去算 cos而是用一个查表或者递推的方式生成。我一般用一个相位累加器加正弦表这样效率高也方便和 PWM 中断同步。// 高频注入信号生成简化示意 static float hfi_phase 0.0f; static const float HFI_STEP 2.0f * PI * HFI_FREQ / PWM_FREQ; hfi_phase HFI_STEP; if (hfi_phase 2.0f * PI) hfi_phase - 2.0f * PI; float vd_inj HFI_AMP * sinf(hfi_phase); float vq_inj 0.0f;这里有个细节注入信号的相位最好和 PWM 载波同步否则采样时刻和注入时刻对不齐解调出来的误差信号会有额外纹波。我一般把注入相位累加放在 PWM 中断的最开始保证每个载波周期注入一次采样也在固定时刻进行。注意注入幅值不要超过母线电压的 20%否则可能触发过调制导致电流波形畸变反而破坏位置估计。2.2 高频电流响应的提取注入电压之后电流里会同时包含基波分量和高频分量。基波是电机正常运转需要的高频分量才是我们要的位置信息。所以第一步是把高频分量从总电流里分离出来。常见做法是用一个带通滤波器中心频率设在注入频率 ωh。但带通滤波器会引入相位延迟而且阶数高了计算量大。我更喜欢用同步解调的方式把采样电流乘以一个和注入信号同频的参考信号然后低通滤波。具体来说假设采样到的 d 轴电流是 id里面包含高频分量 id_h。同步解调就是id_demod id * cos(ωh * t)乘完之后id_h 里和 cos 同相的部分会变成直流加二倍频不同相的部分变成二倍频。再用一个低通滤波器把二倍频滤掉剩下的直流就正比于位置误差。// 同步解调 float id_demod id_sample * cosf(hfi_phase); // 低通滤波提取直流分量 float id_error lpf_iir(id_demod);这个低通滤波器就是 IIR 出场的地方。它的截止频率要远低于二倍注入频率但又不能太低否则动态响应跟不上。我一般取注入频率的 1/10 到 1/5 作为截止频率。2.3 IIR 滤波器的设计与实现IIR 滤波器相比 FIR最大的优势是同样的滤波效果下阶数低、计算量小非常适合在 MCU 上跑。缺点是相位非线性设计不好容易不稳定。在 HFI 里我用得最多的是二阶巴特沃斯低通因为它通带平坦相位延迟相对可控。二阶 IIR 低通的差分方程是y[n] b0*x[n] b1*x[n-1] b2*x[n-2] - a1*y[n-1] - a2*y[n-2]系数可以用双线性变换从模拟滤波器映射过来。假设截止频率 fc采样频率 fs先算归一化频率ωc 2 * π * fc / fs然后算预畸变K tan(ωc / 2)二阶巴特沃斯的系数b0 K^2 / (1 sqrt(2)*K K^2) b1 2*b0 b2 b0 a1 2*(K^2 - 1) / (1 sqrt(2)*K K^2) a2 (1 - sqrt(2)*K K^2) / (1 sqrt(2)*K K^2)代码实现typedef struct { float b0, b1, b2, a1, a2; float x1, x2, y1, y2; } IIR_LPF; float iir_lpf(IIR_LPF *f, float x) { float y f-b0 * x f-b1 * f-x1 f-b2 * f-x2 - f-a1 * f-y1 - f-a2 * f-y2; f-x2 f-x1; f-x1 x; f-y2 f-y1; f-y1 y; return y; }这里有个坑系数算出来之后最好用定点或者 Q 格式存储浮点虽然方便但在一些低端 MCU 上跑起来慢。另外滤波器的状态变量要初始化否则上电瞬间会有冲击。提示IIR 滤波器的截止频率不要设得太低否则相位延迟会吃掉系统的相位裕度导致 PLL 振荡。我一般把截止频率设在注入频率的 1/10 左右实测下来比较稳。2.4 位置误差信号的解调同步解调之后得到的 id_error理论上正比于 sin(2*Δθ)其中 Δθ 是估计角度和真实角度的误差。为什么是 2 倍因为凸极效应的电感变化周期是电角度周期的一半所以位置误差信号也是 2 倍频。小误差下sin(2Δθ) ≈ 2Δθ所以可以直接把 id_error 当作误差信号送给 PLL。PLL 的结构就是一个 PI 控制器加一个积分器// PLL 环路 float pll_error id_error; float speed_est pll_kp * pll_error pll_ki * pll_integral; pll_integral pll_error; float angle_est speed_est * Ts;这里 pll_kp 和 pll_ki 的整定很关键。kp 太大角度会抖ki 太大收敛慢还容易超调。我一般先用 kp 把带宽撑起来再用 ki 把稳态误差压下去。经验值是 kp 对应带宽 20 到 50Hzki 是 kp 的 1/10 到 1/5。2.5 磁极极性判断的必要性HFI 估计出来的角度有一个天然的模糊它只能分辨出转子的轴线但分不清 N 极和 S 极。因为凸极效应是对称的d 轴正方向和负方向的电感变化是一样的。所以估计角度可能和真实角度差 180 度。如果不做极性判断电机启动时可能反转或者直接堵转。判断方法有几种脉冲注入法在估计的 d 轴正负方向分别注入短时电压脉冲比较电流响应幅值。由于磁饱和正方向的电感会略小电流上升更快。高频注入法利用二次谐波或者 d 轴电流的直流偏置来判断。直接观察法给一个小的 d 轴电流看电机是否转动。我常用的是脉冲注入法实现简单可靠性也高。具体做法是// 极性判断 float id_pos inject_pulse_and_measure(V_PULSE); float id_neg inject_pulse_and_measure(-V_PULSE); if (id_pos id_neg) { // 估计角度正确 } else { // 估计角度需要加 180 度 angle_est PI; }脉冲幅值一般取额定电流的 50% 到 100%持续时间几百微秒。太短了响应不明显太长了电机会动。注意极性判断只在启动前做一次运行中不需要重复。如果电机已经转起来了再做脉冲注入会干扰正常控制。3. 实操过程与核心环节实现3.1 从零搭建 HFI 的代码框架我一般把 HFI 的代码分成几个模块注入信号生成、电流采样与变换、同步解调、IIR 滤波、PLL、极性判断。每个模块放在 PWM 中断里按顺序执行。PWM 中断的流程大致是读取三相电流做 Clarke 变换得到 iα、iβ用估计角度做 Park 变换得到 id、iq生成高频注入信号叠加到 d 轴电压上对 id 做同步解调得到 id_demod用 IIR 低通滤波得到 id_error把 id_error 送给 PLL更新估计角度和转速电流环计算输出 PWM 占空比。这个顺序很重要注入和采样要错开避免采样时刻正好在注入跳变沿上。我一般把采样放在 PWM 周期的中点注入放在周期开始。3.2 参数计算与整定过程注入频率的选择要考虑几个因素PWM 频率、电流环带宽、电机电感。经验公式是f_inj f_pwm / 4 到 f_pwm / 2比如 10kHz PWM注入 2.5kHz 到 5kHz。注入频率太高电流响应幅值小信噪比差太低又会和基波耦合解调不干净。注入幅值的计算可以用这个公式估算Vh Ih * ωh * Ld其中 Ih 是期望的高频电流幅值一般取额定电流的 10% 到 20%。Ld 是 d 轴电感。比如 Ih 0.5Aωh 2π*3000Ld 5mH算出来 Vh ≈ 47V。实际还要考虑母线电压限制如果算出来超过母线电压的 20%就要降低 Ih 或者 ωh。IIR 截止频率的整定我一般先用注入频率的 1/10然后看 id_error 的波形。如果纹波大就降低截止频率如果响应慢就提高。实测下来截止频率在 200Hz 到 500Hz 之间比较合适。PLL 参数整定先用 kp 把角度跟踪调快再加 ki 消除稳态误差。我一般用阶跃响应来调给一个角度阶跃看估计角度的超调和收敛时间。kp 对应带宽 30Hz 左右ki 是 kp 的 1/8。3.3 实测波形与调试记录我第一次调 HFI 的时候id_error 的波形一直很脏角度估计抖得厉害。后来发现是同步解调的参考信号相位不对和注入信号差了 90 度。把相位对齐之后id_error 就干净多了。还有一次电机启动时偶尔反转。查了半天发现是极性判断的脉冲太短电流还没上升到可比较的程度就结束了。把脉冲时间从 200us 加到 500us问题就解决了。下面这张表是我调试过程中记录的一些典型现象和对应原因现象可能原因解决方法角度估计抖动大IIR 截止频率太高降低截止频率启动反转极性判断错误加长脉冲时间增大脉冲幅值电流啸叫明显注入幅值太大降低注入幅值低速时角度漂移PLL 带宽太低提高 kpid_error 有直流偏置电流采样偏置校准电流采样3.4 代码层面的优化技巧HFI 的计算量不小尤其是在低端 MCU 上。我一般会做这几件事正弦表用查表加线性插值避免实时算 sinfIIR 滤波器用定点运算Q15 格式速度快PLL 的积分器用饱和处理防止积分饱和同步解调的乘法用移位代替如果注入频率是 2 的幂次分频。还有一个技巧把注入信号和 PWM 载波同步这样采样时刻固定解调参考信号的相位也固定省去了相位跟踪的麻烦。4. 常见问题与排查技巧实录4.1 角度估计不准的排查思路角度估计不准表现是电机运行不平稳电流波形畸变严重时直接失步。排查的时候我一般按这个顺序来先看 id_error 的波形。如果波形很脏说明解调或者滤波有问题。检查同步解调的参考信号相位检查 IIR 滤波器的截止频率和系数。如果 id_error 干净但角度还是不准看 PLL 的参数。kp 太小跟踪慢kp 太大抖动。可以给一个角度阶跃看估计角度的响应。如果以上都没问题检查电流采样。采样偏置、采样延迟、采样时刻不对都会导致角度估计偏差。我遇到过采样电阻温漂导致偏置变化最后角度慢慢偏掉的情况。4.2 IIR 滤波器不稳定怎么办IIR 滤波器不稳定通常是系数算错了或者状态变量溢出。先检查系数用 MATLAB 或者 Python 算一遍和代码里的对比。然后检查状态变量是不是用了浮点但实际是定点导致精度不够。还有一个常见原因是截止频率设得太低导致极点靠近单位圆数值精度不够就发散了。这时候要么提高截止频率要么用更高精度的定点格式。提示IIR 滤波器的系数最好用双精度算然后转成单精度或者定点。直接用单精度算系数误差可能比较大。4.3 极性判断失败的几种情况极性判断失败电机启动时可能反转或者堵转。常见原因有脉冲幅值太小电流响应差异不明显脉冲时间太短电流还没上升到可比较的程度电机已经有一点转动初始位置不确定磁饱和不明显正负方向电感差异小。解决方法增大脉冲幅值到额定电流的 80% 到 100%加长脉冲时间到 500us 到 1ms确保电机静止。如果还是不行可以改用二次谐波法或者直接给一个小的 d 轴电流看电机是否转动。4.4 常见问题速查表问题排查方向快速解决电机不转注入信号是否生成检查注入幅值和频率电机反转极性判断加长脉冲增大幅值电流啸叫注入幅值降低到 10% 额定角度抖动IIR 和 PLL降低截止频率调 kp低速失步PLL 带宽提高 kp检查解调相位高速切换失败观测器切换检查切换阈值和过渡4.5 一些踩过的坑和心得我最开始做 HFI 的时候以为注入频率越高越好结果信噪比反而差了。后来才明白注入频率高电流响应幅值小ADC 量化噪声占比就大。所以注入频率要折中一般 2kHz 到 5kHz 比较合适。还有一次IIR 滤波器的状态变量没初始化上电瞬间输出一个很大的冲击直接把 PLL 冲乱了。后来养成习惯所有滤波器状态变量上电清零。极性判断的脉冲注入一定要在电机完全静止的时候做。如果电机还在惯性转动判断结果就不可靠。我一般会在启动前加一个延时确保电机停稳。最后HFI 的参数不是一成不变的不同电机、不同负载最优参数都不一样。我一般会留一组可调参数方便现场整定。整定的时候先调注入幅值和频率再调 IIR 截止频率最后调 PLL 参数。这个顺序实测下来效率最高。这个内容后续还可以这样扩展把 HFI 和中高速的观测器结合起来做全速域的无感控制切换点的平滑过渡又是一个可以深挖的话题。