
写这种东西最怕的就是“抄了一堆波形图回头问你为什么长这样答不上来”。DPWM不连续脉宽调制在逆变器控制里不是新东西但能一次性把DPWM00、DPWM01、DPWM02、DPWM03、DPWMMIN、DPWMMAX这六种全部跑通、对比明白的人确实不多。我今天就把自己搭建三相两电平逆变器六种DPWM调制仿真模型的完整过程写下来包括算法原理、Simulink实现细节、波形特征和调试时踩过的坑。这套内容适合正在做电机驱动、并网变流器、储能PCS控制算法的工程师也适合电力电子方向的研究生拿来作为毕业论文的仿真基础。六种DPWM的差异说穿了就是“往三相调制波里注入什么样的零序分量”。零序分量选得不一样调制波被钳位到正母线或负母线的区间就不一样开关管不动作的时间长短和位置也就不一样。这个“钳位”动作就是DPWM比SVPWM省开关损耗的根本原因。我的目标是让你看完之后能自己动手在Matlab/Simulink里复现不靠别人给的模型文件也能从零搭出来。1. 六种DPWM算法到底在改什么一个零序分量框架说清楚1.1 从SPWM到SVPWM再到DPWM绕不开的零序分量三相两电平逆变器的核心问题很简单怎么把直流母线电压变成频率、幅值可控的三相交流电压。SPWM最直接三相正弦波各自和三角载波比较SVPWM稍微绕一点但从结果看等效于在三相正弦波里注入一个零序分量公式是u0 -0.5 × (umax umin)其中umax是三相参考波的最大值umin是最小值。注入之后三相调制波的峰值被压缩线性调制比能从1.0提高到1.15直流电压利用率更高了。DPWM的思路更极端注入的零序分量不是让调制波“压缩”而是让某一相的调制波直接撞到±1的限幅上也就是被钳位到正母线或者负母线。这一相在这个区间内不动作开关管不切换开关损耗直接归零。你可以这么理解SVPWM让三相开关管雨露均沾每相在每个载波周期都参与开关DPWM则是每个时刻集中“压榨”某一相让这一相持续导通或持续关断其他两相正常PWM。三相轮流休息总的开关次数就降下来了。1.2 钳位逻辑的核心P/N选择信号S工程实现上我不喜欢用复杂的扇区矢量图去推而是直接用“P/N选择信号S”。先定义两个钳位方向P型钳位把当前最大相钳位到正母线注入的零序分量为 u0 1 - umaxN型钳位把当前最小相钳位到负母线注入的零序分量为 u0 -1 - uminS为1时执行P型钳位S为0时执行N型钳位。那么统一表达式就是u0 S × (1 - umax) (1 - S) × (-1 - umin)这样一来六种DPWM的全部差异就浓缩成一句话S这个0/1信号在60度扇区内怎么变化。根据三相正弦波的对称性一个工频周期可以分成6个60度扇区。每个扇区内哪一相是最大相、哪一相是最小相是确定的扇区角度范围最大相最小相中间相10°~60°ACB260°~120°BCA3120°~180°BAC4180°~240°CAB5240°~300°CBA6300°~360°ABC这个表是后面搭模型的基础S序列的Lookup Table就是按这个扇区顺序来查的。1.3 六种DPWM的S序列定义与钳位窗特征不同教材对DPWM0~DPWM3的编号定义确实存在差异我这里给出的是我在仿真中实际使用的一套定义能保证六种方式在同一个平台下公平对比。你如果看到别的文献里编号对不上不用纠结替换S序列表即可整个仿真模型架构不需要动。六种S序列定义如下DPWMMINS恒为0即始终把最小相钳位到负母线每相下管持续导通约120°。DPWMMAXS恒为1即始终把最大相钳位到正母线每相上管持续导通约120°。DPWM0每个60°扇区内S恒定按扇区交替 [1, 0, 1, 0, 1, 0]。DPWM1每个60°扇区内S恒定按扇区交替 [0, 1, 0, 1, 0, 1]。DPWM2S每30°切换一次序列为 [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]。DPWM3S每30°切换一次序列为 [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]。这里要特别说明一下DPWMMIN和DPWMMAX的区别。DPWMMAX是把“最大相”一直钳到正母线所以A相在300°~60°这120°范围内被钳到1正好包住A相电压的正峰值DPWMMIN是把“最小相”一直钳到负母线A相在120°~240°这120°范围内被钳到-1包住A相电压的负峰值。而DPWM0和DPWM2的钳位窗相对电压峰值有偏移这就带来一个非常重要的工程问题开关损耗最优的位置不在电压峰值处而在电流峰值处。当功率因数不为1时电流峰值和电压峰值是错开的所以你需要根据负载的功率因数角来挑DPWM类型。这也是为什么工程上不只用DPWMMAX和DPWMMIN两种还要保留DPWM0~3这种可调钳位窗位置的原因。2. Simulink仿真模型搭建从零序分量到六路PWM脉冲2.1 主电路参数设置模型整体分两部分主功率电路在前控制算法在后。主电路我用的是Simulink里的Universal Bridge模块设成两电平三相桥臂开关器件选IGBT/Diodes。仿真参数如下直流母线电压Vdc700V调制比m0.9注意不要超过1.15的线性区上限基波频率50Hz载波频率5kHz负载三相对称RL负载R10ΩL15mH仿真步长定步长1e-6sRL负载的好处是电流连续性好波形平滑便于观察调制策略对电流THD的影响。如果是做电机控制后面可以把RL负载替换成永磁同步电机模型但调制算法部分不需要改。为什么要用定步长而不是变步长因为PWM调制本身就是离散事件载波比较在每个仿真步长上都会发生变步长求解器在开关时刻附近会疯狂加密步长导致仿真速度慢到一个离谱的程度。定步长1e-6秒配合5kHz载波一个载波周期有200个采样点足够还原PWM细节了。2.2 零序分量生成器六种DPWM的统一核心模块这个模块是整套模型的大脑。输入是三相参考波ua、ub、uc和电角度theta输出是加完零序分量之后的三相调制波。以A相为例参考波表达式为ua_ref m × cos(theta)同理ub_ref和uc_ref分别滞后120°和240°。这三个量可以直接通过Clock模块计算theta再经Trigonometric Function模块生成。接下来分四步走求最大值umax和最小值umin。用MinMax模块选三个输入输出选Max和Min各一个。根据S序列表做Lookup Table。如果S是60°级别的变化可以直接用扇区号去查表如果S是30°级别的变化DPWM2、DPWM3就把theta映射到12个区间再查表。计算零序分量u0 S × (1 - umax) (1 - S) × (-1 - umin)。这里用两个Product和一个Add就能搞定S做一个比较或直接查表得到。三相调制波分别加上u0进入载波比较环节。我自己会在Matlab Function模块里写这个逻辑因为用纯Simulink积木搭起来比较绕。核心代码我贴在这里方便你直接测function [ua_m, ub_m, uc_m] dpwm_gen(theta, m, type) % theta: 电角度(rad) % m: 调制比 % type: 1-DPWMMIN, 2-DPWMMAX, 3-DPWMO, 4-DPWM1, 5-DPWM2, 6-DPWM3 ua m * cos(theta); ub m * cos(theta - 2*pi/3); uc m * cos(theta 2*pi/3); umax max([ua, ub, uc]); umin min([ua, ub, uc]); % 将角度映射到0~360度 theta_deg mod(theta * 180/pi, 360); % 60度扇区: 1~6 sec floor(theta_deg / 60) 1; % 30度块: 1~12 blk floor(theta_deg / 30) 1; switch type case 1 S 0; case 2 S 1; case 3 S_table [1 0 1 0 1 0]; S S_table(sec); case 4 S_table [0 1 0 1 0 1]; S S_table(sec); case 5 S_table [1 0 1 0 1 0 1 0 1 0 1 0]; S S_table(blk); case 6 S_table [0 1 0 1 0 1 0 1 0 1 0 1]; S S_table(blk); end u0 S * (1 - umax) (1 - S) * (-1 - umin); ua_m ua u0; ub_m ub u0; uc_m uc u0; end代码本身不复杂但type参数的切换很方便跑对比仿真的时候一个For循环就能批量出六组结果。2.3 载波比较与死区设置调制波生成之后下一步就是跟三角载波比较生成PWM脉冲。三角载波幅值范围是-1到1频率5kHz我直接用Repeating Sequence模块生成参数设为[0 1/5000]时间区间内从-1线性到1再回到-1的三角波。载波比较用Relational Operator模块调制波大于载波时输出1否则输出0。上管驱动信号就是比较器输出下管驱动信号取反。但直接取反在工程上是不允许的因为没有死区时间上下管可能直通炸桥。我用的是Universal Bridge自带的死区设置在桥臂参数里直接填死区时间。如果你是用离散的IGBT和Diode自己搭桥臂就得上Transport Delay模块或编写死区逻辑。死区时间我设了2μs。注意死区大小直接影响输出波形的THD死区越大电流波形畸变越明显。仿真里设2μs是为了贴近实际工况你如果只是做算法验证设成0.5μs甚至0都可以但那样会忽略死区效应带来的谐波跟实际装置有偏差。2.4 验证模块输出先看调制波再上主电路新手最容易犯的错就是模型一搭完直接跑波形不对也不知道问题出在哪。正确做法是分两级验证。第一级断开主电路直接看调制波。把ua_m、ub_m、uc_m接到Scope上看是否有被钳位到±1的区间。比如DPWMMAX模式下A相调制波应该在300°~60°附近被钳到1B相在60°~180°附近被钳到1C相在180°~300°附近被钳到1。这个特征验证通过说明零序分量计算没问题。第二级接上主电路看逆变器输出线电压Uab的波形。线电压应该是六个电平的阶梯波幅值在±Vdc、±2Vdc/3、±Vdc/3之间跳变。这一步验证PWM脉冲是否正确分配到了三相桥臂。我实际遇到的情况是第一级波形正确但线电压波形乱跳。最后查出来是三角载波的相位和S序列的起始相位没有对齐。具体来说theta0对应A相参考波的正峰值但我的S序列在theta0时处于扇区1的边界如果S序列的0°起点选错了整个钳位区间就会错位30°到60°波形当然不对。解决方法是统一以A相参考波的峰值点作为theta0的参考点。3. 仿真结果对比波形、THD和开关损耗的取舍逻辑3.1 调制波与钳位效果解读六种DPWM跑完最直观的差异就在三相调制波的形状上。DPWMMAX的A相调制波在正半周有一段是平的那条平的线段就是上管常通区间DPWMMIN则在负半周有一段平线对应下管常通区间。这两者看起来是“正负镜像”的关系。DPWM0和DPWM1的调制波波形介于DPWMMAX和DPWMMIN之间钳位区间不再完全覆盖电压峰值而是偏移了30°。这个偏移在示波器上不容易一眼看出来但你把A相电流波形叠加上去对比就能发现DPWM0的钳位区间跟A相电流峰值的位置是错开的而DPWMMAX的钳位区间跟电压峰值重合。如果负载是阻感性电流滞后电压那么在功率因数角约30°的情况下DPWM0反而能让钳位区间更贴近电流峰值开关损耗更低。DPWM2和DPWM3因为S每30°切换一次调制波上会出现更频繁的转折钳位区间被切成了更碎的小段。代价是谐波性能会变差但换来的是钳位窗位置更灵活可以根据实际功率因数角去匹配最佳钳位点。这就是为什么DPWM0~3在工程上不是多余的它们提供了损耗和THD之间的不同取舍点。3.2 电流THD和电压利用率对比我在离线状态下对六种DPWM的输出电流做了FFT分析统一取A相电流分析窗口取10个基波周期基波50Hz频谱分辨率5Hz。测量条件是调制比0.9、RL负载不变。定性结论如下调制方式电流THD相对水平开关损耗相对水平适用场景SPWM最低最高小功率、对噪声敏感SVPWM较低较高通用场合DPWMMAX较高较低单位功率因数大功率DPWMMIN较高较低单位功率因数大功率DPWM0/DPWM1中等中等功率因数角约±30°DPWM2/DPWM3最高最低功率因数角较大场合注意这个THD排序不是绝对的。DPWM的谐波主要集中在开关频率附近的边带如果你只看低频段THD差异有可能被小到工程上可以忽略。但开关损耗的差异是硬性的DPWM的每相平均开关频率只有连续调制方式的2/3IGBT的开关损耗大致按开关次数线性变化所以理论上DPWM最多能省下约1/3的开关损耗。实际工程中风扇和散热器的体积很多时候是被开关损耗决定的。这就是为什么在大功率变流器里DPWM类调制策略应用非常广泛——芯片本身不贵但散热系统贵。3.3 一个容易忽略的细节功率因数角对DPWM选型的影响很多工程师以为DPWMMAX就是最优解因为它把损耗降得最多。但你忽略了一个事实开关损耗的瞬时值正比于开关时刻的电流瞬时值。也就是说如果钳位区间设在电流很小的地方省下的开关损耗就很少如果钳位区间正好把电流很大的区域给“躲过去”了那省下的损耗才可观。用单位功率因数电阻负载来看DPWMMAX的钳位窗刚好包住电流峰值损耗降低最明显。但换成感性负载比如功率因数角60°此时电压峰值和电流峰值差了60°DPWMMAX的钳位窗虽然在电压峰值附近但电流早就过了峰值了省损耗的效果大打折扣。这时你需要DPWM2或DPWM3这种能把钳位窗挪到电流峰值附近的策略。从仿真角度看验证这个现象的办法是给RL负载换不同的L值让功率因数角变化然后对比不同DPWM下IGBT的导通电流和开关时刻的乘积积分。这个量可以近似用平均开关损耗的评估方式去算不需要真的去做热仿真。4. 调试过程中踩过的坑与排查技巧4.1 调制比过大导致调制波削波有一次我把调制比直接拉到1.15理论上SVPWM可以线性运行但DPWM部分波形还是出现了削波。检查之后发现SVPWM的1.15线性上限是针对特定零序分量的DPWM的零序分量是分段非线性的线性调制比上限不一定能到1.15。DPWMMAX在调制比1.15时注入零序后某些相调制波已经触到-1限幅了。解决办法很简单要么把调制比降到1.0以下要么在调制波进比较器之前加饱和限幅块。但我建议仿真时保持调制比0.8~1.0不要挑战上限否则THD分析结果会把过调制谐波也算进去六种DPWM之间就没法公平对比了。4.2 三角载波频率和仿真步长不匹配仿真步长我踩过1e-5s的坑。5kHz载波步长1e-5s的话一个载波周期只有10个采样点PWM波形阶梯感极重调制波和载波的交点误差非常大导致输出的电流THD偏高而且六种DPWM的差异被噪声淹没。后来改成1e-6s一个载波周期200个采样点波形就干净了。如果你用的是变步长求解器建议把最大步长限制在载波周期的1/100以内。以5kHz载波为例最大步长要小于2e-6s否则你看到的PWM波形可能是“假”的。4.3 FFT分析窗口设置不对THD分析的一个经典坑是分析窗口太短。如果你只取两三个基波周期做FFT频谱泄漏很严重THD数值会飘来飘去。我一般是取10个周期而且等仿真跑到稳态之后再开始记录数据。阻感负载的启动过程有暂态电流这个暂态分量会严重影响THD统计。另一个细节是采样率。从Scope里导出的波形默认间隔是仿真步长1e-6s用powergui的FFT分析工具时要设置好基波频率50Hz最大频率至少取到开关频率的5倍也就是25kHz这样高频边带谐波才不会漏算。4.4 死区影响钳位效果加了死区之后钳位相的互补管在死区时间内会短暂导通看起来好像钳位不再“干净”了。这其实是正常的。死区期间电流通过反并联二极管续流电压波形会出现毛刺但只要死区时间远小于载波周期对钳位时长的总体影响是可以接受的。如果你发现钳位区间的波形出现明显的窄脉冲先检查是不是死区时间设置得过大。我试过10μs的死区5kHz载波周期是200μs死区占了5%调制波边缘被明显侵蚀THD显著上升。2μs比较合适。4.5 S序列的扇区起始角对不上这个坑我建议每个新手都亲自踩一遍。因为三相参考波的初始相位会影响扇区划分。我在代码里把theta 0定义为A相参考波的峰值点也就是cos波起始点。如果你的参考波用的是cos(theta - pi/2)之类的表达扇区边界就会整体偏移90°S序列查出来的钳位对象全错波形混乱程度堪比白噪声。排查方法很简单把S的值和三相调制波同时拉到一个Scope里看看。S1时应该能看到最大相调制波正好被顶到1那条线上S0时最小相调制波应该被压到-1。如果S的切换点和钳位区间对不上那就是角度起点没对齐。最后说点我自己的体会DPWM这类策略真正难的地方不在于公式推导而在于你想清楚“我为什么要省这1/3的开关损耗”以及“省下来的损耗能不能值回增加的谐波”。我做仿真的时候习惯先把六种DPWM全部跑一遍把调制波和电流波形的截图存下来然后回到工程需求去选型如果整套系统对散热体积特别敏感就选钳位窗和电流峰值最匹配的那一种如果对输出谐波要求苛刻那不如老老实实用SVPWM。另外一个很实用的技巧是把这六种DPWM的S序列生成逻辑封装成一个函数参数化type编号。后面不管是做电机控制还是并网逆变器同一个函数直接复用改一下调制比和载波频率就能出结果。仿真这东西一次搭好后面就是收益。