
做电机驱动这些年几乎每个做FOC的同仁都会在某一天碰上一个问题电机转速往上一拉电流环就开始力不从心扭矩输出跟着塌下去示波器里电压波形已经削顶削得不成样子。这时候你翻开手里那本《现代电机控制技术》里面会告诉你线性SVPWM的调制比上限是0.907想要更高就得去过调制。于是过调制这三个字就成了很多人从入门到放弃的门槛。这篇文章不是教科书想聊的是怎么把一个能用的SVPWM过调制算法搭起来并在Simulink里面完完整整跑通。看完之后你能搞清楚过调制到底在做什么、为什么能把电压利用率顶上去、仿真里哪些模块最容易翻车以及实际工程里什么时候该用它、什么时候用了反而惹麻烦。适合入门FOC但还没碰过电压饱和问题的同学也适合那些已经在跑SVPWM但总感觉母线电压利用率不够、想在基速以上再榨一点转矩余量的工程师。1. 电压瓶颈为什么电机转速一到高速就开始发虚1.1 逆变器给得了的最高电压其实是有物理上限的先别急着看算法我们先说清楚瓶颈这个东西到底卡在哪。SVPWM控制的对象是三相逆变器的六个开关管它想干的事情很纯粹在允许的开关组合下合成一个幅值和角度都可控的电压矢量加在电机定子绕组上。但逆变器不是无限的电压源。它的直流母线电压是Udc三个桥臂能输出的相电压瞬时值最大只能是±Udc/2。把三相合成到静止坐标系里得到电压矢量的最大幅值有这样一个关系SVPWM在线性区工作时所能合成的最大相电压幅值是Udc/√3对应的线电压有效值就是Udc/√2。这0.907的调制比就是不进入过调制时的天花板。那这个天花板是怎么来的你可以把六个非零电压矢量想象成正六边形的六个顶点线性区所能到达的区域就是它们围出来的正六边形内切圆。内切圆半径正好等于Udc/√3再大就会跑出六边形边界。理论上你还可以继续补偿让电压矢量在六边形边界上顶着走这就是过调制做的事。1.2 转速上去之后反电动势和阻抗压降一起抢电压搞清楚了逆变器限制再看电机侧。永磁同步电机的电压方程在dq旋转坐标系下写出来是ud Rs·id - ωe·Lq·iq uq Rs·iq ωe·(Ld·id ψf)看第二项就知道转速ωe升上去之后uq里的反电动势项ωe·ψf会涨得很快。高速时这一项会占掉绝大部分电压预算剩下留给电流调节器做动态调节的电压余量就所剩无几。这就是工程上常说的电压饱和。当电流环PI输出的指令电压Uref已经大于逆变器线性区能给出的最大电压你不管怎么调PI参数输出也上不去了。转速越高越是这样。如果这时候不做处理电流环解耦会失效、id和iq之间互相串扰电流波形畸变转矩脉动加大严重时甚至出现过流报警。1.3 过调制不是把PI调硬一点这么简单很多新手的第一反应是电压不够把PI限幅放开不就行了事情的真相是PI输出限幅放得太宽电压矢量就飞出了六边形边界。而不在合法区域内的电压矢量实际逆变器是发不出来的全被削成边界上的值。削波这件事会让你实际得到的电压矢量方向跟想要的差得越来越远——角度错了电流解耦就乱了。所以过调制的核心本质上不是把限幅加大而是在六边形边界上重新规划电压矢量的轨迹既要尽量逼近你想要的指令值又要保证合成出来的矢量永远不越界。换句话说这是一个有约束条件下的最优逼近问题。接下来要讲的算法就是解决这个逼近问题的一种典型解法。2. SVPWM过调制原理从线性区到六步运行的两段式逼近2.1 先说清楚调制比这把尺子工程里判断过调制深浅习惯用调制比M来表示M Uref / (2Udc/π)。这个分母是六阶梯波运行也就是六个非零电压矢量各占60电角度轮流作用时的基波电压幅值是逆变器在方波模式下能给出的最大电压。线性区对应的调制比是π/(2√3) ≈ 0.907而六步运行对应M 1。过调制的工作区间就是M从0.907到1的这一段越接近1电压波形就越接近方波。这里要强调一个容易被跳过的知识点同样是调制比不同文献用的基准可能不一样。有的用Udc/√3做基准那线性区上限就是1六步是1.1027。看论文时先看分母不然数值对不上容易被绕晕。2.2 过调制一区让电压矢量轨迹贴着六边形走当0.907 M ≤ 0.951具体临界值跟算法实现有一点关系有的文献取0.952时我们称之为过调制一区。此时参考电压矢量的幅值已经略大于内切圆半径但还没大到需要做剧烈修正的程度。一区的经典做法是在大部分扇区保持参考矢量的角度不变只把幅值压到六边形边界以内但某些特定角度处需要让轨迹从内切圆逐渐过渡到六边形边界再过渡回来。有个用起来很顺手的做法是按保持幅值修正角来分段参考矢量在一个电角度周期内大部分时间按原始角度走只有边界交叉处做幅值钳位和角度修正。这样输出的基波幅值基本能跟上指令值而谐波畸变增加得不多。简单说一区的本质是**幅度有损修正、角度尽量保持**它适合调制比刚刚突破线性区的场合。2.3 过调制二区向六步运行状态过渡当M 0.951单纯压幅值已经不够了一区的修正策略下基波幅值会达不到指令。这时要进入二区让电压矢量在扇区边界位置保持不动相当于被锁在某个非零电压矢量上然后在扇区其余部分以修正轨迹快速扫过。保持的时间占比随着M增大而增长当M 1时整个周期都锁在六个非零矢量上就是标准的六步运行。二区的直观理解是把内切圆轨迹逐渐掰成六边形的边锁定在顶点上的时间越来越长。这个阶段谐波明显变大但基波幅值也确实更接近方波极限。因为锁相时间可调整个二区的控制其实可以归一化成一个参数——保持角αh它跟调制比M之间存在一个稳态对应关系算法实现时往往通过查表或者函数逼近来计算αh。2.4 我的实现选择基于几何轨迹修正的过调制关注过调制超过的人可能发现市面上还有基于傅里叶分解的算法、基于电压角度补偿查找表的算法等等。我在Simulink里落地时选的是几何轨迹修正法理由很简单计算量小、逻辑直观、调试方便而且纯Simulink标准模块就能做不依赖复杂工具箱。实现的逻辑框架分三路先按标准SVPWM算出参考电压矢量的幅值Vref和角度θ判断当前调制比M落在哪个区间线性区/一区/二区根据区间对Vref和θ做修正再把修正后的电压交给标准SVPWM发波模块。这样做的另一个好处是底层SVPWM发波模块完全不用动过调制作为它上游的一个预处理器存在出问题也好隔离。3. Simulink仿真模型搭建过调制模块的完整实现过程3.1 仿真模型整体结构这套仿真模型我建议用如下结构搭上游是一个PMSM矢量控制闭环电流环输出Vd、Vq之后做Park反变换得到Vα、VβVα、Vβ进入过调制预处理模块输出修正后的Vα、Vβ再进标准SVPWM发波模块产生六路PWM给逆变器和电机模型。如果你只是验证过调制算法本身可以更简化直接给一个恒幅值恒频率的正弦电压参考前面不加电流环先看开环波形。我实际测试时是先在开环条件下把过调制跑通、波形看对再接上电流环闭环这样排查问题效率高很多。模型里的关键模块拆开来说坐标变换模块用标准Park/Park逆变换注意角度用的是旋变或编码器反馈的电角度过调制函数模块用MATLAB Function写成自定义函数输入Vα、Vβ、Udc、周期Ts输出修正后的Vα_corr、Vβ_corr标准SVPWM模块常规的扇区判断、作用时间计算、七段式调制波生成。3.2 过调制算法的核心代码实现下面是过调制修正函数的核心逻辑我按一区和二区分开写简洁版代码如下function [V_alpha_corr, V_beta_corr] overmodulation(V_alpha, V_beta, Udc, M_mode) % 过调制预处理函数几何轨迹修正法 % 输入V_alpha, V_beta 为参考电压矢量分量 % Udc 为直流母线电压 % M_mode 为当前控制模式0-线性区 1-过调制一区 2-过调制二区 % 输出修正后的电压分量 % 计算参考电压幅值和角度 V_ref sqrt(V_alpha^2 V_beta^2); theta atan2(V_beta, V_alpha); % 线性区最大幅值 V_lin_max Udc / sqrt(3); % 相对调制比以六步电压幅值 2*Udc/pi 为基准 M V_ref / (2*Udc/pi); % 六边形边界约束函数输入角度返回该方向上最大允许幅值 V_max_six (theta) (Udc/sqrt(3)) / cos(mod(thetapi/6, pi/3)-pi/3); switch M_mode case 0 % 线性区直接限幅到内切圆 if V_ref V_lin_max V_ref_corr V_lin_max; else V_ref_corr V_ref; end theta_corr theta; case 1 % 过调制一区角度基本保持幅值压缩到六边形边界 V_boundary V_max_six(theta); if V_ref V_boundary V_ref_corr V_boundary; else V_ref_corr V_ref; end theta_corr theta; case 2 % 过调制二区引入保持角在扇区边界锁定电压矢量 % alpha_h 是与调制比相关的保持角可查表或由函数逼近得到 alpha_h hold_angle_lookup(M); % 单位rad theta_mod mod(theta, pi/3); if theta_mod alpha_h % 锁定在扇区起始边界 theta_corr floor(theta / (pi/3)) * (pi/3) alpha_h; V_ref_corr V_boundary; elseif theta_mod (pi/3 - alpha_h) % 锁定在扇区结束边界 theta_corr floor(theta / (pi/3)) * (pi/3) (pi/3 - alpha_h); V_ref_corr V_boundary; else % 中间区域幅值压缩到边界 V_boundary V_max_six(theta); V_ref_corr min(V_ref, V_boundary); theta_corr theta; end otherwise V_ref_corr V_ref; theta_corr theta; end % 坐标还原 V_alpha_corr V_ref_corr * cos(theta_corr); V_beta_corr V_ref_corr * sin(theta_corr); end这里的hold_angle_lookup是保持角的查找函数工程上常用的做法是把 M 和 αh 的稳态对应关系做成一张表或者用多项式拟合。我实测时发现用简单的二次多项式拟合在全调制比区间误差就能控制在工程可接受范围内。3.3 关键参数设置和采样注意事项逆变器开关频率我建议设10kHz太高了仿真速度慢太低了谐波分析不好看Simulink求解器用离散变步长discrete步长设1e-5PWM载波生成用三角波比较法三角波周期1e-4s对应10kHz电机参数用一台典型的表贴式PMSM极对数4、定子电阻0.5Ω、LdLq8.5mH、永磁磁链0.175Wb直流母线电压设300V注意MATLAB Function里避免用连续谱变量输入输出维数要一眼能看出来否则代码生成时会报错。4. 仿真结果与性能对比电压利用率到底提升了多少4.1 从仿真曲线看线性区、一区、二区的差异模型搭好之后先做开环测试。我直接给定一个幅值持续增大的正弦电压参考让调制比从0.85慢慢爬到1.0记录输出相电压的波形和FFT结果。线性区内M0.9左右相电压波形是标准的SVPWM调制波频谱里谐波主要集中在开关频率及其边带附近基波幅值和指令值一致。进入一区M0.93左右可以明显看到相电压波形顶部开始出现削平的迹象但削平不严重。FFT结果显示基波幅值仍然能跟上指令但低次谐波5次、7次为主开始冒头总谐波畸变率THD从线性区的2%~3%上升到5%左右。进入二区M0.97及以上相电压波形削平变得非常明显波形已经趋向六阶梯波。此时5次、7次谐波幅值进一步增大THD可能到10%以上。如果拿三相线电压看阶梯波特征更直观——每60度一个台阶正是六步运行的典型表现。4.2 实测对比数据我把一组典型数据整理如下供参考给定调制比实际基波幅值VTHD%电压利用率提升0.90155.52.8基准0.93160.15.13%0.96166.28.46.9%1.00173.513.611.6%这里直流母线300V理论六步基波幅值2Udc/π≈191V实际由于死区和开关管压降仿真里能到173V已经算不错。电压利用率提升的数字看起来不大但在高速弱磁区这百分之几到十几的提升往往意味着电机能多跑几百转或者母线电压低一点也能维持同样的最高转速对整车续驶里程和最大车速都有实际意义。4.3 为什么THD变大却仍然值得用看到THD到13%以上有些人可能会犹豫谐波这么大电机受得了吗答案取决于应用场景。过调制本来就不是让你长期运行在满调制比的状态的它存在的意义是在极端工况下把电压榨干用尽。比如一台电动车在高速巡航、偶尔需要急加速超车时过调制介入几秒钟让电机在那个瞬间多输出一点转矩、多爬一点转速代价是发热和噪音增加——这往往是可以接受的。又比如一些对成本敏感的工业变频器为了省掉一级DC-DC升压希望母线电压更低一些那过调制就能在额定工况附近帮你把电压利用率找补回来。工程决策的本质是权衡过调制只是给了你多一种权衡的手段。5. 工程实践中的坑与应对策略5.1 低速轻载工况下千万别让过调制误触发这是我在现场吃过最大的一次亏。当年给一台实验台架调程序低速空载时电流环输出很小但转速PI输出电角度变化很快采样噪声导致Vα、Vβ瞬时幅值出现尖峰过调制误判为调制比过高结果一触发电压波形就开始削波电流畸变、电机噪音骤增整个台架看起来像出了严重故障。后来排查下来的根因是过调制判断用瞬时幅值而瞬时幅值受电流环PI动态和采样噪声影响很大。解决办法是加一个平均滤波对Vα、Vβ先做一阶低通再算幅值判断调制比同时用转速信号做条件使能——只有转速高于某个阈值时才允许过调制介入。低速段电压本来就不缺完全不需要过调制。5.2 母线电压测量不准过调制就是灾难过调制算法里有个关键参数Udc直接参与所有计算。如果Udc采样值偏大算法会以为还有电压余量把指令电压顶到边界上实际逆变器已在削波如果Udc采样值偏小线性区限幅又会过早触发浪费电压利用率。这一进一出可能造成5%~10%的性能差异。我在做硬件在环测试时发现母线电压采样滤波时间常数不能太大否则动态工况下Udc更新滞后过调制响应慢半拍容易在负载突加时短暂失控。建议采样频率不低于10kHz滤波做50μs左右的一阶惯性即可。另外软件里要对Udc做合理上限和下限钳位防止传感器损坏时算法飞掉。5.3 死区时间是过调制波形畸变的放大器死区造成的电压误差在正常调制比下占比小但进入过调制后因为PWM波在部分区间已经接近满占空比或零占空比死区补偿不足会导致相电压出现明显的平台和缺口进一步加重电流谐波。我的经验是做纯算法验证时死区可以设1~2μs先忽略影响但做工程评估时死区必须设实际值比如2.5μs而且在离线仿真和台架实测两边保持一致不然谐波对比数字完全对不上。如果你手头有死区补偿模块过调制运行时最好保持补偿开启。虽然补偿算法在饱和区间可能达到极限但至少能减少一半以上的死区误差。5.4 过调制和弱磁控制的分工很多人把过调制当成弱磁的替代品这其实是个误解。弱磁控制处理的是反电动势超过电压极限的问题它通过注入负的id电流来削弱气隙磁场从而在电压约束下让电机转速更高。这个过程是连续的、动态的需要电流环深度参与。而过调制处理的是电压指令超出了逆变器线性输出能力的问题它不改变电机的磁链状态只是让逆变器尽量把你想要的电压合出来。两者的关系是互补的在弱磁区电流调节器给出的电压指令经常超过线性区上限此时就需要过调制来兜底弱磁负责把工作点往高转速方向推过调制负责把这个工作点上所需要的电压实际合出来。工程上常常是两者一起启用只不过过调制的激活深度要跟弱磁深度配合好。5.5 从Simulink模型到嵌入式代码移植的要点模型在Simulink里跑通之后很多人马上就想到生成嵌入式代码。过调制模块用MATLAB Function写的话代码生成一般没问题但要注意几点MATLAB Function里不要用可变大小数组保持输入输出维度静态hold_angle_lookup如果用的是查表建议用Lookup Table模块而不是在MATLAB Function里写大数组所有内部变量建议显式初始化生成代码前开启模型数据字典把过调制相关参数集中管理定点化也要提前考虑浮点转定点时角度计算最容易丢精度建议角度用Q16格式幅值用Q12格式。我在嵌入式平台STM32F407上实测过过调制模块折算到100MHz主频上单次调用大约耗时5μs相比整个FOC控制周期50μs来说开销完全可以接受。6. 调试过调制算法的几个实用技巧6.1 用开环扫频法快速验证算法正确性接上闭环之前先用开环模式跑一遍是最稳妥的办法。给定一组幅值在1V到200V之间线性爬升的Vα、Vβ正弦波频率固定50Hz记录输出相电压和电流波形。如果出现过调制模块输出跳变异常或者角度跳跃开环下能一眼看出来。我习惯在这个阶段多添加几个观测点原始Vref、修正后Vref、原始角度、修正后角度全部送进Scope。比对这四个观测量就能清楚看到算法在哪一段做了修正、修正量有多大比事后分析输出波形高效得多。6.2 用调制比渐变验证各区切换的连续性过调制一区和二区之间切换时如果不做平滑处理会出现电压跳变进而引发电流冲击。我在仿真里做过一次测试把调制比从0.9连续渐变到1.0观察过调制模块输出的幅值曲线——理想情况下曲线应该是连续渐变的没有台阶。如果你的实现里一区、二区是两套独立逻辑中间又没有插值过渡切换那一下往往会出现幅值回退或突跳。解决办法是设置一个滞回区间升调制比时M从0.95切二区降调制比时M回到0.94才切回一区滞回可以抑制临界区间的不确定性抖动。6.3 用冻结PWM法检查过调制对电流环的稳定性影响过调制介入后电流环等效增益会发生变化因为从电流环输出到实际PWM电压的传递关系不再是线性的。简单说调制比接近1时电压增量对PI输出的敏感度下降相当于环路增益变小。有一个很有效的调试方法把电机锁定转子或仿真中固定转速不动给定一个固定的电压矢量幅值和角度然后缓慢增加这个幅值看稳态电流是否平稳。如果出现过调制修正导致角度跳变电流会跟着抖动。用这个方法可以快速暴露过调制和电流环的耦合问题比跑完整动态工况容易定位。7. 我的个人体会做了这么多年代码和台架过调制在我眼里就像一个含金量高但又不常出镜的配角。它不会像FOC那样天天被挂在嘴边但到了整车高速实测、到了客户要极限车速、到了冬天电池电压低导致母线掉压的时候过调制往往就是补上最后那百分之几性能的关键拼图。如果你正在调试中发现母线电压明明够高、但是电流环输出就是被削顶先别急着怀疑PI参数先想想是不是该引入过调制如果你的Simulink模型里过调制模块的行为和理论对不上先回到开环把Vref和角度两个观测点看仔细90%的问题都能在开环阶段排掉。这套流程我反反复复用下来踩过的坑基本都是走了一遍弯路才摸清楚的希望你看了这篇之后能少走两步弯路。