做无感FOC的人其实都清楚,高速段靠反电动势观测器越用越顺,可一旦转速掉到额定转速的5%以下,整套系统就像喝了假酒,角度漂到完全没法用。我这次用STM32F4把高频注入完整工程从头到尾搭了一遍,从原理图上的采样电阻选型到源代码里的解调环路,全部集成在一个工程里。这篇文章就是把我这个完整工程的关键决策和踩坑过程拆开讲清楚,尤其是“源代码+原理图”这两条线怎么对齐,适合正在做低速无感、压缩机启动、伺服堵转或者想复现高频注入算法的朋友。
先说结论:高频注入不是玄学,它就是利用电机转子凸极性做位置观测。原理不复杂,但工程里有大量细节会让你的算法“看起来对、跑起来飘”。下面我从为什么必须用、平台选型、代码拆解、原理图设计到完整调试流程,一层层讲。
1. 为什么在低速段必须上高频注入,以及我踩过的速度观测坑
1.1 反电动势法的低速盲区是从哪里来的
无感FOC最常用的位置观测手段是观测反电动势,无论是滑模观测器还是龙伯格观测器,本质上都是拿电机模型去“预估”反电动势,再从反电动势里提取转子角度。这里的问题在于:反电动势大小和转速成正比。额定转速3000rpm的电机,在30rpm时反电动势只剩1%,而采样噪声、PWM死区引起的谐波、电流采样偏置这些“垃圾信号”可不会按比例缩小。信噪比一旦恶化,观测器的增益就只能在“收敛快”和“抗噪强”之间做艰难取舍,最后往往两边都不讨好。
我当时在一个低速伺服项目里试过把观测器增益调软、把滤波器带宽压到很低,结果是角度勉强能看,但一转起来有明显的滞后,负载稍微一变就开始震荡。后来意识到,这条路在极低速下本质是死路,因为信号本身已经淹没在噪声里了,滤波做得再好也只是把有用的残骸捞出来那么一点,根本不够用。
1.2 高频注入到底在测什么(凸极效应)
高频注入换了一条路:不等电机转起来产生反电动势,而是主动给电机注入一个高频电压激励,然后通过检测电流响应的差异来推算转子位置。它能工作的核心在于“凸极效应”:内嵌式永磁同步电机(IPMSM)的转子磁路不对称,d轴电感通常小于q轴电感。转子位置不同,对同一高频电压激励呈现出来的阻抗也不同,电流响应里就携带了转子角度信息。
这个原理可以类比成用声呐探测水下物体:主动发一束声波出去,根据回波判断目标方位。高频注入就是持续向电机“发声”,电流采样就是“听回波”。你不需要知道反电动势有多大,只需要关心高频电流分量的幅度和相位,这两个量在零速和低速时依然存在,不会消失。所以高频注入特别适合零速和低速场景,比如压缩机启动前转子还停在某个未知位置,或者伺服系统堵转时仍然需要维持力矩。
1.3 我为什么选PMSM项目作为落地载体
高频注入不是对所有电机都有效。最理想的对象是凸极率足够的IPMSM,也就是d轴电感和q轴电感差异明显的电机。表贴式永磁同步电机(SPM)虽然反电动势波形好,但转子磁路接近对称,凸极率接近1,高频电流响应里几乎没有角度信息,硬要注水也提炼不出来。
我这次选的是一台“某小型内嵌式永磁电机”,额定功率400W,极对数4,凸极率大概在1.5倍左右。这种电机做高频注入很合适,因为位置信息幅度够大,调理电路和解调代码都有余量。如果凸极率只有1.1,你就不得不用更复杂的信号处理,对硬件设计的要求也更高,新手很可能被噪声折磨到怀疑人生。所以我的第一个建议是:前期选电机时,先确认凸极率,不要拿一台啥参数都没有的电机就开始写高频注入。
2. STM32F4平台的选型权衡与工程框架划分
2.1 为什么选STM32F4而不是F3/G4
STM32F4在这个项目里是我比较之后确定下来的平台。它主频168MHz,带FPU,做三相FOC加高频解调完全没有压力。更重要的是,它的ADC支持双通道同步采样,配合高级定时器能在PWM中心时刻精准触发电流采样,这对高频注入来说非常关键。高频注入的电流响应信号不像反电动势那么大,如果ADC采样时刻抖动几十ns,解调出来的误差信号就会带上一堆毛刺。
有人会问,STM32G4不是主频更高还有CORDIC硬件加速吗?确实,G4做电机控制很香,尤其是算Park变换和三角函数时能省不少CPU。但我当时手里这批STM32F4的库存和现有驱动板兼容性更好,而且高频注入解调本身不是算力瓶颈,真正难的是信号调理和时序同步。F4的电容、定时器、ADC资源完全够用,开发资料也比G4多,与其换平台折腾,不如把精力放在算法和硬件上。
2.2 源代码工程的模块划分:从ADC到注入信号生成
我把完整工程按功能拆成几个独立模块,不搞一锅炖。这样某个环节出问题时,能快速定位是采样问题、解调问题还是角度切换问题。核心模块如下:
bsp_adc:ADC初始化,负责三相电流和母线电压采样,并处理过采样。bsp_pwm:高级定时器PWM生成,配置中心对齐模式和PWM触发ADC事件。motor_foc:电流环、速度环以及Clarke/Park变换,输出d/q轴电压指令。motor_hfi:高频注入信号生成、高频电流提取、位置误差解调。observer_pmsm:角度跟踪观测器,负责低速高频注入和高速反电动势之间的切换。comm_task:上位机通信,用于在线调参和波形导出。
数据流向是:PWM触发ADC采样,得到三相电流,先做坐标变换得到d/q电流;motor_hfi在低速模式时把一个高频电压叠加到d轴电压指令上,同时从d/q电流里提取出高频分量并解调出位置误差;这个误差送到observer_pmsm里的锁相环,最终估算出转子角度和转速;角度再回送给Park反变换,形成完整闭环。
2.3 原理图集成的几个关键信号链路
源代码和高频注入能不能跑起来,原理图集成占一半。我这里梳理了三条关键信号链路,每一路都有明确的接口定义:
- 功率链路:直流母线输入 → 母线电容 → 三相逆变桥 → 电机相线。这条链路上的走线要尽量短粗,尤其是逆变桥下管的源极到采样电阻之间的连接。
- 采样链路:采样电阻 → RC滤波 → 差分运放 → ADC引脚。这是高频注入最容易出问题的链路,运放带宽、RC参数、ADC采样保持时间都要对齐。
- 控制链路:MCU的PWM输出 → 驱动芯片输入 → 逆变桥栅极 → 相线输出。这条链路要注意驱动芯片的传播延迟,PWM死区时间也要在原理图阶段就预留好。
我把这些链路画成了一张集成检查表,评审原理图时逐项打勾。很多项目高频注入做不出来,不是算法写得差,而是采样链路已经先把高频信号“污染”了,后面无论怎么调都救不回来。
3. 高频注入核心代码逐段拆解:从注入信号到转子角解调
3.1 高频电压信号的产生与注入方式
高频注入有旋转电压注入和脉振电压注入两种主流方式。旋转注入把高频电压矢量叠加在静止坐标系上,电流响应里同时包含正负序分量,解调时要把负序分量分离出来;脉振注入则是把高频电压只叠加在估计转子坐标系的d轴上,q轴高频电流响应直接反映位置误差,算法实现更简单,适合在MCU里实时跑。
我采用的是脉振高频电压注入,注入频率选在1kHz,幅值初始给10V。频率选择有讲究:太高会被PWM开关频率的边带和谐波干扰,太低又会耦合进电流环的带宽范围。1kHz对10kHz的PWM载波来说有十倍差距,滤波容易分开,又不至于要求电流采样率太高。注入幅值也不能过大,过大会产生额外转矩脉动和噪声,过小则位置误差信号弱,我最后通过实测标定取的是一个折中值。
代码上我直接用FOC中断里叠加电压指令:
// 高频注入信号生成,与FOC周期同步 float hfi_voltage = hfi_amp * arm_sin_f32(hfi_angle); // 叠加到估计d轴电压指令上 v_d_inj = v_d_ref + hfi_voltage; v_q_inj = v_q_ref;这里的hfi_angle按注入频率递增,每次FOC中断更新一次。需要注意,注入信号必须和PWM中断严格同步,否则注入的相位会漂移,解调出来的误差信号就会不稳定。我一开始图省事在低优先级任务里弄了个定时器生成注入信号,结果角度观测器一直收敛不到零,最后改成在FOC中断里统一生成才解决。
3.2 三相电流采样与带通/同步解调的工程实现
电流采样是高频注入的“耳朵”。我从ADC拿到三相电流后,先做Clarke变换得到i_alpha和i_beta,再做Park变换得到i_d和i_q。因为注入信号是加在估计d轴上的,高频电流分量会同时出现在d轴和q轴电流里,其中i_q经过解调后最能反映转子位置误差。
直接拿原始i_q去算误差会被基波电流和PWM开关噪声淹没,必须先把高频分量提取出来。我写了两个二阶IIR带通滤波器,中心频率设置在1kHz,分别滤i_d和i_q,然后再做同步解调:
// 对q轴高频电流进行同步解调 float iq_hf = bandpass_iq(i_q); float demodulated = 2.0f * iq_hf * arm_sin_f32(hfi_angle); // 低通滤波得到位置误差 float error = lowpass(demodulated);这里的2.0f不是随便写的,同步解调后高频分量会集中在两倍频上,乘2是为了补偿解调过程中的增益衰减。低通滤波器的截止频率我设在100Hz左右,既能保留位置误差的动态信息,又能滤掉1kHz和2kHz的高频成分。工程实现时我遇到过一个问题:IIR滤波器如果用浮点直接算,系数稍不留神就会因为量化误差产生自激振荡。后来我改用二阶级联形式的滤波器,并且限制了中间变量的幅值,才稳定下来。
3.3 锁相环角度跟踪与低速切入切出的状态机
解调出来的误差信号通常是一个近似正弦的曲线,在零附近与真实位置误差成正比。直接用这个误差去修正角度,会像比例控制器一样残留稳态误差。我的做法是把误差送到一个锁相环(PLL)里:误差信号经PI调节后得到电角速度估计,再积分得到角度估计。PI的输出本质上是一个“转速修正量”,积分后就是不断修正的角度。这才是高频注入能稳定跟踪角度的关键。
// 简化的角度PLL更新 float speed_est = speed_pi_kp * error + speed_pi_ki * integral_error; theta_est += theta_est_last + speed_est * dt_foc;这里要注意初始角度。高频注入在零速时能观测转子位置,但会存在一个“N/S磁极模糊”问题:检测到的角度可能是实际转子角,也可能差了180度。工程上我处理得很直接:先做一个预定位,把d轴电流指令给一个固定值拖动转子到一个已知方向,或者用脉冲电压法做个简单的初始角度粗定位,再切换到高频注入的PLL跟踪。
低速和高速切换也是绕不开的工程问题。高频注入在低速好用,但到了中高速,注入信号反而会成为额外噪声源,还会产生明显的电磁噪声。我设计了一个速度状态机:
- 转速低于10%额定转速时,纯高频注入观测角度。
- 转速在10%到20%之间,高频注入和反电动势观测器并行工作,按速度加权融合。
- 转速超过20%额定转速后,完全切换到反电动势观测器。
切换瞬间如果不做处理,角度会跳变,轻则电流波动,重则过流保护。我在融合区用了一个权重系数k_hfi,角度等于k_hfi * theta_hfi + (1 - k_hfi) * theta_bemf,并用一阶低通平滑权重变化,实测切换冲击降到了可以接受的范围。
4. 原理图设计里最容易被忽略的三个环节
4.1 电流采样运放带宽与相移对高频信号的影响
很多人以为电流采样运放只要“差不多”就行,但高频注入对运放有两个隐藏要求:带宽和建立时间。采样电阻两端产生的是一个很小的差分电压,必须经过运放放大到ADC输入范围。如果运放带宽不够,1kHz的高频分量虽然有幅值衰减,但更关键的是会产生额外相移。高频注入解调对相位很敏感,滤波器本身已经有不少相移,运放再来一点,误差信号的零点就不准了,最后你会发现自己明明追踪到了正确角度附近,PI输出却始终有个偏置。
我这边选的运放是差分放大器结构,增益约20倍,带宽在MHz级别,对付1kHz注入信号绰绰有余。RC滤波参数也要算一下,不能盲目堆大电容。RC截止频率如果压得太低,比如低于5kHz,那1kHz信号虽然能过,但相位会偏移很多。我建议RC截止频率至少放在注入频率的10倍以上,也就是10kHz以上,这样相位偏移还能控制在一个很小的范围内。
4.2 高频注入的PWM载波频率与死区设置
PWM载波我用了10kHz,和注入频率1kHz刚好差十倍,谐波分离比较容易。如果载波只有6kHz,那注入频率就只能选五六百赫兹,解调动态响应会变慢,而且更容易受到电流环带宽影响。反过来如果载波选20kHz,开关损耗变大,驱动芯片和MOS管的温升也会更明显。10kHz是个平衡点。
死区设置在原理图和代码里都要明确。我用的IGBT或MOSFET驱动模块要求死区至少1us,但死区带来的电压误差会在电流里产生低频谐波,这个谐波虽然主要落在基波频率附近,但某些工况下也会污染高频电流。我的处理是:死区时间填0.5us到1us之间,同时在代码里做了一个简单的死区补偿。补偿不追求绝对精确,只需要把电压畸变的趋势抵消掉一大半。如果你发现堵转时的角度抖动明显变大,可以怀疑一下死区补偿没做好。
4.3 地平面与采样点布局:示波器看不到的噪声
高频注入调试时容易被表面现象骗过去:示波器探头夹在ADC引脚上看波形,似乎很干净,但一跑高频注入,角度就是抖。这种噪声往往不是来自模拟信号本身,而是来自地平面。功率部分的地电流很大,如果采样运放的参考地和功率地混在一起,功率开关动作时产生的地弹噪声会直接叠加到采样信号上。
我这次专门把采样电阻的低压侧通过一条单独走线回到MCU的模拟地,模拟地和功率地只在母线电容负极处单点连接。另外采样电阻必须使用四线开尔文接法,采样线从电阻本体两端直接引出,绝对不要在电阻和地之间的铜皮上随便找个点当作采样点。这个问题在原理图阶段看不出差别,但到了样板调试阶段会耗费你大量时间。我的经验是:铺铜之前先把采样走线当作“关键信号”对待,宁可绕远路也要保证它不被功率走线包围。
5. 完整调试流程与实测波形:从跑飞到锁相的48小时
5.1 第一步:开环强制旋转验证采样链路
我拿到工程后第一件事不是启动高频注入,而是先做开环验证。给电机一个固定幅值和频率的旋转电压矢量,让它在无感但低速状态下被强制拉着转。这时候用示波器看三相电流波形,确认采样链路没有发生相序错误、电流波形没有明显削顶或直流偏置。如果开环电流波形都是乱的,那后面闭环必然跑不起来。
这个过程还顺带可以验证PWM触发ADC的时序。我在示波器上同时抓PWM中点信号和ADC采样完成标志,确认每次采样的时刻都落在PWM中心点,而不是在开关边沿附近。高频注入对采样时刻的确定性要求极高,这一步马虎了后面很难排查。
5.2 第二步:静止状态下的高频响应标定
开环跑通后,让电机完全停住,不施加任何基波电压,只注入高频信号。然后我从调试接口里直接读取d/q轴高频电流的幅值。正常情况下,q轴高频电流应该会随注入电压增加而线性增加,并且d轴和q轴的高频响应幅值有明显差异,这个差异就是凸极效应的体现。
我还做了注入频率的扫描:从500Hz到2kHz,每隔100Hz记录一次q轴高频电流幅值。扫出来的结果让我决定最终注入频率。不同板子因为寄生电容和采样滤波参数不同,最优频率可能差很多,所以这一步不能省。如果发现某一频率下电流响应有明显谐振峰,那就要避开了,否则工作点稍微漂移就会让信号质量迅速恶化。
5.3 第三步:角度跟踪效果与堵转工况实测
标定结束后才能开始闭环角度跟踪。我先用手慢慢转动电机轴,观察调试上位机里的估计角度是否同步变化。这里一个常见问题是:手转电机时角度可以跟,但方向反了或者跳变180度。方向反多半是PLL极性配置错了,跳变180度则要回去检查初始定位逻辑。
我遇到的更有意思的情况是:角度跟随看起来没问题,但把电机堵住后,高频注入给出的估计角度在负载下慢慢偏离真实角度。后来发现是电流采样偏置在作怪,堵转时大电流让采样电阻的温漂明显,偏置变化导致解调误差里混入了直流项。解决办法是在采样链路里增加了基波电流的低速漂移抑制,并且用更稳定的精密采样电阻。实测堵转工况下,角度误差最终稳定在±5度电角度以内,低速2rpm闭环运行也能持续稳定,不会因为负载突变而失步。
5.4 遇到的两个难点和最终解决方案
第一个难点是角度估计在低速带载时出现周期性抖动,频率和机械转速有固定关系。排查下来发现是电流采样信号中混入了少量转子位置相关的高次谐波。这些谐波进入了带通滤波器,虽然强度不大,但经过PLL积分后会被放大成角度波动。解决办法是把带通滤波器的阶数从二阶提到四阶,并且增加了一个陷波器,专门处理2倍注入频率附近的残余分量。
第二个难点是低速到高速切换时的角度跳变。最开始我的状态机只是单纯地切换观测器,结果每次切换瞬间都会出现一次电流冲击。后面我加了速度加权融合,还在切换区故意把速度环目标斜率限制住,让转速不要变化太快。最终切换冲击从原来的“跳变”变成了“平滑过渡”,整个过程的电流波动已经不明显了。这部分调试花的时间最多,但也是高频注入工程里最容易出彩的地方。
6. 给同样做无感FOC的人几点忠告
高频注入不是一上来就写PLL,优先把电流采样做到极致。很多工程最后跑不出来的根因都在信号链路上,代码反而是次要的。原理图阶段就要给采样运放、滤波器、地平面留足设计余量,不要指望软件去擦屁股。
先开环、再静止标定、再角度跟踪,最后才带载闭环,这个顺序不能乱。我见过不少人直接跳到闭环,波形一乱就改代码,最后越改越乱。严格按照步骤来,虽然前期看起来慢,但每个环节都验证过,最后合起来时反而最快。
条件允许的情况下,调试时保留一个真实编码器作为参照对象。哪怕只是临时接上去对比角度,也能让你快速区分“算法问题”和“硬件问题”。等系统彻底稳定后再把编码器拆掉,这样既能验证高频注入的准确性,也能避免在无头苍蝇式调试里浪费时间。
最后说一句实话:高频注入能覆盖零速和低速,但到了中高速还是要交给反电动势观测器。别指望一套算法包打天下。把两者融合好,做的无感FOC才算真正落地。这套STM32F4完整工程,我最满意的不是跑通了一路算法,而是把原理图和源代码的每一条线索都拧成了一股绳,定位问题时能一下子找到源头。