搞电机控制的人迟早都会撞上那堵看不见的墙——基速。额定转速以内电流和电压都宽裕想怎么控就怎么控可一旦用户甩过来一句“我要再快30%”就会发现反电动势已经顶到逆变器能输出的最高电压再往上提频率电流环就开始往下掉转矩跟着崩严重一点直接过流炸模块。这时候几乎所有方案都会走到同一个屋子里弱磁。很多人一听“弱磁”两个字第一反应是把磁铁弄没。实际当然不是这么玄本质是在定子电流里注入一个和转子磁链方向相反的去磁分量把气隙磁链“压”下去给电压腾出空间让电机在基速以上还能继续升速。这个操作说起来就一句话难的是“这个去磁分量到底怎么算”。查表法标定量大电压环PI法动态慢而我今天要拆的是思路最直接、代码最好落地的一种——直接计算法弱磁控制策略。这篇文章会从电压极限的物理本质讲起把直接计算法的数学推导一步步写清楚再给出一套可以直接嵌进FOC中断里的C代码最后聊聊实机调试时那些文档里不会写的坑磁链温漂、母线电压跌落、PI退饱和、退出弱磁时的震颤。篇幅不短但每一步都是能直接上机的干货。1. 基速墙的本质电压极限椭圆才是真正的天花板1.1 从反电动势说起永磁同步电机在dq同步旋转坐标系下的稳态电压方程是ud Rs*id - ωe*Lq*iq uq Rs*iq ωe*(Ld*id ψf)式中id、iq是直轴交轴电流Ld、Lq是直轴交轴电感ψf是永磁磁链ωe是电角速度。低速时电阻压降Rsid、Rsiq还占一定比例到了高速弱磁区电阻压降相比于反电动势项ωeψf和ωeL*i就小到可以忽略工程上几乎都会把Rs丢掉方程简化为ud ≈ -ωe*Lq*iq uq ≈ ωe*(Ld*id ψf)注意看这两项全都跟ωe成正比。转速每升高一点ud、uq的幅值就跟着往上涨而逆变器的输出电压能力是硬的物理约束母线电压Udc就摆在那里SVPWM线性调制区最多只能输出幅值为Udc/√3的相电压。超过这个值你的调制波就会被削顶电流波形畸变谐波电流失控。这就是“基速墙”的来源——不是转矩不够是电压真的不够用了。1.2 电压圆是怎么画出来的把上面两个电压方程平方相加得到电压矢量幅值的关系ud² uq² ωe²[(Ld*id ψf)² (Lq*iq)²]如果要求电压幅值不超过逆变器最大输出umax那么(Ld*id ψf)² (Lq*iq)² ≤ (umax/ωe)²这个式子在id、iq平面上画出来是一个椭圆。椭圆中心在(-ψf/Ld, 0)半轴分别是(umax/ωe)/Ld和(umax/ωe)/Lq。转速越低椭圆越大转速越高椭圆越小一路往里缩。只要电流工作点落在椭圆内部电压就是够用的一旦工作点跑到椭圆外面去了电流环就心有余而力不足。所谓弱磁用几何语言说就是转速升高导致椭圆收缩之后把工作点拽回椭圆内。要做到这一点最有效的方向就是让id变得更负。因为id负向增加会让(Ld*id ψf)这一项变小——直轴磁链被“抵消”了一部分uq随之降下来电压圆内部的空间就回来了。这就是去磁的本质也是“弱磁”这个名字的真正来源。1.3 “直接计算法”要解决的核心问题现在问题变得很具体转速升到椭圆缩小到一定程度后id指令到底该给多少iq指令又该给多少传统做法是加一个电压外环PI把“电压误差”积分成额外id补偿量直接计算法的思路则完全不同——既然电机模型摆在这里电压极限的数学表达式也摆在这里那就直接把方程解出来让工作点一步到位落到约束允许的位置。这个“位置”不是随便找个椭圆内的点就行。为了在基速以上还能保持输出能力我们要让工作点同时踩在电流极限圆和电压极限圆上这样本周期总共能用到的电压全部用完、电流也全部用完才能在该转速下输出最大转矩。这才是“突破基速还能保持输出能力”的真正含义电压受限了但每一伏特、每一安培都不浪费。2. 直接计算法的数学骨架把电流极限和电压极限联立求解2.1 表贴式电机的闭式解推导先看最常见的表贴式永磁同步电机SPMSMLdLqLs此时电压极限从椭圆退化成圆电流极限则是标准的电流圆id² iq² imax² (Ls*id ψf)² (Ls*iq)² ρ²其中ρumax/ωe量纲是磁链Wb。两个圆方程联立可以直接消元。把第二个方程展开Ls²*id² 2Ls*ψf*id ψf² Ls²*iq² ρ²利用id²iq²imax²第一项和最后一项合起来就是Ls²*imax²于是Ls²*imax² 2Ls*ψf*id ψf² ρ²整理一下id的闭式解就出来了id* (ρ² - ψf² - Ls²*imax²) / (2*Ls*ψf)iq跟着取电流圆上的剩余量iq* ± sqrt(imax² - id*²)这个公式绝对是我个人认为弱磁策略里最漂亮的一个解析结果。不存在任何积分器、调节器、增益参数每周期输入实时转速和母线电压输出就是当前速度下“电压极限和电流极限同时满用”的最优工作点。这一行公式就是直接计算法弱磁控制策略的核心玩法。注意这个id的符号判定。低速时ρ很大id算出来是正的说明电压圆还没收缩到需要弱磁的程度此时什么都不干维持正常的MTPA指令表贴式电机的MTPA就是id0。只要转速升高到id*变成负值就说明进入了弱磁区立刻让工作点跳到这个解析点。所以这个公式天然就带一个“进入判断”不需要额外的切换条件。2.2 一个具体参数下的计算示例公式光摆出来不够直观我带一组实际参数算一遍。假设一抬表贴式电机Udc310V极对数p4ψf0.055WbLs1.2mH电流极限imax15A。那么umax 310/√3 ≈ 179V基速 ωe 179 / sqrt(0.055² (0.0012*15)²) ≈ 3091 rad/s对应转速约7380rpm目标转速拉到10000rpm时ωe 2π100004/60 ≈ 4188.8 rad/sρ 179 / 4188.8 ≈ 0.0427 Wbid* (0.0427² - 0.055² - 0.018²) / (20.00120.055) ≈ -11.56A此时iq* sqrt(15² - 11.56²) ≈ 9.56A。跟基速时的iq15A相比转矩降到了约64%但速度提了35%功率基本保持住这就是恒功率区的效果。再算一个极限当id被压到-15A、iq0时转速极限ωe 179/(0.055-0.018) ≈ 4838 rad/s对应约11550rpm。超过这个速度连零转矩都维持不住控制器应该直接限速。这个例子告诉我们几个重要信息弱磁不是无限度的它受制于电流极限与磁链/电感的配合。ψf/(Ls*imax)这个比值决定了弱磁能力的上限比值越小能跑越高的转速但代价是基速附近的转矩密度下降。选型的时候如果客户要求很高转速攀升比电机本身的弱磁率就要足够大光靠控制算法是帮不了忙的。2.3 凸极电机怎么处理内嵌式永磁同步电机IPMSMLqLd电压极限是个真正的椭圆两个约束联立后方程不再有前面那种简单线性解严格推导会得到一个含四次项的方程。工程上我通常不追求闭式解而是做一个实时一维搜索。思路很简单固定id从电压圆方程解出iq_voltage sqrt(ρ² - (Ld*idψf)²)/Lq再从电流圆解出iq_current sqrt(imax² - id²)。两个iq都是id的函数找它们在id负方向上的交点就是同时满足两个极限的工作点。用一个for循环从id0往负方向迭代最多循环十来次在当前Cortex-M级别的MCU上每周期耗时也就是几个微秒float id_lo -imax, id_hi 0.0f; for (int i 0; i 12; i) { float mid 0.5f * (id_lo id_hi); float iq_v sqrtf(rho*rho - powf(Ld*mid psif, 2)) / Lq; float iq_c sqrtf(imax*imax - mid*mid); if (iq_v iq_c) id_hi mid; // 电压圆还够大弱磁可以再深一点 else id_lo mid; // 电压圆不够大需要往回退 }二分法每轮收敛一半区间12轮精度足够。这篇后续代码以表贴式为主但如果你在调IPMSM把这个迭代块替换掉闭式解那行就行其余框架完全通用。3. 代码落地在FOC中断里嵌入弱磁模块3.1 模块接口设计直接计算弱磁模块最好设计成独立的小单元只跟电流环交换指令不碰底层PWM和采样。我习惯这样组织数据typedef struct { float Ld; // 直轴电感 H表贴式 Ls float Lq; // 交轴电感 H float psif; // 永磁磁链 Wb float imax; // 电流极限 A峰值 } MotorParam_t; typedef struct { uint8_t weak_enable; // 当前是否处于弱磁区 float id_ref; // 修正后的 d 轴电流指令 float iq_ref; // 修正后的 q 轴电流指令 float rho; // 电压圆半径磁链量纲 Wb float umax; // 实际使用的电压极限 V } WeakMag_t;接口按“输入电角速度、母线电压、当前MTPA指令输出弱磁修正后的指令”这种思路来。注意一点电流变量全程使用峰值约定且与Park变换采用等幅值形式。很多弱磁公式在非等幅值变换下系数完全不同代码移植时先确认约定再套公式否则算出的id能偏出一倍。再看逆变器电压极限。SVPWM在线性调制区输出最大相电压幅值是Udc/√3这是弱磁设计里最安全、最保守的取值。如果用了过调制母线电压利用率能再往上凑一点但谐波和PI调节难度都会上去。我的习惯是弱磁基准始终以Udc/√3为准宁可留一点电压裕度也不要让电流环在非线性区磨。这个选择在后面讲母线电压跌落时还会提到。3.2 解析弱磁核心函数核心计算函数就这么一点直接把它挂在速度环或者电流环中断里每周期调用void weak_mag_compute(MotorParam_t *motor, WeakMag_t *wk, float we, float id_mtpa, float iq_mtpa) { if (we 1e-3f) we 1e-3f; // 防止除零 wk-umax motor-Udc * 0.57735027f; // 采样值经过滤波后使用 wk-rho wk-umax / we; float rho2 wk-rho * wk-rho; float psif2 motor-psif * motor-psif; float lim motor-Ld * motor-imax; float id_w (rho2 - psif2 - lim * lim) / (2.0f * motor-Ld * motor-psif); if (id_w 0.0f) { // 电压空间足够未进入弱磁区直接透传 MTPA 指令 wk-weak_enable 0; wk-id_ref id_mtpa; wk-iq_ref iq_mtpa; } else { // 进入弱磁区以解析点为基准 wk-weak_enable 1; float id_ref id_w; if (id_ref -motor-imax) { id_ref -motor-imax; // 电流极限兜底 } wk-id_ref id_ref; float iq_max sqrtf(motor-imax * motor-imax - id_ref * id_ref); wk-iq_ref (iq_mtpa 0.0f) ? iq_max : -iq_max; } }这段代码本身没什么花活该算的都算了该判的也都判了。不过直接这么扔进工程里跑起来大概率会在基速附近抖得像筛子。问题出在哪出在三个地方id指令跳变、退出弱磁时的切换震颤、以及电流环赶不上参考导致的电压饱和。下面逐个解决。3.3 限幅、平滑与切换保护第一个问题是斜率。弱磁解析公式算出的id_ref是目标值但电流环跟踪需要时间。如果上一周期id还是0这一周期直接给-8A电流环无论如何都会在瞬间饱和。更麻烦的是退出弱磁时id_ref跳回0电磁转矩瞬间恢复一大截整个机械系统会像被踢了一脚。所以id指令变化必须加平滑。工程上的标准做法是一阶低通或者斜坡限速。我习惯用一阶低通系数根据速度环执行周期选。如果弱磁计算放在1kHz速度环里执行alpha取0.05左右比较稳放在10kHz电流环里执行alpha可以取0.01到0.02。核心代码如下// 一阶低通平滑alpha 依执行频率选取值越小越平滑 wk-id_ref alpha * (id_target - wk-id_ref); // 为保证电流幅值不超限iq 与 id 联动 float iq_allowed sqrtf(motor-imax * motor-imax - wk-id_ref * wk-id_ref); wk-iq_ref (iq_mtpa 0.0f) ? iq_allowed : -iq_allowed;注意这里把id和iq绑定在同一个电流圆上id变了iq跟着变而不是让iq保持原值。这种做法能保证任何时候电流幅值都不越界但代价是转矩和速度之间存在耦合。弱磁区的动态响应天然比恒功率区慢这是物理约束滤波只是让它别抖。第二个问题是基速附近的反复横跳。id_w在0附近小幅波动时弱磁标志位可能一会儿置1一会儿清0系统会周期性地切入切出。我的对策是加一个小的滞环id_w小于-0.5A才进入弱磁id_w大于0.5A才退出避免在临界点上来回切换。3.4 与电流环PI的配合抗积分饱和弱磁区最容易埋的雷是电流环PI积分饱和。想象一下id指令忽然变到-10A但逆变器电压已经满了实际id根本充不到这么负PI积分器发现误差一直在持续往上积分最后积分器顶到上限位置。等到转速稳定或指令回调时积分器要从很深的位置慢慢退出来这段时间内电流环会有一个大超调甚至直接触发硬件过流保护。处理办法没有银弹但有两板斧很有效。第一板斧是给电流环PI的积分器设一个与工况相关的动态上限。比如iq环的piout限幅值在弱磁区不要给满留出20%的裕量给d轴电压因为弱磁区ud和uq都要占用电压矢量的空间。第二板斧是在弱磁模块里直接监视uq、ud的幅值一旦发现电压参考值接近umax且长时间无法跟踪参考电流就把对应电流环PI的积分器清零或缩半。这个动作比任何参数调整都更能救场。4. 从仿真到实机参数漂移、母线电压与退磁风险4.1 永磁磁链的温度漂移直接计算法有一个绕不过去的软肋它吃参数。公式里的ψf和Ld一旦跟实际电机不符算出来的id_ref就偏。最典型的是ψf随温度漂移。钕铁硼永磁体的剩磁温度系数大约是-0.12%/K常温25℃标定的ψf到90℃可能已经跌了8%。偏小8%意味着什么呢带入id*公式看ρ²和ψf²相减ψf实际变小公式用大的ψf算出来的id会更深。这个方向是偏保守的不会立刻出大问题但会白白牺牲转矩和功率。反过来最怕的是低温大电流场景ψf标定值偏低算出的id不够负电压压不住电流环失控转速上不去。所以凡是做产品我都会在代码里加一个简单的温度补偿表。测功台标定出ψf随绕组温度的变化曲线后用一个查表加插值的方式实时修正ψf。没有温度传感器的话至少要留一个参数辨识口用电机停机状态的直轴电感测量或在线磁链观测器做一个慢速校准别让ψf就这么死板地躺在常量里。4.2 母线电压波动必须实时采集另一个坑是Udc。前面代码里我专门写了注释“采样值经过滤波后使用”。这不是废话是血泪教训。急加速时母线电容上的电压会明显跌落某些恶劣工况能掉10%以上。如果你在弱磁计算里用固定的310V而实际母线只剩280V那么实际电压圆比计算用的电压圆小一圈电流环在弱磁区会持续追不上参考表现出来就是电机一顿一顿、转速波动严重时触发母线欠压保护。对策很简单每个控制周期直接采样Udc做一阶低通滤波后喂给weak_mag_compute。滤波时间常数不要太大几毫秒量级就够——太慢了反而跟不上母线动态最好跟电流环采样频率匹配。用实时Udc算出umax电压圆半径自然跟着收缩膨胀系统运行点就会自动适应母线波动。4.3 实机调试时怎么观察弱磁是否正常有示波器在手的时候我一般分三步确认弱磁状态。第一步看电压幅值。进入弱磁区后ud²uq²的合成电压幅值应该稳定贴在umax附近像电流环在“顶”着电压天花板走。如果电压明显低于umax说明id_ref给深了白白损失了转矩如果电压高于umax那说明指令已经超出逆变器能力电流波形里一定有割顶畸变。第二步看id和iq的轨迹。在id-iq平面上工作点应该沿着电流圆和电压圆的交点走。转速越高id越负iq越小。如果看到id大幅振荡而不是平滑加深优先检查平滑系数和电流环带宽是不是不匹配。第三步关键时刻做一次阶跃加速观察转速过冲。弱磁区动态响应慢是物理特性但过冲过大说明切入动作太生硬。此时把平滑alpha调小或者把切入的滞环窗口调大转速曲线就会漂亮很多。实机还有一个比较隐蔽的现象机械振动导致角度编码器误差会让坐标变换里的dq轴“虚转”表现为弱磁区id、iq均值正常但波形上叠加明显的交流纹波。这种情况控制算法怎么改都没用先把角度采样和机械装配问题解决。4.4 直接计算法、电压环PI、查表法怎么选这套直接计算法不是万能的实际产品里三种弱磁路线各有位置我列一个对比表方案参数依赖动态响应标定工作量适用场景直接计算法高依赖ψf/Ld精度快理论上无延迟低公式即轨迹参数已知、需要对阶跃响应快的驱动器电压环PI法低对参数漂移不敏感慢受PI带宽限制低但要调多组PI参数可能漂移的通用变频器查表法无直接查表快无在线计算极高全工况标定量产车载驱动、控制芯片没余量的场景个人经验是先分清你到底怕不怕参数漂移。如果电机跟驱动器是固定搭配电机本体参数有铭牌可查那直接计算法性价比最高代码干净、响应快、还可以跟在线参数辨识结合起来实时更新ψf。如果是通用型驱动器今天带这个电机明天带那个电机参数漂移幅度不可控那用电压环PI法更稳妥毕竟它不跟你较真电机模型。查表法的场景是那些死磕效率和NVH的车载项目全套标定做下来虽然贵但能保证所有工况下轨迹最优直接计算法求的是“两个极限圆交点”在某些低电感高凸极比的电机上这个点跟严格的MTPV轨迹还有一点差距要求极限性能的话需要用更精细的迭代。最后再分享一个实用小技巧。直接计算法最容易给人惊喜的地方是它可以当“前馈”跟电压环PI法混着用——用解析公式算出一个基础的id_ref作为前馈再用电压误差PI做增量补偿。这种混搭既保留了直接计算法的快速性又用PI吸收了参数偏差异带来的稳态误差是我做某些要求高动态响应的驱动器时最常用的最终方案。如果你正在被弱磁区的动态响应折磨可以先试这个方向。