无感FOC核心解析:PWM中断、Ud/Uq与HFI注入频率的工程权衡 我们在调试无感FOC的时候经常碰到这样几个看起来很基础、但问十个人有八个人解释不清的问题20kHz的PWM中断到底在干什么PI输出的Ud/Uq和电机端电压方程里的U_d/U_d是什么关系低速段反电动势明明已经小到不能信了高频注入HFI的频率到底怎么选为什么不能直接拿PWM的一半来用这三个点其实是同一条线上的三个环节把它们拆开看是散的串起来看就是无感FOC的底层骨架。这篇文章我结合自己调试PMSM无感FOC的经验把中断、Ud/Uq、控制频率、HFI注入频率之间的关系一次性讲透。先说清楚这篇文章适合谁或者说什么情况下你读它最实用。如果你刚写完电流环在无感观测器面前发怵不知道低速时候怎么把转子角度估出来或者你已经把高频注入跑起来了发现低速电流波形一团糟角度一卡一卡的总怀疑是滤波器没调好——那这篇文章就是给你准备的。我默认你有基本的FOC背景知道Clarke、Park、SVPWM是什么但对“把这些外设和算法拼接在一起”这件事还需要有人推一把。文章里不会堆公式公式只写必要部分重点放在推导逻辑和工程取舍。1. FOC中断和控制频率底层骨架1.1 中断不是“用来打断的”是控制节拍很多初学者看到FOC代码里第一行就是定时器中断服务函数就误以为中断是被外部信号“打断”的产物。实际上FOC里的定时器中断更像是一个时钟滴答它是整个控制算法的节拍器。这个节拍器叫PWM更新中断也好叫PIE中断也好本质都一样PWM定时器从一个周期结束进入下一个周期时产生一个中断事件处理器在这个时间点里完成电流采样、坐标变换、PI运算、SVPWM更新为下一个PWM周期准备好所有电压指令。void PWM_ISR(void) { // 1. 读取ADC结果得到三相电流 Ia, Ib, Ic // 2. Clarke: Ialpha, Ibeta // 3. Park: Id, Iq (用当前转子角度) // 4. 电流PI: 得到 Ud_cmd, Uq_cmd // 5. 逆Park SVPWM: 更新占空比寄存器 }这个过程必须在一次中断周期内完成。如果PWM频率是20kHz周期就是50us那么从上一次中断执行完到下一次中断触发你只有50us。这个时间是一刀切的不存在“晚一点也没关系”的余地否则占空比更新就会错位电流波形立刻畸变。所以控制频率通常就是指PWM中断频率它决定了FOC运算以多快的节奏循环一次。1.2 中断频率怎么定载波、带宽和死区现在的问题是PWM频率为什么取10k、15k还是20k一旦你调高PWM频率FOC中断频率也跟着变高留给控制算法的时间更短。这里面的约束有三层。第一层是电流环带宽。电流PI的闭环带宽通常只能做到PWM频率的1/10到1/20。举一个具体例子PWM 20kHz电流环带宽典型值2kHz左右。如果想把电流环带宽推到3kHz甚至更高PWM不加到30kHz以上离散化引入的相位滞后就会吃掉稳定裕量。反过来PWM取10kHz时电流环带宽大概只能做到1kHz上下动态响应会明显“肉”一点。第二层是采样时刻。FOC需要三相电流的瞬时值。如果ADC采样时刻落在开关管导通关断的瞬间电流上全是振铃和毛刺后面所有算出来的东西都是脏的。所以ADC触发必须和PWM计数对称点严格同步通常都在PWM载波零点或峰值处触发采样这个位置避开开关边沿采到的电流最干净。第三层是硬件开销。PWM频率越高开关损耗越大MCU的计算压力也越大。在STM32F405这类168MHz、带FPU的芯片上跑20kHz FOC中断服务函数整体耗时大概20us多还剩一半余量但你要是跑到40kHz PWM中断耗时占比就逼近50%再加上通信、保护逻辑系统就开始发紧。所以通用做法是家电类16kHz工业伺服20kHz高性能伺服8到16kHz用更大电流环带宽换取更低开关损耗同时搭配更高级的采样方案。说到底控制频率的选择是带宽、损耗、计算余量三者的折中。1.3 中断里的代码优化少干蠢事既然中断频率决定了一切中断代码就必须精简高效。我调试时踩过一个很典型的坑在中断里顺手加了个串口打印用来观察变量。刚开始没觉得有问题后来把电流环带宽从1kHz调到2kHz才发现中断偶尔超时电流波形上出现周期性的毛刺。用逻辑分析仪一抓超时恰好发生在串口发送数据的那几次中断里。中断代码的优化原则很直接不要在中断里做延时等待不要调用耗时的库函数不要做动态内存分配不要进行高精度浮点运算如果没有FPU。三角函数、开方、反正切这类运算能查表就查表能近似就近似实在不行也要确认CPU周期可接受。还有一点容易被忽略——中断栈分配。FOC中断如果调用了比较深的函数嵌套栈空间不够会直接HardFault。这个在Cortex-M上特别常见因为启动文件里给的栈大小经常是默认值。实测下来给FOC中断单独划分一块栈空间或者把整个系统栈加大是更稳妥的方案。2. Ud/Uq到底是控制器的输出还是电机的状态2.1 符号习惯带来的第一个坑看代码的时候你一定会发现有的工程里电机电压方程写成Ud Rs*Id Ld*dId/dt - ωe*Lq*Iq Uq Rs*Iq Lq*dIq/dt ωe*(Ld*Id ψf)但另一些工程里特别是从Simulink转出来的代码PMSM模块里Ud、Uq的定义可能是反的或者dq轴的方向定义不同。如果照搬公式而不看正方向约定高频注入解调出来的角度差符号就会反相轻则角度震荡重则直接失控。我这里说的正方向约定指的是d轴是取转子磁极方向还是取电流滞后方向q轴超前90度还是滞后90度。不同坐标系定义下Park变换的公式就差一个符号。你可以任意选一种但整条链路必须完全一致从Clarke变换、Park变换、PI输出、逆Park到SVPWM再到观测器和注入解调所有地方都要用同一套约定。我习惯用d轴对准转子磁链方向、q轴超前90度的标准定义这也是大多数电机控制库的默认约定。工程项目里你把变量名写成U_d/U_q还是Ud/Uq完全无所谓重要的是物理含义。代码里的Ud_cmd/Uq_cmd是电流环PI输出的电压指令它最终会经过SVPWM转换成三相占空比。但电机端真正承受的电压和这个指令之间还有不少误差。这就要说到死区补偿了。2.2 电压方程与观测器的底层输入无感FOC里观测器要做的事情本质上是“看到电压算反电动势估角度”。反电动势从哪来从电压方程里来。以q轴电压方程为例稍微变化一下就能写出观测器的核心ωe*ψf Uq - Rs*Iq - Lq*dIq/dt - ωe*Ld*Id等号左边就是反电动势如果忽略磁路饱和。只要能算出左边就能从中提取电角速度ωe和角度θe。但你看这个方程的右边每一项都依赖三个东西准确的电压Uq、准确的电流Iq、准确的电机参数Rs和Lq。其中电压是最容易出偏差的。我们给SVPWM写入的是占空比是期望的电压指令而不是实际电压。实际电压受母线电压波动、IGBT/MOSFET管压降、死区时间、开关延时的影响会对指令值造成几个百分点甚至更大的偏差。低速时Ud/Uq本身很小比如额定电压下运行在5%转速时q轴电压可能只有1V多一点这时如果死区影响就有0.3V误差比例大得离谱。所以在中高速做无感FOC死区补偿几乎是标配不做补偿你估计出来的角度就会出现周期性波动和负载大小强相关。这也是为什么很多教程让你在观测器前面“把电压修正准”。2.3 PI输出的限幅、反饱和与电压利用率再回到PI控制器本身。电流环PI输出得到Ud_cmd/Uq_cmd之后不能直接拿去给SVPWM用还要经过限幅。原因很简单SVPWM能输出的最大电压受母线电压限制空间矢量六边形内切圆对应的最大相电压幅值是Udc/√3。如果指令电压超过这个范围占空比必然饱和电流环就会失去控制能力。限幅之后积分项必须做反饱和处理。我见过很多人限幅只钳住输出积分项还在继续累加结果就是系统进入饱和状态后要花很长时间才能“醒”过来电流波形上出现明显的过冲。处理方式有很多常见的是带条件积分的抗饱和法只有PI输出没超过限幅值时才允许积分累加。这种做法工程上最直观调起来也最省事。电压利用率也很关键。SVPWM本身比SPWM的直流母线利用率高能多输出约15%的相电压幅值。但如果你在逆Park之后没有做过调制比相关的处理比如没有注入三次谐波或者没有用SVPWM的过调制区高速下的输出电压就会打折扣。对于无感FOC来说这直接决定了弱磁转速能拉到多高。如果高速表现上不去先别急着怀疑观测器回头看看电压利用率是否压榨到位。3. 高频注入HFI为什么低速要加“外援”3.1 低速观测器失效的本质前面提到反电动势Es ≈ ωe*ψf它的幅值正比于电角速度。转速趋近于零时反电动势也趋近于零。而所有基于反电动势的观测器本质上都是拿电压方程去反推动转角速度一旦信号源消失信噪比就会急剧下降。低速下随便一点死区误差或者电流采样噪声都能把微弱的反电动势信号淹没掉。这就是为什么低速段不能用滑模或者龙伯格观测器必须换一种思路来识别转子位置。这种思路利用了电机的凸极性。对内嵌式PMSM来说d轴磁路因为永磁体磁导率低等效电感Ld小于q轴电感Lq。这就意味着转子在不同的角度时定子侧的等效电感分布是不一样的像一块椭圆形的“电感地图”。如果我们在定子绕组上注入一个高频电压信号然后观察高频电流的响应就能从电流响应里反推出转子角度。这种识别方式不依赖反电动势因此零速下依然有效。对于表贴式PMSM通常Ld和Lq差别很小凸极性弱传统高频注入很难做过。不过在负载状态下磁路饱和会造成等效凸极性也可以尝试用注入法识角。但如果你做的是低成本表贴电机无感启动主流的工程方案还是“开环强拖 反电动势切换”而不是高频注入。做HFI前提是电机要有可利用的凸极性。3.2 注入方式脉振正弦和方波注入高频注入常见两种实现方式一种是脉振正弦注入一种是方波注入square-wave injection。脉振正弦注入逻辑比较直观在估计的d轴方向注入某一频率的高频正弦电压比如1kHz到2kHz的正弦波然后对高频电流做解调提取出转子位置误差信号。这种方式适合控制频率不太高、处理器算力有限的情况因为正弦信号本身是连续的采样率要求低一些解调出来的信号也比较光滑。方波注入则直接利用PWM周期的离散特性在连续两个或四个PWM周期内注入正负交替的脉冲电压电流采样时刻也跟随同步。它的频率可以做到很高比如20kHz PWM下直接注入10kHz方波这样解调出来的带宽就比正弦注入高很多动态响应更好。代价是采样时序要求苛刻ADC触发必须和PWM边沿严格对齐电流采样窗口稍偏一点解调质量就迅速恶化。我在自己的项目里先用脉振正弦跑通逻辑再切到方波注入来提高响应带宽。这个步骤很重要。如果你一上来就做方波注入很难判断到底是哪里出了问题——是注入频率不对、滤波器带宽不对、还是采样时序残了。先做相对稳的正弦注入把整条链路验证通再优化到方波调试时间能省一半。3.3 注入频率和幅值怎么定注入频率的选择是HFI里最值得讲清楚的事。它不是一个孤立参数而是和PWM频率、电流环带宽、滤波器设计、采样率共同约束出来的。第一注入频率必须明显高于电流环带宽。为什么因为电流环本身就是一个低通调节器如果你注入1kHz的信号而电流环带宽也是1kHz电流环就会把这个注入信号当成真实电流误差来调节导致电流环输出里出现和注入信号同频的强干扰整个电流波形都会被污染。反过来如果注入6kHz、10kHz电流环对它的增益已经衰减下去了电流PI就不会把它当成误差去追。所以工程上一般要求注入频率至少是电流环带宽的3到5倍。第二注入频率必须远低于采样频率的奈奎斯特频率。20kHz PWM采样你的注入信号如果选12kHz那就太接近折叠点解调出来的信号会出现严重的混叠和相位畸变。一般做法是注入频率不超过PWM频率的一半而且留足裕量常用10kHz甚至以下。第三注入频率的选择还受限于电机本身的感性特性和电流采样分辨率。频率太高电感阻抗Zs 2πfL会变得很大同样电压幅值下电流响应会变小ADC采到的高频电流信噪比下降。频率太低又靠近电流环带宽隔离不干净。所以这里是两边夹逼中间取平衡。针对不同PWM频率我整理了一个参考表可以当作初始调试的起点PWM频率电流环带宽正弦注入频率参考方波注入频率参考解调低通滤波带宽10kHz~1kHz2kHz ~ 3kHz5kHz200Hz ~ 400Hz16kHz~1.5kHz3kHz ~ 5kHz8kHz300Hz ~ 500Hz20kHz~2kHz4kHz ~ 6kHz10kHz400Hz ~ 600Hz注入幅值通常是母线电压的5%到10%或者更直接地说是一个能产生足够信噪比的高频电流幅值。太小解调出来的误差信号弱角度估计抗噪能力差太大电机发出明显的高频啸叫铁损和铜损都上升而且容易把电流环的输出顶到饱和区。我自己的习惯是先选一个保守值比如5%然后在示波器上看高频电流的峰峰值慢慢加大到高频电流分量清晰可辨、又不对力矩产生明显扰动为止。你要知道注入信号进入的是电压指令最终会在电流上产生一个同频的纹波分量这个纹波分量会带来高频转矩脉动和噪音所以幅值能小则小绝不存在“越大越稳”的说法。3.4 注入信号的解调与角度跟踪注入只是一半另一半是把转子角度误差从高频电流响应里解出来。流程大致是先把三相电流变换到估计的dq坐标系然后通过带通滤波器把注入频率附近的电流分量提取出来再与注入的参考信号做乘法相干解调最后用低通滤波器把高频分量滤掉剩下一个和转子角度误差近似成正比的直流分量。这个误差信号进到PLL或者其他跟踪观测器里通过PI调节让估计角度逼近实际角度。需要注意的是带通滤波器和低通滤波器都会引入相位延迟尤其是低通滤波器带宽越低延迟越大。如果这个延迟不补偿最终估计出来的转子角度就会带一个偏置直接表现为低速运行时的电流不对称和转矩波动。我在实测里就遇到过低速正转一切正常反转时q轴电流纹波明显变大一开始怀疑是死区补偿方向反了查了一圈才发现是解调低通滤波器的相位延迟没做补偿。补偿量也很好算就是在误差信号的增益路径上乘一个和滤波器相位响应相关的修正系数或者在PLL前面对误差做相位前置。具体的补偿值可以通过一个很简单的测试来确定零速下开环给定一个已知角度然后比较估算角度和实际角度的差值直接把这个差值作为固定补偿写进去。4. 控制频率和注入频率的统一规划4.1 频率分层像音频系统一样做带宽隔离当你同时运作PWM中断、电流环、速度环、高频注入时整个控制系统其实是一个多频率系统。如果各个频率互相干扰系统就乱了。合理的做法是让不同频率各自占据频谱上的不同区间用滤波器把区间隔离开来。把整个频率体系从上往下排大概是这样的PWM频率20kHz是最高层所有更新的基础节拍注入频率比如10kHz紧贴着PWM逻辑工作于离散的高频区间电流环带宽2kHz低于注入频率确保电流环不会响应注入信号速度环带宽100Hz到500Hz再低一截最后是位置环或者外环通常只有几十Hz。这张频域分布图决定了你设计的每一个滤波器应该把截止频率放在哪里。带通滤波器让注入频率通过低通滤波器从解调结果里滤出低频误差信号电流采样本身还可能加一个高频抗混叠滤波器。每个滤波器都是这个频率体系里的“关卡”缺一个或者设错一个问题就往相邻频段窜。4.2 控制周期与注入信号采样的衔接上文提到方波注入需要在相邻PWM周期里交替注入正负电压也就是说注入频率可能直接是PWM频率的一半。这种情况下ADC采样至少要在每个PWM周期采一次电流而且不同采样点对应不同的注入方向。解调的时候是把相邻两个周期的电流之差当作某个特定方向上的高频响应。这就对中断代码提出了额外要求不能在中断里做太多耗时的操作否则ADC采样的滞后会让整个解调错位。我用逻辑分析仪看过很多次发现最容易出问题的是ADC开始转换到DMA把结果搬运到内存之间如果DMA配置不当或者ADC触发的源选错采到的电流可能滞后半个周期或者一个周期。这个滞后在普通FOC里还可以忍受但在方波注入里半个周期的错位就足以让解调误差信号完全失真。如果你在调试方波注入时发现角度估算在零速附近振荡先别调滤波器先确认采样时序。最直接的办法是把高频电流波形和PWM同步信号一起抓在示波器上看高频电流的过零点是否和注入方向切换点对齐。一旦发现错位优先检查DMA触发源和ADC采样保持时间而不是去改DI/DO。4.3 离散化误差与相位补偿最后再提一个很多人忽略的问题数字控制从采样到更新占空比天然存在一拍延迟。在20kHz PWM下这一拍等于50us对应的相位滞后在2kHz电流环带宽下大约为18度。这个相位滞后不仅影响电流环稳定裕量也会影响高频注入解调。补偿方法叫一拍超前铅补偿即在电流环计算出来后把电压指令向估计的下一拍方向做一点预估或者调整控制器的比例项和积分项权重。更常见的做法是在电流环输出后加一个精准的延迟补偿滤波器这个滤波器的群延迟正好等于一个控制周期。虽然听起来玄乎但实际实现起来就是几行程式码关键在于你要意识到这个相位滞后的存在。我在自己的代码里会在电流环运行结束后记录当前使用的角度θ然后在Park变换前把角度额外加上ωe*Ts。这个操作能有效补偿一拍滞后代价是转速不稳时会引入噪声。所以更建议通过参数配置来开关是否启用补偿这样在不同电机上调试时可以快速对比补偿前后的表现。5. 实际调试遇到的问题和排查技巧5.1 高频注入的第一个实验锁轴验证角度估计算法跑HFI之前先做一个很廉价但很有效的小实验把电机转子锁在已知角度然后让算法在开环状态下输出一个已知角度的电压矢量通过注入解调观察误差信号是否和这个已知角度一致。具体做法是在估计角度θ_est上叠加一个固定的偏置Δθ观察解调出来的误差信号是否等于sin(2*Δθ)凸极性模型的经典关系。如果方向和幅值都符合预期就说明你的坐标约定、注入方向、解调流程全都通了。我建议不要跳过这个步骤。很多项目直接上闭环转起来也转得很顺但一到零速或者反转就暴露出角度偏置的问题。锁轴测试能把这个偏置提前揪出来省得后面排查半天。5.2 角度偏置、高频噪声和失步怎么查调试过程中最常遇到的三个问题我列成一张速查表方便你对着排查现象可能原因排查步骤低速角度有固定偏置死区补偿不准、解调滤波器相位延迟未补偿、采样时序错位锁轴测试确认偏置方向抓电流波形看高频分量是否对称检查ADC触发时刻高频啸叫明显注入幅值过大、死区引入非线性谐波降低注入幅值加大死区补偿检查逆变器死区时间设置低速启动失步解调信号信噪比太低、PLL带宽过窄、负载突变提高注入幅值在可接受范围内增加低通滤波器带宽提高PLL跟踪速度速度切换时有冲击FOC换算法瞬间角度和转速不平滑确保切换时估算角度与当前实际角度连续先切换速度估算再切换角度来源这些只是排查的起点。实际项目里往往不是单一原因而是几个因素叠加。比如死区补偿不准和采样时序错位同时存在时角度偏置是两者的复合结果。我的经验是先保证采样时序正确再去校准死区补偿最后才动滤波器参数。顺序反了你永远分不清问题出在谁身上。5.3 一个值得养成的调试习惯最后说一个我觉得特别有用的调试习惯每次调整一个参数记录当前的目标转速、母线电压、负载状态以及示波器上的关键波形截图。很多FOC项目调试周期长中间变量多了之后容易陷入“调了这个忘那个”的状态。我吃过不少亏最后养成一个简单的习惯每次只改一个参数跑完记录再改下一个。看起来拖慢速度实际上是最快的路径。高频注入和无感FOC的边界参数很多想一口气学完几乎不可能。如果你已经跑通了中高速观察器但低速还在摸索这篇文章里的频率规划和锁轴测试应该能帮你省下大半周的时间。我调试无感FOC之后最大的体会是从中断到Ud/Uq再到注入频率本质上是同一套工程思维——在正确的时刻拿到正确的信号在正确的频段里处理它。搞明白了这一点剩下的只是细节打磨。