ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于MATLAB/Simulink的光伏电池建模与仿真完整指南

基于MATLAB/Simulink的光伏电池建模与仿真完整指南 后台经常有人问我光伏电池模型怎么做正好我最近整理了一套自己一直在用的 MATLAB/Simulink 光伏电池模型带说明文档还有配套的仿真绘图代码。这套东西不复杂适合在校学生、刚接触光伏仿真的工程师以及要做 MPPT 算法验证、并网逆变器前级仿真的人直接拿去用。它不是让你在 Simscape 里拖个现成模块然后一脸懵而是从光伏电池的等效电路出发把方程、Simulink 框图、批量仿真脚本、绘图模板串成一条完整链路保证你能理解每个环节在干什么也能照着复现。我在实际项目中用过 Simscape 自带的光伏模块也自己搭过模型。自建模型的优势在于参数可控、逻辑透明、不依赖额外工具箱授权并且非常方便改成“组件级、阵列级”或者“带温度的实时变化”模型。下面这套就是我平常教学和自己做仿真时最常用的一套版本我把细节都展开讲一遍包括建模思路、参数计算、Simulink 搭建方法、批量绘图代码、文档组织方式以及在仿真中很容易踩的坑。1. 建模前的准备光伏电池的核心方程与参数概念1.1 单二极管等效电路到底在讲什么光伏电池的电气特性工程上最常用的是“单二极管五参数模型”。它的等效电路可以这样理解光照在 PN 结上会产生光生电流 Iph这个电流可以看成是一个恒定电流源PN 结本身又是一个二极管存在反向饱和电流 I0半导体材料和电极接触会有接触电阻对应串联电阻 Rs电池边缘漏电和内部缺陷会造成漏电流路径对应并联电阻 Rsh。根据基尔霍夫电流定律输出电流 I 与输出电压 V 的关系式为I Iph - I0 * [exp((V IRs) / (a * Vt)) - 1] - (V IRs) / Rsh其中 Vt Ns * k * T / q是热电压的组件级表达。Ns 是单体电池串联数量k 是玻尔兹曼常数T 是电池温度开尔文q 是电子电荷a 是二极管理想因子。很多新手看到这个方程第一反应是“好复杂”但它拆开看并不难第一项 Iph 是光照产生的电流第二项是二极管分流掉的电流第三项是并联电阻漏掉的电流。你从外部能测到的输出电流就是光生电流减去这两部分损耗。我在实际教学中经常打一个比方光生电流是水管里流进来的水二极管和并联电阻是两个漏水口串联电阻是管道里的摩擦阻力。你希望水龙头的出水尽量大就得让两个漏水口尽量小、管道阻力尽量低。这个类比能帮你快速理解后面调参的方向Rs 大填充因子差Rsh 小曲线在最大功率点附近塌陷严重。1.2 从 datasheet 拿到哪五个关键参数搭建模型的第一步不是写代码而是明确你仿真对象是哪种组件。拿一块常见 260W 多晶硅光伏组件来说datasheet 上标称参数如下参数符号典型值短路电流Isc8.21 A开路电压Voc32.9 V最大功率点电流Impp7.61 A最大功率点电压Vmpp26.3 V短路电流温度系数Ki0.0032 A/°C开路电压温度系数Kv-0.123 V/°C串联电池数量Ns54这里要强调短路电流、开路电压、最大功率点电流和电压都是标准测试条件 STC 下的值也就是辐照度 1000 W/m²、电池温度 25°C、AM1.5 光谱。你可能会问我们建模型不是直接需要 Rs、Rsh、I0 这些参数吗datasheet 为什么不直接给原因很简单厂商不会在铭牌上标这些内部参数它们是“隐含参数”只能通过标准参数反推。反推的思路是让模型在三个关键点与 datasheet 完全吻合短路点V0, IIsc、开路点I0, VVoc、最大功率点VVmpp, IImpp。只要这三个点能对上整个 I-V 曲线在中段尤其是最大功率点附近就不会差太多后续做 MPPT 仿真的可靠性才有保障。温度系数 Ki 和 Kv 也不能忽略。它们决定了辐照度和温度变化时 I-V 曲线的平移趋势。辐照度主要影响电流温度主要影响电压这两个规律在后面的绘图阶段你会在曲线上直观看到。1.3 工程简化模型和隐含数解法在 Simulink 里直接解那个超越方程最关键的是 Iph、I0、Rs、Rsh 这四个内部参数的确定。工程上常用如下简化估计Iph (Isc Ki * (T - Tref)) * G / GrefI0 (Isc Ki * (T - Tref)) / (exp((Voc Kv * (T - Tref)) / Vth) - 1)其中 Vth Ns * a * k * (T 273.15) / q。至于 Rs 和 Rsh很多人直接取 Rs (Voc - Vmpp) / ImppRsh 则取一个较大的值比如 300~1000 欧姆。这种取法在最大功率点附近精度是可以接受的但如果你要做高精度曲线拟合建议用最小二乘或者粒子群去辨识。这里有个数学细节必须注意方程中 V 和 I 都在指数项和分母项里属于隐式方程没办法直接写成 I f(V) 的显式形式。所以在 MATLAB Function 里我习惯用 fzero 求根把问题转成求 I使得 Iph - I0 * (exp((V IRs) / Vth) - 1) - (V IRs) / Rsh - I 0初始猜测值设为 0.9 * Iph。求根区间 [0, Iph] 也可以因为光伏电池正常工作时输出电流不会超过光生电流。后文代码会直接展示这个做法。你也可以用牛顿迭代自己写几行效果差不多但 fzero 在数值稳定性上更省心。2. Simulink 模型搭建从方程到仿真框图2.1 建模方式的取舍MATLAB Function 模块 vs Simscape 自带模型聊到 Simulink 光伏建模很多人第一反应是 Simscape Electrical 里的 PV Array 模块。确实官方模块在并网逆变器、微电网这种需要和电力电子拓扑实时交互的场景里很方便它内部已经帮你算好了所有参数还能直接设置组串并联数、MPPT 接口等。但我还是建议你掌握“从零自建”的方式至少在研究和教学场景里它的优势更明显对比维度自建 MATLAB Function 模型Simscape 自带 PV Array 模块需要工具箱只需要 Simulink 基础模块需要 Simscape Electrical灵活性完全可控任意改内部算法只能设置厂商参数内部黑盒计算速度较快适合批量扫描较重适合精度仿真教学友好度高能看到完整公式低模块内部逻辑不可见与 MPPT 算法联调方便输出电压电流自己决定方便但接口是物理域我的建议是如果你是做光伏电池特性研究、MPPT 算法验证或者给学生上课讲原理自建模型是首选如果你在做完整的并网系统、需要把模型放在一个大的 Simscape 物理域网络里跑那就老老实实用官方模块别拿自建模型去和电感电容直接连物理端口。两种方式各有各的用武之地。2.2 用 MATLAB Function 模块写光伏电池方程实操步骤很简单先新建一个 Simulink 模型我这里命名为 pv_curve.slx。然后从常用模块库里拖入几个关键模块MATLAB Function用于写光伏电池方程斜坡信号 Ramp 或 Signal Builder用于产生电压扫描信号Constant用于给定辐照度 G 和温度 TProduct用于计算功率 P V * ITo Workspace用于导出 V、I、P 到工作区Scope用于快速查看曲线MATLAB Function 里核心代码如下function I pv_cell_engine(V, G, T) % 组件参数260W 多晶硅组件示例 Isc 8.21; % 短路电流 A Voc 32.9; % 开路电压 V Impp 7.61; % 最大功率点电流 A Vmpp 26.3; % 最大功率点电压 V Ns 54; % 串联电池片数 Ki 0.0032; % 短路电流温度系数 A/°C Kv -0.123; % 开路电压温度系数 V/°C a 1.3; % 二极管理想因子 Tref 25; % 参考温度 °C Gref 1000; % 参考辐照度 W/m² k 1.3806503e-23; q 1.60217646e-19; Tk T 273.15; % 转开尔文 Vth Ns * a * k * Tk / q; % 估算内部参数 Iph (Isc Ki * (T - Tref)) * G / Gref; I0 (Isc Ki * (T - Tref)) / (exp((Voc Kv * (T - Tref)) / Vth) - 1); Rs (Voc - Vmpp) / Impp; Rsh Vmpp / (Iph - I0 * (exp((Vmpp Impp * Rs) / Vth) - 1) - Impp); % 隐式方程求根 fun (i) Iph - I0 * (exp((V i * Rs) / Vth) - 1) - (V i * Rs) / Rsh - i; I fzero(fun, 0.9 * Iph); end这里有几个细节要交代输入 V 是由外部斜坡信号产生的 0 到 35V 电压扫描G 和 T 是两个常量。输出 I 后用 Product 模块把 V 和 I 相乘得到 P然后把三者一起送进 To Workspace 模块。我实际测试过用 ode45 默认步长跑一次完整扫描只需要零点几秒效率完全够用。不过注意 fzero 在每个时间步都会被调用一次如果你最后要把仿真时长拉到几十秒计算量会线性增加。你在批量仿真之前先把 StopTime 设置合理比如电压扫描速率是 10V/s扫描 0~35V 需要 3.5 秒留点余量设成 4 秒就够了。2.3 代数环问题仿真中必踩的一个坑刚开始搭这个模型的时候最容易碰到的问题就是代数环。出现代数环的原因是如果你用“可变负载电阻”来连接模型输出电压 V I * Rload而 I 又依赖 V模型里就出现了瞬时信号循环。Simulink 会在诊断窗口报一个警告提示存在 Algebraic Loop求解时会增加迭代严重的会导致仿真缓慢甚至报错。解决方式有三条路我按推荐程度排序第一种也是最推荐的方式用“电压源扫描法”而不是“可变电阻法”。也就是说直接从外部给定电压 V然后模型计算对应的 I。这样信号流向是单向的从电压到电流没有循环依赖根本不会产生代数环。我前面搭的框图就是这种方式。第二种如果你的实际场景是光伏电池接电阻负载或者 DC/DC 变换器必须让电压和电流双向耦合那就在反馈回路上加一个 Memory 模块或者单位延迟 Unit Delay把代数环“打断”。本质上是用上一个仿真步长的输出量代替当前步长的瞬时值代价是会引入一个步长的延迟但只要步长足够小对结果影响可忽略。第三种把整个方程整合进一个更大的状态空间用 Simulink 的求解器统一处理。这个方法理论最优但对使用者要求高实际很少人用它来搭光伏模型。我的经验是做 I-V 曲线扫描时一律用电压源扫描法做 MPPT 或并网仿真时在反馈回路里放一个 Memory。这两种方式我都验证过仿真结果一致稳定性很好。2.4 封装子系统与参数接口设计模型调通以后不要嫌麻烦把它封装成子系统加上 Mask。这一步很多人会跳过但等你要做温度扫描、辐照度扫描或者换一块电池板参数时封装的价值就体现出来了。封装操作方法选中所有模块右键 Create Subsystem然后右键子系统 Mask Create Mask。在 Mask Editor 里添加参数比如短路电流 Isc开路电压 Voc最大功率点电流 Impp最大功率点电压 Vmpp串联电池数 Ns这样你每次只需要双击子系统在弹出的对话框里换参数而不需要打开 MATLAB Function 去改代码。尤其当你有多个相同结构的子阵列时封装后的效果就是“参数填进去直接出结果”。我习惯在封装说明里也写清楚输出电压范围不超过 Voc 的 1.2 倍辐照度单位是 W/m²温度单位是 °C。这能避免同事或学生后续使用时因为单位问题把曲线跑飞。3. 仿真绘图代码把仿真结果变成易读的曲线3.1 使用 sim 函数批量扫描不同工况单条 I-V 曲线只是在验证模型真正有说服力的图是“不同辐照度下的曲线族”和“不同温度下的曲线族”。手动在 Simulink 里改常量再点运行当然可以但那样效率太低而且不容易统一管理数据。正确做法是写一个仿真脚本在循环里修改模型参数调用 sim 函数批量跑。下面这段脚本是我常用模板。假设模型里辐照度常量模块名为 G温度常量模块名为 TTo Workspace 输出变量名分别为 Vout、Iout、Pout。mdl pv_curve; load_system(mdl); G_list [1000 800 600 400 200]; results struct(); for i 1:length(G_list) set_param([mdl /G], Value, num2str(G_list(i))); set_param([mdl /T], Value, 25); simOut sim(mdl, StopTime, 4); results(i).G G_list(i); results(i).V simOut.Vout.Data; results(i).I simOut.Iout.Data; results(i).P simOut.Pout.Data; end这段代码有几个容易忽略的细节。set_param 修改的 Value 必须是字符串所以要用 num2str 转换。sim 函数的返回值建议用 Simulink.SimulationOutput 对象接收这样数据格式统一后面绘图不容易出错。建议在命令行先运行 load_system避免每次循环都在加载模型上浪费时间。另外一个实战经验是批量仿真之前把模型的“快速重启 Fast Restart”功能打开可以在 Tools Run Fast Restart 里设置。这样循环里的多次仿真会共享编译结果仿真速度能提高不少。尤其是你后面要做几十组参数扫描时这个设置能节省大量时间。3.2 绘制 I-V 曲线与 P-V 曲线的完整代码数据拿到手以后下一步就是画图。我习惯把 I-V 曲线和 P-V 曲线放在同一张图的两个子图里或者用双 y 轴放在同一张图。双 y 轴的好处是能直观看到最大功率点对应的位置但需要注意坐标轴刻度范围设定不然曲线会挤在一起。figure(Color, w, Position, [100 100 900 600]); colors lines(length(results)); hold on; yyaxis left; for i 1:length(results) plot(results(i).V, results(i).I, Color, colors(i, :), LineWidth, 1.6); end ylabel(电流 I (A)); xlabel(电压 V (V)); ylim([0 9]); xlim([0 35]); yyaxis right; for i 1:length(results) plot(results(i).V, results(i).P, --, Color, colors(i, :), LineWidth, 1.2); end ylabel(功率 P (W)); ylim([0 280]); legend(arrayfun((x) sprintf(G%d W/m², x.G), results, UniformOutput, false), Location, northeast); grid on; set(gca, FontName, Helvetica, FontSize, 11);在 MATLAB 中文环境下如果图例或坐标轴要显示中文你需要在画图前设置系统的默认字体否则中文会显示成方块。常用的设置命令是set(0, defaultAxesFontName, SimHei); set(0, defaultTextFontName, SimHei);如果是在英文版 MATLAB 上运行建议直接用英文标签省得字体问题影响阅读。我平时交付给别人的脚本里会保留中英双语变量注释但图上的文字统一用中文因为国内团队看得更直观。图片导出建议用 print 命令而不是直接截图这样输出分辨率可控。比如print(gcf, pv_curve_family.png, -dpng, -r600);600 DPI 足够期刊插图使用。如果你要把图放进 Word 报告300 DPI 就够了文件体积还小。3.3 不同温度/辐照度对比曲线的一次成型技巧做温度扫描的逻辑完全一样只需要把常量 T 设为循环变量G 固定为 1000。温度范围我一般取 0°C、25°C、50°C、75°C 这四档覆盖大部分户外运行场景。有个技巧是把辐照度扫描和温度扫描的绘图函数封装成独立函数 draw_iv_curve(results, title_str)这样两种工况的绘图脚本共用一个函数代码量小风格也统一。我就是这么组织的function draw_iv_curve(results, title_str) ... end另外在画 P-V 曲线时我习惯同时标注出每个工况的最大功率点。计算方法很简单用 max 找到最大功率和对应的电压电流索引[Pmax, idx] max(results(i).P); Vmpp_calc results(i).V(idx); Impp_calc results(i).I(idx);然后在图上用 scatter 画一个实心点再用 text 标注数值。这样审稿人和领导一眼就能看出你的模型最大功率和 datasheet 标称值的偏差。4. 说明文档的组织方法让模型可以被别人复现4.1 一个能复现模型的说明文档应该包含哪些章节项目标题里特意强调“附带说明文档”这一点很多人忽略但它恰恰是这套模型价值能不能发挥出来的关键。我自己收过很多没有文档的模型文件拿到手根本不知道该改哪里、参数在哪里设置、输出怎么处理。所以我在交付模型时说明文档固定包含六个部分项目说明这套模型是什么、解决什么问题、适合用在哪些场景。文件清单模型文件、函数文件、脚本、数据文件的目录树以及每个文件的作用。快速开始从打开 MATLAB 到复现一张 I-V 曲线的完整操作步骤。参数表所有参数的名称、符号、初始值、单位、来源。仿真结果示例标况下的 I-V/P-V 曲线图、不同工况对比图。注意事项与常见问题包括版本要求、求解器设置、常见报错处理。你可以直接用 Word 或者 Markdown 写也可以做成项目里的 README.md。我的习惯是既放一份 Markdown 在项目根目录再导出一份 PDF 放进 doc 文件夹方便给不看代码的人快速了解。说明文档里最关键的是“快速开始”。不要假设接手你模型的人很熟悉 MATLAB。你要写清第一步打开 pv_curve.slx第二步点击运行第三步在命令行执行 plot_curves.m第四步看输出图片。每多写一个步骤用户自己摸索的时间就少十分钟。4.2 命名规范和变量管理模型里涉及的参数很多如果命名随意后期维护非常痛苦。我的命名规范是这样的物理量直接用英文字母组合例如 Isc、Voc、Impp、Vmpp、Ns、Ki、Kv。多个参数可以用结构体打包例如 params.Isc、params.Voc这样在 MATLAB Function 里只需要传一个 params 进去。Simulink 模型名称和文件名称统一不用中文和空格。脚本名称用动词开头例如 plot_curves.m、run_sweep.m、export_figures.m。另外要注意Simulink 模型内部的信号名也很重要。双击信号线可以输入名称比如 V_pv、I_pv、P_pv这样 To Workspace 导出以后的工作区变量名会带上信号名方便识别。很多人忽略这个细节最后导出数据后还要手动猜哪个变量是电压哪个是电流非常浪费时间。4.3 关于版本和工具箱的注意事项我搭建这套模型用的是 R2021a 版本核心功能在 R2020b 以上都能正常运行。需要特别注意的是MATLAB Function 模块在早期版本叫 Embedded MATLAB Function界面略有不同但代码写法基本一致。如果你的 MATLAB 版本是 2016a 之前的老版本建议先升级否则有些模块接口会不兼容。工具箱方面这套自建模型只需要 MATLAB 基础包和 Simulink不需要额外安装 Simscape、Simscape Electrical 等授权工具箱这对很多没有购买全套工具箱的学生来说非常友好。但如果你要用官方 PV Array 模块对比验证那你需要确认许可证里包含 Simscape Electrical。版本兼容性还会影响绘图导出的字体例如不同操作系统下 SimHei 字体的支持情况不同。为了避免交付后图片字体错乱我通常在脚本开头统一检查是否有对应字体没有就自动切换成系统的默认字体。5. 常见问题与排查技巧实录5.1 问题1MATLAB Function 模块报错Not enough input arguments这个问题在我刚把代码拷贝进 MATLAB Function 模块时经常遇到。原因通常是模块的输入引脚数量和函数声明里的输入参数数量不一致。比如你在函数声明里写了 function I pv_cell_engine(V, G, T)但模块只有两个输入引脚那就必然报错。解决办法双击 MATLAB Function 模块在编辑器上方的“编辑数据”里检查输入名称确保与函数参数名一致并且数量对得上。另外输入的数据类型也要留意如果 G 是 uint8而函数内部做浮点运算可能会触发类型转换错误建议在 Constant 模块的输出数据类型里直接设成 double。5.2 问题2仿真曲线出现毛刺或负电流出现毛刺大概率是求解器步长过大导致的。光伏电池的 I-V 曲线在最大功率点附近转折很剧烈如果变步长求解器没有捕捉到这个转折就会出现数值振荡。解决办法是打开 Configuration Parameters把 Solver 类型保持 Variable-step算法选 ode45同时把相对误差 Relative tolerance 改小例如 1e-5最大步长 Max step size 设置成 0.01 或更小。如果出现负电流一般是电压扫描超过了开路电压太多导致二极管反向偏置模型在某些数值条件下算出很小的负电流。解决办法很简单把扫描电压上限设成 Voc 的 1.05 倍就够了不用扫到 40V、50V。同时 fzero 求根区间最好限制在 [0, Iph]防止在非物理区间迭代发散。5.3 问题3最大功率点偏差过大这是最需要重点排查的问题。模型在短路点、开路点一般都很准但最大功率点如果不准通常原因有三个第一个是 Rs 和 Rsh 估计过于粗糙Rs 增大最大功率点功率显著下降Rsh 减小曲线在最大功率点左侧塌陷第二个是二极管理想因子 a 取值不合适常见晶硅组件 a 在 1~1.5 之间但不同厂商工艺有差异第三个是温度系数 Ki、Kv 设置错误导致温度变化时最大功率点偏移。我的经验是先用 datasheet 给的最大功率点反推一遍 Rs 和 Rsh然后在仿真里扫描 a 的取值看哪个值让最大功率点功率误差最小。如果误差还是超过 3%那就得用优化算法辨识参数。别怕这个步骤麻烦参数辨识一次完成后模型在宽范围内都稳定。5.4 问题4批量仿真数据覆盖或无法保存批量循环里如果每次都用同一个变量名接收 sim 输出下一次循环会把上一次的结果覆盖掉。所以必须用结果数组或元胞数组保存。我常用 results(i).V simOut.Vout.Data 这种方式每一组数据单独存放。还有就是 To Workspace 模块的输出格式建议选“Timeseries”不要用“Array”或“Structure With Time”因为 Timeseries 自带时间和数据后续提取更方便。如果 sim 函数最后一次运行报错检查模型编译阶段是否有问题可以在循环外加 try-catch把出错工况打印出来。这样即使某个辐照度下模型收敛失败也不会中断整个批量扫描。5.5 常见排查速查表现象可能原因处理方法代数环警告电压和电流存在瞬时反馈用电压源扫描法或在反馈回路加 Memory曲线毛刺多求解器步长过大降低相对误差设置最大步长最大功率点偏低Rs 估计偏大用 datasheet 最大功率点方程反推 Rs低温曲线异常温度单位写错确认 T 单位为 °C内部转开尔文批量仿真很慢未开启快速重启启用 Fast Restart中文乱码系统字体不支持设置 defaultAxesFontName 为 SimHei 或改英文标签6. 一眼定睛接线信号方向与 To Workspace 的数据类型最后再分享两个我踩过不少坑的小细节。第一个是关于信号方向。在 Simulink 里从电压源到 MATLAB Function 模块再到 Product信号方向一定是从左到右单向流动。如果你不小心把 G 的 Constant 也接到函数输出端或者连线交叉导致信号回流仿真结果会非常诡异。检查方法是选中连线看是否有红色虚线那是未连接或连接错误的提示。第二个是 To Workspace 模块的数据类型。在设置界面里有个 Save format 下拉菜单我推荐选择 Timeseries。很多人默认会选 Structure等到工作区里发现 simOut.Vout.Data 取不到数据才回头改。这个小坑浪费了我不少时间所以提前写在这里。我自己使用这套模型时已经形成了固定的项目文件结构模型文件放根目录脚本放 scripts 文件夹生成的图片放 figures 文件夹说明文档放 doc 文件夹。每次做 MP PT 算法对比时只需替换外围控制器部分光伏电池模型本身基本不用动。你现在拿这套代码去复现只要按顺序把步骤走完半小时内就能跑出完整的 I-V/P-V 曲线族。如果后续要扩展加上一个 Boost 变换器和扰动观察法就能直接开始做最大功率点跟踪的仿真实验了。
返回列表