
简介面向电力电子与控制系统仿真人员资源提供在MATLAB中调用PLECS进行模型扫频分析并绘制结果图的完整示例包。内容涵盖PLECS模型建立、MATLAB接口调用、频率扫描参数设置以及Bode/Nyquist图绘制等关键环节适合具备MATLAB基础、希望提升PLECS与MATLAB联合仿真效率的初学者及研究人员。压缩包共4个文件包含1个plecs模型和3个m脚本整体仅7KB体量小巧但功能链条完整便于直接运行与二次修改。已有1542人学习/下载脚本围绕扫频分析主流程组织结合资源描述中的安装配置与函数使用说明可帮助读者快速掌握plecsLoadModel、plecsRunSweep等接口的基本用法进而实现系统频域特性的自动化分析与可视化为后续更复杂的电力电子仿真研究打下基础。 搞电源仿真的人迟早会碰到这个时刻PLECS里时域波形跑得流光水滑可真到了设计补偿器、判断相位裕度的时候波形根本帮不上忙。你需要的是整个系统在不同频率下的响应曲线——也就是Bode图。这时候就绕不开“在MATLAB里调用PLECS对其中模型扫频对结果画图”这套流程。这篇文章就按我实际跑通的经验来写适合做电力电子、电机控制、开关电源需要定量做环路设计、滤波器特性分析或者模型校核的工程师和研究生。我会把路径选型、模型搭建、脚本怎么写、图怎么画以及哪些坑不能踩都完整过一遍。1. 扫频之前先搞清楚你扫的是哪种“频”1.1 频响扫描解决的问题从时域波形到稳定性判断时域仿真能告诉你的只有“系统在这个激励下是怎么响的”但它很难直接告诉你“系统离不稳定还有多远”。频域扫频则不同它把一个系统的增益和相位沿频率轴展开几个关键指标一目了然0 dB穿越频率、相位裕度、幅值裕度、谐振峰位置。我用PLECS搭过一个LLC谐振变换器的开环模型时域看驱动波形、输出波形都没问题可一旦闭环PI参数稍微加猛就振荡。当时就是缺一张控制对象到输出的频响曲线不知道穿越频率落在哪、相位余量有多少。后来在MATLAB里对PLECS模型做扫频直接画出开环增益的Bode图问题就清楚了60 kHz附近对象增益的相位滞后已经接近-160°补偿器如果还在那里堆增益肯定稳不住。扫频在工程里的价值就三个给补偿器设计提供依据零点极点放在哪里是看相频曲线决定的不是拍脑袋做环路稳定性评估穿越频率和相位裕度是衡量电源动态品质的硬指标做模型校核把仿真扫频结果和实测网络分析仪扫出来的数据对比能验证仿真模型是否可信。这些都是时域波形替代不了的。1.2 三种实现路径的取舍要不要全走MATLAB脚本在动手前先梳理一下“MATLAB调用PLECS做扫频”可以走的三条路因为不同路线的工具链需求和适用场景差别很大。路径APLECS自带的AC Sweep功能。在PLECS电路窗口里直接配置起始频率、终止频率、扫描点数和每点周期数自动出Bode图。最省事适合快速看一眼系统特性。缺点是和MATLAB的数据互通要导出再导入做批量参数扫描时很别扭。路径BPLECS Blockset嵌入Simulink用Simulink Control Design工具箱的Linear Analysis工具直接在模型上做线性化。优点是可以拿到状态空间对象后面各种分析都很方便。缺点是对开关电路模型的线性化处理有时不太直观而且不少人的MATLAB安装并没有包含这个工具箱。路径CMATLAB脚本驱动PLECS模型自己做逐点扫频。思路是对模型输入施加某个频率的正弦扰动等稳态后测输出幅值和相位再换下一个频率把所有频率点拼成频响曲线。优点是完全透明、可控、可批量辅以代码就能跑几百个工况数据全部留在MATLAB工作区里画图、分析、导出一体化。缺点是代码要自己写仿真时间也会长一些。我最后推荐路径C原因很实际最接近“在MATLAB里调用PLECS”这个操作习惯而且数据链路最短中间不会有任何软件界面截断。本文主体就是按路径C讲的路径A我会在最后一节拿来当对照参考。2. 环境准备与一个够用的测试模型2.1 版本、许可证和容易被忽略的环境问题你至少需要一套能正常协同工作的MATLAB/Simulink和PLECS Blockset。这里有一个很多人栽过跟头的点PLECS版本和MATLAB版本存在兼容矩阵不是每个PLECS版本都能配每个MATLAB版本。装完之后别急着搭模型先在MATLAB命令行里执行一下PLECS自带的接口命令确认PLECS模块库能被Simulink正确加载同时确认许可证状态正常。我见过的情况是许可证在PLECS独立版里一切正常但换到MATLAB的PLECS Blockset里却找不到模块最后发现是环境变量和许可证服务没指到同一处。还要注意如果你打算用parfor并行加速扫频每个MATLAB worker进程都要能独立拿到PLECS许可证。一些浮动许可证对并行worker的支持是有限制的不是所有worker都能同时启动仿真。实测下来单机多核并行时正常但跨多台机器调度时容易卡在许可证这里。所以第一次跑通扫频流程建议先用串行循环确认数据和模型都没问题再谈加速。2.2 测试模型怎么搭给扫频留一个“口子”想要扫得准模型在搭建阶段就得留好扫频接口。第一步在Simulink模型里放一个PLECS Circuit模块双击进去搭被扫的电路。第二步把需要扫频的正弦激励信号从Simulink侧引进去方式是通过PLECS Circuit模块的输入端口接一个可控电压源或可控电流源。第三步把你要观测的电压或电流通过PLECS里的电压表/电流表测量模块引出到Simulink侧接一个To Workspace模块扫频时才拿得到数据。这里有一个核心设计思想不要把你关心的被测系统包装成一个黑盒要明确定义“输入在哪、输出在哪”。如果目标是测某个电源的环路增益那输入点就不能选在主功率线上而要选在环路内部——常见做法是在反馈分压网络和误差放大器之间插入一个注入点扰动信号从那里进去。这样扫出来的才是环路各个模块串联起来的总环路增益而不是单纯功率级的频率特性。这个道理和实际用网络分析仪测环路一模一样。加到功率级的激励是扫不出环路相位裕度的我第一次就犯了这个错白跑了一整晚仿真。另外建议用一个最基础的二阶RLC电路当测试模型。原因很简单它的理论频响就是标准的二阶低通你能用公式直接算出每个频率点应有的增益和相位用来验证脚本算法对不对。等算法链路确认没毛病再换上你真正要研究的Buck、Boost、LLC或者电机驱动模型。3. 用MATLAB逐点扫频的完整实现3.1 频率序列和仿真时长怎么定逐点扫频频率点的选取直接影响曲线质量和计算量。常见的做法是对数均匀分布让低频和高频都有足够的密度公式是freq_list logspace(log10(f_start), log10(f_stop), N)。比如我想覆盖100 Hz到100 kHz取61个点那相邻点之间的密度已经足够画出平滑的Bode图。点数不是越多越好——100个点通常已经要跑较长时间200个点除了曲线更密对判断穿越频率和相位裕度的帮助反而边际递减。每个频率点的仿真时长是个关键判据。系统从激励开始到进入稳定状态需要一段时间这段时间不能拿来算幅值相位否则结果偏得离谱。工程上我习惯这样分配频率范围丢弃段周期数记录段周期数低频比目标穿越频率低两个十倍频5 ~ 88 ~ 12中频穿越频率附近8 ~ 1010 ~ 15高频比穿越频率高两个十倍频3 ~ 55 ~ 8也就是说总仿真时间T_total (丢弃周期数 记录周期数) / f。频率越低所需仿真时间越长所以在设定扫频下限时要有心理准备。从10 Hz开始扫每点跑15个周期单点就要1.5秒仿真时间61个点累计就接近两分钟这还不算高精度小步长带来的计算量。所以不要拍脑袋把起始频率设到1 Hz先确认你对哪个频段最关心再决定扫频范围。仿真求解器建议设成固定步长步长上限取最高扫频频率对应周期的1/50到1/100。比如最高扫到100 kHz周期10 μs步长就设0.1~0.2 μs。低频点用同样的小步长会增加总步数但能保证每个频率点之间的数值误差水平一致不会出现高频点和低频点精度差几个数量级的情况。3.2 幅值和相位的提取为什么不用FFT扫完一个频率点的仿真后手里是一段时间序列的输出波形和一个已知频率的正弦输入。怎么从波形里还原幅值和相位很多人的第一反应是FFT。但对逐点扫频来说FFT并不是最合适的手段FFT的频率分辨率受采样时长限制记录时间如果不是信号周期的整数倍还会出现频谱泄漏得加窗、补零操作繁琐还不直观。我推荐用最小二乘正弦拟合法原理很直接。假设测试信号可以表达为s(t) A1*sin(ωt) A2*cos(ωt) C D*t其中ω是扫频角频率C是直流偏置D*t是缓慢漂移项。A1和A2是待求系数用MATLAB的解线性最小二乘问题方式一行就解出来了。求出A1、A2后幅值 sqrt(A1² A2²)相位 atan2(A2, A1)用输入信号的相位减去输出信号的相位就是该频率点的相移。这个方法好处很明显即使记录长度不是周期的整数倍只要有足够的波形覆盖拟合结果依然稳定而且它对信号中的噪声、直流偏置和慢漂移天然免疫非常合适从仿真数据里提取特定频率的分量。这里再多说一句回归抗干扰的进阶处理如果被测系统是开关变换器输出波形里会混入开关频率及其倍频的纹波直接按基频做拟合高次分量会被最小二乘当作误差平均掉结果基本不受影响。如果你发现基波拟合残差特别大还可以把设计矩阵里加上sin(2ωt)、cos(2ωt)等项把谐波成分一并纳入拟合这样得到的基波幅相会更干净。核心拟合函数可以直接写成function [amp, phase] fit_sine(t, y, f) w 2 * pi * f; A [sin(w*t), cos(w*t), ones(size(t)), t]; theta A \ y; amp sqrt(theta(1)^2 theta(2)^2); phase atan2(theta(2), theta(1)); end3.3 主循环脚本简约但能直接改着用下面的脚本是我实际用过的骨架去掉了和具体模型相关的部分保留了完整的扫频逻辑。它做的事就是生成频率序列 → 每个频率点生成正弦输入数据 → 调用sim运行模型 → 拟合输入输出 → 保存复增益 → 下一频率点。% 扫频参数 f_start 10; f_stop 1e5; N 61; freq_list logspace(log10(f_start), log10(f_stop), N); Amp_in 0.01; % 输入扰动的幅值 drop_cycles 5; % 丢弃段周期数 record_cycles 10; % 记录段周期数 fs_max 1e5; % 最高扫频频率 Ts_sim 1 / (50 * fs_max); % 固定仿真步长 H zeros(1, N); % 存每个频点的复数增益 for k 1:N fk freq_list(k); T_total (drop_cycles record_cycles) / fk; t_sim 0 : Ts_sim : T_total; % 生成正弦输入交给模型里的 From Workspace 模块 input_data [t_sim, Amp_in * sin(2*pi*fk*t_sim)]; assignin(base, SweepInput, input_data); % 运行仿真StopTime用字符串指定 simOut sim(plecs_sweep_model, StopTime, num2str(T_total), ... ReturnWorkspaceOutputs, on); % 从 To Workspace 拿输出数据 t_out simOut.tout(:); y_out simOut.yout{1}.Values.Data(:); % 只取记录段数据丢弃前 drop_cycles 个周期 t_drop drop_cycles / fk; idx find(t_out t_drop); t_rec t_out(idx); y_rec y_out(idx); % 拟合输入输出注意这里输入是理想正弦直接算相位即可 [amp_out, phi_out] fit_sine(t_rec, y_rec, fk); phi_in 0; % 如果输入定义为 sin(wt)初始相位就是0 dphi phi_out - phi_in; % 保存复增益幅值/输入幅值就是增益相位差就是相移 H(k) (amp_out / Amp_in) * exp(1i * dphi); end这段脚本有几个细节值得注意。第一个是assignin(base, SweepInput, input_data)它把每个频率点的正弦序列写到MATLAB基础工作区模型里的From Workspace模块会自动认到这个名字。好处是比用sine wave配合set_param改频率更稳定你想改扰动幅值、加谐波干扰都很容易。第二个是索引idx find(t_out t_drop)这行确保了送入拟合函数的数据是稳态段而不是包含启动过程的全段数据。第三点是输入信号我把初始相位定为0实际如果有相位偏移你也应该对输入数据用同样的fit_sine函数算一次初始相位再和输出相位做差这样最严谨。跑完这个循环后H数组就是这个模型在设定频率范围内的复数频率响应。接下来要做的就是把它画出来以及决定怎么处理那些看起来“不对劲”的点。4. 结果画图从裸数据到能放进论文的Bode图4.1 把复数频响整理成可画图的数据扫频结束以后手里是一串复数增益H(k)和对应频率freq_list(k)。首先要明确几个单位换算关系幅值转dB用20*log10(abs(H))相位转角度用angle(H)*180/pi并做unwrap处理频率横轴用对数坐标。如果装了Control System Toolbox最省事的方式是构造一个frd对象再交给bodeplotH_frd frd(H, freq_list, Units, Hz); opt bodeoptions; opt.FreqUnits Hz; opt.MagUnits db; opt.MagScale log; opt.Grid on; bodeplot(H_frd, opt);但我更推荐你也掌握手动画图的方法因为它让你对数据有完全的控制权而且不依赖特定工具箱。4.2 手动版Bode图绘制的完整示例手工绘制Bode图的完整代码骨架如下figure(Color, w); subplot(2, 1, 1); semilogx(freq_list, 20*log10(abs(H)), o-, LineWidth, 1.2); grid on; xlabel(Frequency (Hz)); ylabel(Magnitude (dB)); title(Frequency Response of PLECS Model); subplot(2, 1, 2); semilogx(freq_list, unwrap(angle(H)) * 180/pi, o-, LineWidth, 1.2); grid on; xlabel(Frequency (Hz)); ylabel(Phase (deg));如果你有理论传递函数作为对照可以像下面这样叠加上去f_th logspace(log10(f_start), log10(f_stop), 200); H_th 1 ./ (1 1i*2*pi*f_th*R*C); % 一阶RC低通的例子 hold on; semilogx(f_th, 20*log10(abs(H_th)), r--, LineWidth, 1.2); legend(PLECS sweep, Theory);这里我特别提醒一个高频坑MATLAB的angle函数返回的相位范围是-180°到180°直接画会发现曲线在-180°处跳变到180°看起来像毛刺。解决办法就是unwrap它本质上是在相邻点之间检测跳变幅度把超过180°跳变的点自动补上2π的整数倍。用unwrap(angle(H)) * 180/pi就对了。画完曲线后标注穿越频率和相位裕度是很多人需要的功能。穿越频率就是幅频曲线穿过0 dB时对应的频率点可以手动从曲线读也可以用代码自动找mag_db 20 * log10(abs(H)); fc interp1(mag_db, freq_list, 0, pchip); % 找0dB穿越频率 disp([0 dB穿越频率: , num2str(fc), Hz]);如果穿越不止一次那就需要分段查找或者直接用[~, idx] min(abs(mag_db))取最接近0 dB的点。相位裕度就是在fc处看相频曲线距离-180°还有多少度。最后不要忘了输出图片。exportgraphics(gcf, sweep_result.png, Resolution, 300)能输出符合论文或报告要求的高清图比saveas更稳一点。4.3 数据平滑和异常点判断扫频数据不可能每个点都完美落在光滑曲线上尤其是开关电源这类带高频纹波的系统。小于0.5 dB的波动是正常的不用处理。但如果某个点明显偏离相邻点好几dB说明这个频率点大概率有问题不要急着做平滑去掩盖它先回到第5章的排查思路看是什么引起的。如果确认某些点是数值噪声可以做一个保守的移动平均window 3; mag_sm movmean(20*log10(abs(H)), window); phase_sm movmean(unwrap(angle(H))*180/pi, window);但注意相位曲线在谐振点附近变化非常快盲目移动平均会把真实的相位陡降抹平导致计算的相位裕度失真。我的建议是幅频数据可以适当平滑相频数据宁可让它“毛”着也要保留真实趋势。画图的时候用点标记加细线点密度够了以后看起来依然很干净。5. 我踩过的坑和一些经验判断5.1 扰动幅值小信号线性化的边界扫频这件事在数学上默认系统是线性的或者至少在工作点附近可以做小信号线性化。扰动幅值选大了系统进入非线性区扫出来的幅值会受大信号平均效应影响和你想要的小信号频响完全是两回事选小了数值误差和模型本身的计算噪声会把信号淹没。我通常这样定初值先把系统稳定在一个典型工作点调扰动幅值让被测输出变量的变化量占该变量稳态值的1%到5%。如果做环路增益扫频注入信号加在反馈环路里幅值一般取参考电压或输出电压的0.5%~2%。比如一个输出48 V的电源注入幅值在0.3~1 V之间比较合适。在这基础上做一次预扫看输出的时域波形有没有明显畸变如果有把幅值再降一半。这是一个非常实用的经验判据——输出波形依然保持良好的正弦形状说明扰动还没大到激发非线性。5.2 高低频段结果乱跳的排查扫完发现曲线在某个频段突然乱跳先别怀疑算法按顺序排查这四个原因第一稳态没有真正建立。低频段最容易发生因为系统会需要更长的仿真时间才能抹平启动瞬态。你把丢弃段周期数加大到10以上再试一次多数情况就平了。第二固定步长过粗。高频段要检查每周期有多少个仿真采样点如果采样点少于50个幅值误差会显著上升。解决办法是按最高频率重算步长Ts_sim 1 / (100 * fs_max)。第三开关纹波混叠。电力电子模型天然带有开关频率的纹波如果扫描频率接近开关频率的某次谐波或者记录段采样点数不是开关周期整数倍提取值就会抖动。这时候可以在拟合函数中把谐波项加进去或者把记录段周期数加多让随机误差在最小二乘里被充分平均掉。第四系统在这个频率点确实存在谐振或相位的剧烈变化。有些系统在谐振频率附近幅相曲线本身就很陡不是仿真错是物理特性如此。这时候应该细化该频段的扫频点而不是怀疑结果错了。用LLC变换器扫增益曲线时尤其明显峰值附近相邻两个频率点能差出好几dB别慌这是真实特性。5.3 和PLECS自带AC Sweep的结果对比如果你装了比较新的PLECS版本可以试试它自带的AC Sweep。这个功能会围绕稳态工作点自动施加小信号扰动频点设置、稳态判定和数据绘图都由PLECS内部完成半个小时能跑完本来要折腾一下午的扫频任务。我自己拿二阶RLC模型做过对比PLECS自带AC Sweep、SIMetrix扫频和我这段MATLAB脚本扫频三条Bode曲线几乎重合低频到谐振点附近偏差小于0.2 dB、1°以内。如果你两组数据对不上最可能的原因是两个一个是我前面说的扰动幅值不对PLECS的AC Sweep默认使用很小的小信号扰动你手动脚本给了一倍额定值结果自然不同另一个是注入点选的不同不同注入点测到的环路增益不一样。想验证脚本就用同一个RC一阶电路跑一遍理论传递函数是确定的H(s) 1 / (1 sRC)幅值、相位闭着眼都能算出来。用这个当标尺脚本有没有问题一眼就能看出来。最后分享一个小的工程习惯我每次正式扫频前都会额外设两个“已知点”做验收——一个选在远离所有极点零点的平坦增益区一个选在某个明确的转折频率附近。如果这两个点的仿真结果与理论判断一致才会相信整条扫频曲线否则就先解决模型和脚本的问题。这个习惯帮我挡掉过不少把错误数据当宝贝写进报告的情况。扫频只是一个工具真正值钱的是你能不能判断结果是否合理。本文还有配套的精品资源点击获取