简介:面向电机控制与电力电子方向研究人员、工程师的学习资料,聚焦永磁同步电机5次与7次电流谐波的成因与注入补偿方案,通过Simulink建模仿真抑制转矩脉动、效率下降与发热问题。资源包共1个PDF文件,约115KB,内容涵盖气隙磁场非正弦、齿槽效应等谐波来源分析,以及电机参数配置、FFT谐波检测、反相位注入信号生成、PI闭环控制等完整建模环节,并附MATLAB/Simulink代码示例与仿真前后频谱对比。已有51人学习下载。读者可从中获得谐波检测与相位对齐、带通滤波器应用、电压限幅保护与补偿量限制等实用经验,理解从坐标变换分离谐波到补偿量注入的实现思路,为实际工程项目中优化电流质量、降低转矩脉动提供可参照的建模流程与调试参考。
1. 5次7次谐波在PMSM电流环里到底长什么样:从一条毛刺波形说起
台架上电机空载拉到3000rpm,示波器里相电流看着挺圆,一挂FFT,250Hz和350Hz两根柱子明晃晃地立着——这就是永磁同步电机里最典型的5次、7次电流谐波。这套Simulink仿真模型干的事很具体:在FOC双闭环基础上,把这两根柱子检测出来,生成幅值相同、相位相反的谐波注入信号顶回去,再用电流频谱和转矩脉动验证效果。它适合已经在做PMSM电流环、被THD卡在5%以上下不来的工程师,也适合刚接触谐波抑制、想找一个能跑通、能改参数的最小闭环的人。基波50Hz下5次是250Hz、7次是350Hz,频率不算高,但补偿通道里相位差个二三十度,效果就从抑制变成放大,后面几章基本都围着这件事展开。
2. Simulink骨架:从电机参数到谐波检测链的搭建顺序
模型的搭建顺序比模块本身更影响后面调不调得动。我的习惯是先固化参数、再打通坐标变换、最后接检测环节,因为谐波检测一旦建立在错误的旋转角或非整周期窗口上,后面所有补偿通道的参数整定都是在错误的基线上做无用功。这一章按这个顺序把骨架拆开。
2.1 电机与逆变器参数:发散多半出在这一步
Simulink自带的PMSM模块要填的参数不少,但真正决定模型能不能跑、跑出来像不像的只有那几个:定子电阻、dq电感、永磁体磁链、极对数、转动惯量,再加上逆变器的开关频率、母线电压和死区时间。参数表里最容易被随手填错的是极对数和磁链的组合——两个都改成"看着顺眼"的数值,反电动势系数就跟着飘,电流环PI按错误的增益整定,一上负载就振荡。
我一般把参数写成独立脚本,在模型的InitFcn里调用,这样换一台电机只改一处:
% PMSM 与逆变器基础参数,放在 model_init.m,由 InitFcn 调用 clear; clc; pmsm.Pn = 3000; % 额定功率 W pmsm.Un = 380; % 额定线电压 V pmsm.fn = 50; % 额定频率 Hz pmsm.pn = 4; % 极对数,机械转速 = 电频率*60/pn pmsm.Rs = 2.875; % 定子相电阻 Ohm pmsm.Ld = 8.5e-3; % d 轴电感 H pmsm.Lq = 8.5e-3; % q 轴电感 H(表贴式取 Ld = Lq) pmsm.psi_f = 0.175; % 永磁体磁链 Wb pmsm.J = 0.0008; % 转动惯量 kg*m^2 pmsm.B = 1e-4; % 粘滞阻尼 N*m*s inv.fsw = 10e3; % 开关频率 Hz inv.Ts = 1e-5; % 仿真步长 s,取开关周期的 1/10 inv.Vdc = 540; % 直流母线电压 V inv.Tdead = 2e-6; % 死区时间 s,谐波的主要来源之一 inv.Verr = 0.5; % 管压降 V,和死区一起决定低次谐波幅值 % 基波电角频率,谐波检测和 PR 控制器都用它 w_e = 2*pi*pmsm.fn;这段脚本的关键在于三处:pn决定电角度和机械角度的换算关系,写错会让转速环的输出完全对不上;psi_f与pn共同决定反电动势常数,进而决定同样的母线电压下能跑多高的转速;Tdead和Verr是可选项,但如果不填,电流里的5次、7次谐波就只剩绕组分布和齿槽效应贡献的部分,幅值会比实测小一截,补偿做完看着效果很好,换到实机就露馅。
提示:表贴式电机取
Ld = Lq,模型里凸极率为零,转矩脉动只来自谐波电流;如果做内置式,Lq要大于Ld,此时磁阻转矩会引入额外的6次脉动,频谱上容易和7次谐波混淆,读图时要分清。
母线电压和开关频率的组合决定电流纹波幅值,也决定仿真步长能不能取到1e-5。步长再放大到5e-5,PWM 边沿就采不准,谐波频谱的底噪会抬高,5次、7次的幅值读数跟着漂。这部分参数没有玄学,就是老老实实按开关周期十分之一取。
2.2 Clarke/Park与5、7次谐波旋转坐标系:方向搞反等于白干
坐标变换是谐波分离的核心。基波在同步旋转坐标系下是直流量,这个大家都知道;但5次和7次的序不同,这一点如果没搞清楚,后面补偿一定是反的。
在三相系统中,5次谐波是负序分量,7次是正序分量。也就是说,5次谐波在空间上相序与基波相反。当把它投影到以 +ω 正向旋转的同步坐标系时,它表现为 -6ω 的交流量;投影到 -5ω 的旋转坐标系时,才变成直流量。7次谐波投影到 +7ω 坐标系时变成直流量。原文示例里写theta_5h = 5*theta_e,如果直接照抄,5次谐波不会被搬到直流,反而会变成 -10ω 的交流量,低通滤波器根本滤不出来——这是最容易翻车的一处。
下面这段把两路分离写全,5次取负角度:
function [id, iq] = park_fwd(ialpha, ibeta, theta) % 正向 Park 变换:alpha/beta -> d/q c = cos(theta); s = sin(theta); id = c*ialpha + s*ibeta; iq = -s*ialpha + c*ibeta; end function [ualpha, ubeta] = park_inv(ud, uq, theta) % 反向 Park 变换:d/q -> alpha/beta c = cos(theta); s = sin(theta); ualpha = c*ud - s*uq; ubeta = s*ud + c*uq; end % ---- 谐波分离:5 次负序取 -5θe,7 次正序取 +7θe ---- theta_5 = -5 * theta_e; % 注意负号,这是 5 次谐波的关键 theta_7 = 7 * theta_e; [i5d_raw, i5q_raw] = park_fwd(i_alpha, i_beta, theta_5); % 5 次变直流 [i7d_raw, i7q_raw] = park_fwd(i_alpha, i_beta, theta_7); % 7 次变直流 % 低通滤波取直流分量,截止频率取基波的 1/5 左右即可 fc_lpf = 10; % Hz wn_lpf = 2*pi*fc_lpf; [b_lpf, a_lpf] = butter(2, wn_lpf/(1/(2*Ts)), 'low'); i5d = filter(b_lpf, a_lpf, i5d_raw); i5q = filter(b_lpf, a_lpf, i5q_raw); i7d = filter(b_lpf, a_lpf, i7d_raw); i7q = filter(b_lpf, a_lpf, i7q_raw);三个函数各管一段:park_fwd负责把 αβ 静止量搬到指定转速的旋转坐标系;park_inv负责把补偿指令搬回 αβ 相加;中间那段才是谐波分离本体。
参数上有几个点值得说明。theta_5前的负号不是风格问题,是负序决定的,改成正号后 5 次谐波会被推到 -10ω,低通滤波后的直流量接近零,表现为"检测不到5次谐波",很多人到这里就开始怀疑 FFT 模块坏了。fc_lpf取 10Hz 是个折中:再低响应慢,转速变化时跟不上;再高则直流分量里混入基波残余,补偿信号带着基波成分注入,等于给电流环加了一个低频扰动。低通阶数用二阶 Butterworth,相位滞后约在 20° 量级,这个滞后必须在补偿通道里补回来,否则就是第5章要讲的翻车场景。
注意:用
filter做在线滤波时初始状态为零,前几个基波周期内i5d/i5q会有一个衰减的暂态,仿真前 0.1s 的频谱不要拿来下结论。
2.3 实时FFT与带通滤波:两条检测路线的取舍
检测5次、7次谐波有两条常见路线,选哪条取决于你后面是离线分析还是在线补偿。
第一条是整周期 FFT。把相电流按基波周期整数倍截断,一次 FFT 拿到全部次数的幅值和相位,谱线干净、误差小,适合仿真跑完之后做效果评估。它的短板是延迟:窗口取10个基波周期就是 0.2s,转速一变,检测结果滞后于实际工况。
第二条是带通/复滤波提取。在同步坐标系下把 dq 打包成复信号,用中心频率对应 6 倍基频的带通滤出谐波,或者直接用 2.2 节的旋转坐标系加低通。延迟小、可在线跑,但滤波器阶数和带宽需要权衡,带宽给宽了会把邻近次数的谐波一起抓进来。
我一般两条都放:FFT 只做验证,补偿通道用旋转坐标系那条。FFT 的窗口配置按整周期来,而不是凑 2 的幂:
fs = 1/Ts; % 采样频率 f0 = pmsm.fn; % 基波 50Hz n_period = 10; % 取 10 个基波周期 spp = round(fs/f0); % 每周期采样点数,1e5/50 = 2000 N = n_period * spp; % 20000 点,严格整周期,不做补零 seg = ia(end-N+1:end); % 取最后 N 点,ia 为 A 相电流 w = hann(N); % 加窗抑制泄漏 Y = fft(seg .* w) / N * 2; % 幅值归一化 f = (0:N-1) * fs / N; idx5 = round(5*f0*N/fs) + 1; idx7 = round(7*f0*N/fs) + 1; A5 = abs(Y(idx5)); ph5 = angle(Y(idx5)); A7 = abs(Y(idx7)); ph7 = angle(Y(idx7)); fprintf('5次: %.3f A, %.1f deg\n', A5, rad2deg(ph5)); fprintf('7次: %.3f A, %.1f deg\n', A7, rad2deg(ph7));n_period决定频率分辨率,10 个周期对应 5Hz 一格,250Hz 和 350Hz 都正好落在格点上。spp用round而不是整除,因为fs/f0未必是整数,取整后窗口长度略微偏离整周期,泄漏会有一点但不致命;真正致命的是按 1024 的整数倍去凑窗口长度,那样窗口和基波周期对不上,幅值读数会在几个百分点范围里抖。hann窗是为了压住首尾不连续带来的旁瓣,代价是幅值要按窗函数相干增益修正,这里用*2的粗略归一化对比较前后已经够用。
带通那条路线的写法如下,注意用复信号一次处理 d、q 两路:
% 复信号带通:中心频率 6*f0,带宽 ±0.5*f0 fc_band = 6 * f0; % 300Hz,对应 dq 下的 5/7 次谐波 bw_band = f0; % 带宽 50Hz,留出转速波动余量 [b_bp, a_bp] = butter(2, ... [(fc_band-bw_band/2) (fc_band+bw_band/2)]/(fs/2), 'bandpass'); i_dq = id + 1j*iq; % 复信号,一次滤两路 i_dq_h = filter(b_bp, a_bp, i_dq); i5_est = abs(i_dq_h); % 幅值估计,相位由 angle 取fc_band之所以取 6 倍基频,是因为在同步旋转坐标系里,5次和7次都表现为 6 倍频的交流量,这一点和 2.2 节的旋转坐标系法殊途同归。bw_band给 50Hz 是为了覆盖转速 ±8% 左右的波动,如果台架转速很稳可以收到 20Hz,噪声更小;如果做的是宽调速场景,带宽还得再放宽,但放宽之后 5 次和 7 次在频域上开始重叠,分离精度下降,这时候就该回到旋转坐标系法。
3. 反向注入通道:信号生成、PR控制器与相位对齐
检测只是拿到"敌人"的位置,真正决定抑制效果的是注入通道。这一章的三件事按依赖顺序排:先把检测到的直流量变成反向指令,再用谐振控制器把指令跟踪准,最后处理两个通道之间的耦合和电压限幅。
3.1 从检测幅值到反向注入波形:符号与角度都要对
最直观的做法是幅值相位法:从 2.2 节拿到i5d/i5q,算出幅值和相位,构造一个相位加 180° 的正弦,频率取 5 倍基频,注入到电流环的给定端。原文给的就是这条路,思路没问题,但有两个细节要在实现时补上。
第一,注入信号的相位基准必须和检测时用的角度基准一致。检测用的是电角度theta_e,注入也必须用它,中间不要引入额外的积分或延时环节,否则相位对不上。第二,幅值不要一次给满,加一个 0 到 1 的渐入系数,仿真里能避免起始瞬间的冲击,实机上也能防止补偿通道突然投入造成的电流跳变。
更工程化的做法是直接在各自的旋转坐标系里做闭环调节,把i5d/i5q调到零,再把调节器输出反变换回 αβ 相加。这样相位问题被吸收进闭环里,鲁棒性更好:
function [ua_c, ub_c] = harmonic_inject(i5d, i5q, i7d, i7q, theta_e, Kp, Ki, Ts) % 在 5 次、7 次旋转坐标系内做 PI 调节,输出补偿电压(alpha/beta) persistent x5d x5q x7d x7q if isempty(x5d) x5d = 0; x5q = 0; x7d = 0; x7q = 0; end % 5 次通道:给定为 0,误差即检测值 e5d = -i5d; e5q = -i5q; x5d = x5d + Ki*e5d*Ts; x5q = x5q + Ki*e5q*Ts; u5d = Kp*e5d + x5d; u5q = Kp*e5q + x5q; % 7 次通道 e7d = -i7d; e7q = -i7q; x7d = x7d + Ki*e7d*Ts; x7q = x7q + Ki*e7q*Ts; u7d = Kp*e7d + x7d; u7q = Kp*e7q + x7q; % 反变换:5 次用 -5θe,7 次用 +7θe,与检测保持一致 [ua5, ub5] = park_inv(u5d, u5q, -5*theta_e); [ua7, ub7] = park_inv(u7d, u7q, 7*theta_e); ua_c = ua5 + ua7; ub_c = ub5 + ub7; endKp和Ki的量纲是 V/A 和 V/(A·s),整定时先只看一个通道:把 7 次通道断开,单独调 5 次,Kp从 0.05 开始加,观察i5d/i5q是否单调收敛;Ki取Kp的 1/50 到 1/20,负责消除静差。两个通道的Kp通常接近,因为 dq 轴电感相同;如果电机凸极明显,7 次通道的增益要相应放大。
park_inv的角度符号必须和park_fwd严格配对,5 次用-5*theta_e,7 次用+7*theta_e。这一对符号写反了,补偿量会以 10 倍频和 14 倍频的形式注入,频谱图上5次、7次不降反升,看起来像是"补偿算法没用",其实是符号错。
3.2 PR控制器:带宽、增益与离散化
PI 在旋转坐标系里能消掉直流误差,但如果你的检测是在 αβ 下完成的,用 PR(比例谐振)控制器更直接:它在谐振频率处提供近似无穷大的增益,对 250Hz 和 350Hz 各自设一个谐振点,不需要坐标变换。
理论谐振器的传递函数是Kr*s/(s^2 + w0^2),极点落在虚轴上,实际实现要加阻尼做成准 PR:
function [b, a] = pr_discrete(Kp, Kr, w0, wc, Ts) % 准 PR 控制器离散化(Tustin),w0 谐振角频率,wc 截止带宽 s = tf('s'); G = Kp + Kr * 2*wc*s / (s^2 + 2*wc*s + w0^2); Gd = c2d(G, Ts, 'tustin'); [b, a] = tfdata(Gd, 'v'); end % 5 次 250Hz、7 次 350Hz,带宽 10 rad/s,阻尼取 0.707 对应的 wc w0_5 = 2*pi*250; w0_7 = 2*pi*350; wc = 10; % rad/s,决定谐振峰的宽度 [b5, a5] = pr_discrete(0.8, 60, w0_5, wc, Ts); [b7, a7] = pr_discrete(0.8, 60, w0_7, wc, Ts); u5 = filter(b5, a5, e5); % e5 为 5 次谐波误差 u7 = filter(b7, a7, e7);Kp决定整体带宽和暂态响应,取 0.5 到 1.5 之间;Kr决定谐振点的增益深度,取 40 到 100,太小压不干净,太大则在谐振点附近相位急剧变化,容易和电流环的其他滞后叠加成不稳定。wc是最关键的一个参数:它把理想谐振器的无限增益"削平",形成一个有宽度的峰。取 10 rad/s 意味着谐振峰在 250Hz 附近大约有 ±1.6Hz 的有效带宽,能容忍转速 1% 左右的波动;如果台架转速波动大,wc要加到 20 到 30,代价是谐振点增益下降,残余谐波会多一点。
离散化用 Tustin,Ts必须和仿真步长一致。这里有个常见的翻车点:控制器用1e-4离散、模型步长却是1e-5,两者不匹配,谐振频率会偏几个 Hz,补偿效果打折。我一般把Ts直接从inv.Ts取,避免手写两处。
提示:
c2d生成的是离散传递函数,直接放进 Simulink 的 Discrete Filter 模块即可,系数用tfdata导出成数组,别在模块里现算,仿真速度会差一个数量级。
3.3 双通道耦合与电压限幅
把 5 次和 7 次两个通道同时打开,问题就来了:两个谐振控制器都在同一条电流环上工作,输出相加后进入同一个 PWM 环节,一个通道的调节会通过电流反馈影响另一个通道的检测值,形成耦合。表现是单独调好 5 次之后,再把 7 次打开,5 次的残余量又冒出来,来回调几次都不收敛。
常见的处理是在每个通道的输入前加一级带阻,把对方通道的频率挡掉,形成"隔离舱"。带阻用二阶 IIR 就够:
function [b, a] = notch_iir(f0, bw, fs) % 二阶陷波器,f0 中心频率,bw 陷波带宽 w0 = 2*pi*f0/fs; alpha = sin(w0) * sinh(log(2)/2 * bw * w0/sin(w0)); b = [1, -2*cos(w0), 1] / (1 + alpha); a = [1, -2*cos(w0)/(1+alpha), (1-alpha)/(1+alpha)]; end % 5 次通道前挡掉 350Hz,7 次通道前挡掉 250Hz [b_n7, a_n7] = notch_iir(350, 30, fs); [b_n5, a_n5] = notch_iir(250, 30, fs);bw取 30Hz 是折中:窄了挡不住转速波动导致的频率漂移,宽了会把有用信号也削掉一部分。陷波器本身有相位滞后,放在检测之后、调节之前,滞后的影响会被后面的闭环吸收掉一部分,但如果放在补偿输出之后,就会直接吃掉相位裕度。
限幅是另一条必须有的保护。补偿电压叠加到电流环输出上,遇到突加载或转速阶跃时,两个通道同时往一个方向推,很容易把调制比顶到饱和,轻则波形削顶,重则仿真报积分饱和错误。我一般做两级:先对每个通道单独限幅,再对合成后的 αβ 指令做一次幅值限幅。
Vmax_ch = 0.15 * inv.Vdc / sqrt(3); % 单通道限幅,取母线电压的 15% ua_c = max(min(ua_c, Vmax_ch), -Vmax_ch); ub_c = max(min(ub_c, Vmax_ch), -Vmax_ch); Vmax_sum = 0.25 * inv.Vdc / sqrt(3); % 合成后限幅 mag = hypot(ua_c, ub_c); if mag > Vmax_sum ua_c = ua_c * Vmax_sum / mag; ub_c = ub_c * Vmax_sum / mag; endVmax_ch取 15% 母线电压,对应 3kW 台架上大约 40V 的补偿能力,足够压掉十几安的谐波;Vmax_sum取 25%,给基波留出余量。幅值限幅用等比缩放而不是分别截断,后者会改变合成矢量的方向,等于往系统里注入了额外的相位误差。
4. 仿真跑通后的三条验收线:频谱、THD、转矩脉动
模型跑起来只是第一步,能不能说"补偿有效"要看三条线:频谱上5次、7次的幅值下探多少,THD 降到什么水平,转矩脉动的峰峰值有没有跟着降。三条线要一起看,只看一条很容易被误导。
4.1 示波器触发与数据导出
仿真里的 Scope 默认自由触发,波形一直在滚,截图根本对不齐。我的习惯是把触发方式改成上升沿,触发源选 A 相电流过零点,这样每次暂停都在同一个相位上,前后对比才有意义。
数据不要靠截图,导出到工作区。Simulink 里给信号加To Workspace或直接用logsout,采样时间按Ts记:
% 仿真结束后从 logsout 取数据 sig_ia = logsout.get('i_a').Values; ia = sig_ia.Data; t = sig_ia.Time; Ts = mean(diff(t)); fs = 1/Ts; % 稳态段截取:跳过前 0.2s 的起动暂态 t_start = 0.3; idx = t >= t_start; ia_ss = ia(idx);t_start是经验值,一般取 5 到 10 个基波周期,看电流包络稳定了再截。截早了会把起动过程的直流分量带进 FFT,低频段出现一个大鼓包,把 250Hz 附近的读数抬上去。导出时把补偿前后的两组数据分别存成ia_before和ia_after,后面画对比图直接调。
4.2 频谱对比:20dB下探怎么读
补偿效果的判据,我一般看两个数:5次和7次的单次幅值相对基波下降多少 dB,以及总 THD。原文给的"至少下降 20dB"是个合理的工程目标,对应幅值降到原来的十分之一。
function [THD, A] = spec_analysis(ia, fs, f0, n_period) % 整周期截断 + 汉宁窗 + 单边幅值谱 spp = round(fs/f0); N = n_period * spp; seg = ia(end-N+1:end); w = hann(N); Y = fft(seg .* w) / N * 2; f = (0:N-1) * fs / N; % 只取前半段 half = 1:floor(N/2); f = f(f2); Y = Y(half); A.fund = abs(Y(round(f0*N/fs)+1)); harm_order = 2:13; for k = harm_order idx = round(k*f0*N/fs) + 1; A.h(k) = abs(Y(idx)) / A.fund * 100; % 相对基波的百分比 end THD = sqrt(sum(A.h.^2)); endn_period取 10 对应 5Hz 分辨率,250Hz 和 350Hz 都能落在格点上;harm_order取 2 到 13 次,覆盖了主要低次谐波,THD 按相对基波的百分比算。
读图时注意一点:20dB 的下探是按幅值算的,如果基波本身在补偿前后有变化(比如补偿电压占用了调制余量,基波幅值略微下降),单看谐波绝对值会高估效果,必须用相对基波的百分比。补偿前 5 次约 7%、7 次约 4%,补偿后压到 0.5% 以下,THD 从 8% 出头降到 2% 以内,这在 3kW 台架上算合格。同一组数据里如果 7 次降得比 5 次少,多半是 7 次通道的增益不够或者相位补过头,回头调 3.2 节的Kr。
4.3 突加载与限幅回归测试
稳态频谱好看不代表模型能用。补偿通道在突加载时的行为才是实机上最容易出事的地方:负载阶跃瞬间,转速跌落,谐波频率跟着偏,检测环节的滤波器和 PR 控制器的谐振点都跟不上,补偿量可能短暂反向。
测试方法很简单:在 0.5s 时把负载转矩从 0 阶跃到额定的 60%,观察三相电流和补偿电压指令。要看三个东西:电流有没有明显畸变、补偿指令有没有顶到限幅、转速恢复过程中 THD 有没有出现尖峰。
% 阶跃工况下的 THD 滑动窗口统计 win = 10 * round(fs/f0); % 10 个基波周期一个窗口 step = win / 4; % 四分之一窗口滑动 n_win = floor((length(ia) - win) / step); thd_t = zeros(n_win, 1); for k = 1:n_win seg = ia((k-1)*step+1 : (k-1)*step+win); [thd_t(k), ~] = spec_analysis(seg, fs, f0, 10); endstep取四分之一窗口是为了让 THD 曲线有时间分辨率,又不至于窗口太短导致频谱糊掉。正常的曲线是稳态平坦、阶跃瞬间有一个不超过 2 个百分点的尖峰然后回落;如果尖峰持续超过 0.2s,说明补偿通道的带宽不够,把wc从 10 加到 20 再试。
限幅的检查直接看补偿指令的峰值,如果长时间贴在Vmax_ch上,说明补偿量给大了,回头降Kr。这一步别省,仿真里顶到限幅只是波形难看,实机上就是过调制。
5. 避坑与排查:相位、窗口、耦合这些翻车现场
这一章的五条都是我在台架和仿真之间来回对数据时真实踩过的,按出现频率从高到低排。每条按现象、原因、解决三段写,照着对号入座基本能定位。
5.1 补偿后谐波不降反升:相位反了
现象:打开补偿通道,5次谐波幅值从 7% 涨到 14%,波形比补偿前还难看。
原因:注入信号的相位与原始谐波同相而不是反相。最常见的两种写法错误,一是 5 次谐波用了+5*theta_e做反变换,二是幅值相位法里+pi加在了错误的基准上。相位差 180° 是抵消,差 0° 就是叠加,差 90° 则是把谐波搬到了正交轴上。
解决:先断开闭环,只开检测,把i5d/i5q和 FFT 算出的幅值相位对一遍,确认旋转方向对;再单独注入一个固定幅值的小信号,用示波器看注入波形和原始谐波是不是反相。这一步用 XY 模式看李萨如图最直观,两个信号反相时图形是一条斜率为负的直线。确认之后再合上闭环,从 0.1 的增益慢慢加。
5.2 频谱幅值来回跳:FFT窗口不整周期
现象:同一段稳态数据,连续做几次 FFT,5次谐波的读数在 6.2% 到 7.5% 之间跳,换一个窗口长度又是另一个值。
原因:窗口长度不是基波周期的整数倍,频谱泄漏让能量从 250Hz 摊到邻近的格点上,读数随窗口相位变化。另一个隐蔽原因是采样率和基频不成整数比,fs/f0带小数,取整之后每个周期的采样点数在 1999 和 2000 之间摆动。
解决:窗口长度取n_period * round(fs/f0),n_period取 10 或 20,不要为了凑 1024 的整数倍去改窗口。采样率尽量选成基频的整数倍,比如fs = 100kHz、f0 = 50Hz,spp = 2000正好整除。如果仿真步长不能改,就在 FFT 前做一次重采样,把非均匀点补成均匀的整周期序列。
5.3 两个通道互相干扰:调好一个另一个又冒出来
现象:单独开 5 次通道,残余压到 0.5%;再开 7 次通道,5 次又回到 2%,来回调几次都不收敛。
原因:两个谐振控制器共享同一条电流环,一个通道的输出会通过反馈改变另一个通道看到的误差,形成正反馈式的耦合。带宽给得越宽,耦合越明显。
解决:按 3.3 节在每个通道输入前加陷波,把对方频率挡掉;同时把两个通道的wc稍微收窄,牺牲一点跟踪速度换解耦。如果还是不行,改成主从结构:先让 5 次通道收敛并锁定,再投入 7 次通道,投入时把 5 次通道的积分器冻结,避免被带动。
5.4 突加载时仿真报错或波形削顶:限幅缺失
现象:负载阶跃瞬间,相电流出现平顶,补偿电压指令冲到母线电压附近,仿真报积分饱和或者直接发散。
原因:补偿通道没有限幅,或者限幅值给得过大。两个通道同时往一个方向推,合成矢量超过调制能力,PWM 进入过调制。
解决:按 3.3 节做两级限幅,单通道 15% 母线电压、合成 25%,用等比缩放而不是分别截断。同时给 PI 加抗饱和:积分器输出超过限幅值时停止积分,这一条在离散实现里加一个if判断就够,别指望 Simulink 的饱和模块自动处理。
5.5 转速一变补偿就失效:谐波跑出检测带宽
现象:额定转速下补偿效果很好,转速降到 60% 或者升到 110%,5次、7次的残余量明显变大,频谱上谐波峰的位置也跟着偏。
原因:谐波频率正比于转速,检测用的带通滤波器中心频率和 PR 控制器的谐振点都是按 50Hz 基频固定设的,转速一变,谐波就跑到通带边缘甚至外面。
解决:把基波频率做成随转速实时更新的变量,带通中心频率和 PR 谐振角频率都跟着改。Simulink 里用MATLAB Function模块从转速算w_e,直接喂给滤波器系数和pr_discrete。更省事的做法是加转速前馈,把w_e提前半个控制周期送进去,抵消滤波器的相位滞后,这个放到第6章讲。
6. 进阶:转速前馈与参数固化,把模型做成可复用模板
模型调通之后最有价值的一步是把它变成模板,换一台电机只改参数表,不碰结构。这里有两个具体技巧。
第一个是转速前馈补偿相位。检测通道的低通滤波器和带通滤波器都会引入相位滞后,转速越高,同样的时间延迟对应的电角度越大,补偿信号就越对不准。做法是把基波电角频率提前送进补偿通道,按Δθ = w_e * T_delay算出一个超前角,加在反变换的角度上。T_delay取检测链路的总延迟,用阶跃响应实测:给一个谐波突变,看检测输出的响应延迟多少毫秒,这个值减掉一半就是补偿量。我在 3kW 台架上实测总延迟约 0.6ms,250Hz 下对应 54° 电角度,补进去之后高速段的残余量又降了三分之一。
第二个是参数固化成脚本加结构体。把电机参数、控制器参数、限幅值全部收进一个struct,模型里只引用字段,不写裸数字。配合一个批量扫描脚本,可以自动跑不同转速、不同负载的组合,把 THD 结果存成表,哪组工况下超标一目了然:
% 批量工况扫描:转速 x 负载,输出 THD 表 speed_list = [1500 2400 3000]; load_list = [0 0.3 0.6 1.0]; res = zeros(numel(speed_list), numel(load_list)); for i = 1:numel(speed_list) for j = 1:numel(load_list) set_param('pmsm_harmonic/SpeedRef', 'Value', num2str(speed_list(i))); set_param('pmsm_harmonic/TorqueLoad', 'Value', num2str(load_list(j))); out = sim('pmsm_harmonic'); ia = out.logsout.get('i_a').Values.Data; [thd, ~] = spec_analysis(ia, fs, f0, 10); res(i, j) = thd; end end % 输出成表,行是转速、列是负载 T = array2table(res, 'RowNames', string(speed_list), ... 'VariableNames', "L" + string(load_list)); disp(T);set_param直接改模块参数,sim每次跑完取logsout,spec_analysis复用第4章的函数。这样一轮跑下来十几分钟,比手动改参数点运行靠谱得多,也避免了"这组工况好像调过又好像没调过"的记忆混乱。
从那以后我每次改完补偿通道,都会先把注入信号和原始谐波在 XY 模式下对一次相位,再跑一遍阶跃工况的滑动 THD,两关都过了才敢把参数写进模板。谐波抑制这件事,稳态频谱好看只是入场券,动态过程不炸才是真正的交付标准。希望帮到你。
本文还有配套的精品资源,点击获取