三相逆变器六种DPWM调制仿真:零序分量与钳位实现全解析
2026/9/14 4:44:35 网站建设 项目流程

写这种东西最怕的就是“抄了一堆波形图,回头问你为什么长这样,答不上来”。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 - umax
  • N型钳位:把当前最小相钳位到负母线,注入的零序分量为 u0 = -1 - umin

S为1时执行P型钳位,S为0时执行N型钳位。那么统一表达式就是:

u0 = S × (1 - umax) + (1 - S) × (-1 - umin)

这样一来,六种DPWM的全部差异就浓缩成一句话:S这个0/1信号在60度扇区内怎么变化。

根据三相正弦波的对称性,一个工频周期可以分成6个60度扇区。每个扇区内,哪一相是最大相、哪一相是最小相是确定的:

扇区角度范围最大相最小相中间相
10°~60°ACB
260°~120°BCA
3120°~180°BAC
4180°~240°CAB
5240°~300°CBA
6300°~360°ABC

这个表是后面搭模型的基础,S序列的Lookup Table就是按这个扇区顺序来查的。

1.3 六种DPWM的S序列定义与钳位窗特征

不同教材对DPWM0~DPWM3的编号定义确实存在差异,我这里给出的是我在仿真中实际使用的一套定义,能保证六种方式在同一个平台下公平对比。你如果看到别的文献里编号对不上,不用纠结,替换S序列表即可,整个仿真模型架构不需要动。

六种S序列定义如下:

  • DPWMMIN:S恒为0,即始终把最小相钳位到负母线,每相下管持续导通约120°。
  • DPWMMAX:S恒为1,即始终把最大相钳位到正母线,每相上管持续导通约120°。
  • DPWM0:每个60°扇区内S恒定,按扇区交替 [1, 0, 1, 0, 1, 0]。
  • DPWM1:每个60°扇区内S恒定,按扇区交替 [0, 1, 0, 1, 0, 1]。
  • DPWM2:S每30°切换一次,序列为 [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]。
  • DPWM3:S每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。

仿真参数如下:

  • 直流母线电压Vdc:700V
  • 调制比m:0.9(注意不要超过1.15的线性区上限)
  • 基波频率:50Hz
  • 载波频率:5kHz
  • 负载:三相对称RL负载,R=10Ω,L=15mH
  • 仿真步长:定步长1e-6s

RL负载的好处是电流连续性好,波形平滑,便于观察调制策略对电流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模块生成。

接下来分四步走:

  1. 求最大值umax和最小值umin。用MinMax模块,选三个输入,输出选Max和Min各一个。
  2. 根据S序列表做Lookup Table。如果S是60°级别的变化,可以直接用扇区号去查表;如果S是30°级别的变化(DPWM2、DPWM3),就把theta映射到12个区间再查表。
  3. 计算零序分量u0 = S × (1 - umax) + (1 - S) × (-1 - umin)。这里用两个Product和一个Add就能搞定,S做一个比较或直接查表得到。
  4. 三相调制波分别加上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°附近被钳到+1,B相在60°~180°附近被钳到+1,C相在180°~300°附近被钳到+1。这个特征验证通过,说明零序分量计算没问题。

第二级:接上主电路,看逆变器输出线电压Uab的波形。线电压应该是六个电平的阶梯波,幅值在±Vdc、±2Vdc/3、±Vdc/3之间跳变。这一步验证PWM脉冲是否正确分配到了三相桥臂。

我实际遇到的情况是:第一级波形正确,但线电压波形乱跳。最后查出来是三角载波的相位和S序列的起始相位没有对齐。具体来说,theta=0对应A相参考波的正峰值,但我的S序列在theta=0时处于扇区1的边界,如果S序列的0°起点选错了,整个钳位区间就会错位30°到60°,波形当然不对。解决方法是统一以A相参考波的峰值点作为theta=0的参考点。

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/3,IGBT的开关损耗大致按开关次数线性变化,所以理论上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里看看。S=1时,应该能看到最大相调制波正好被顶到1那条线上;S=0时,最小相调制波应该被压到-1。如果S的切换点和钳位区间对不上,那就是角度起点没对齐。

最后说点我自己的体会

DPWM这类策略真正难的地方不在于公式推导,而在于你想清楚“我为什么要省这1/3的开关损耗”以及“省下来的损耗能不能值回增加的谐波”。我做仿真的时候,习惯先把六种DPWM全部跑一遍,把调制波和电流波形的截图存下来,然后回到工程需求去选型:如果整套系统对散热体积特别敏感,就选钳位窗和电流峰值最匹配的那一种;如果对输出谐波要求苛刻,那不如老老实实用SVPWM。

另外一个很实用的技巧是:把这六种DPWM的S序列生成逻辑封装成一个函数,参数化type编号。后面不管是做电机控制还是并网逆变器,同一个函数直接复用,改一下调制比和载波频率就能出结果。仿真这东西,一次搭好,后面就是收益。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询