简介:离网太阳能发电系统采用光伏板独立供电,适用于偏远地区、应急电源及小型户用等场景。配套的MATLAB程序覆盖光伏组件选型、储能配置与控制策略等核心环节,利用Simulink建立光伏与电池模型,并借助遗传算法、粒子群等优化算法求解经济性最优的装机容量,适合新能源方向的学生与工程师进行方案预研和参数验证。压缩包共2个文件,包含1个脚本文件和1个数据文件,体积仅66KB,结构精简便于快速运行。已有205人学习下载。其中主程序实现了完整的离网系统仿真优化流程,数据文件提供典型光照与负荷数据,可直接调用测试。通过学习可掌握离网光伏系统的建模思路、储能充放电管理方法以及成本效益分析过程,为实际工程配置提供实用参考。
1. 离网太阳能发电系统的仿真边界:先建模还是先算账
离网太阳能发电系统在 Matlab 里做仿真,绝大多数人第一步就选错了方向——一上来就拖 Simulink 库里的 PV Array 模块,然后接个负载看波形。这样做出来的模型,本质上只是个电路演示,离工程决策差得很远。真正的离网系统仿真,核心不是“光伏板发电”这一件事,而是“发电、储能、负载、控制”四个环节的能量闭环:光照变化时 MPPT 有没有跟上,蓄电池 SOC 冲到上限时控制器怎么切状态,负载突增时直流母线电压跌到多少伏、多久能恢复。这些问题的答案,才是一个离网系统能不能稳定运行的关键。所以本文的路线是:先把系统结构分层拆开,再逐个模块用 Matlab/Simulink 实现,最后讨论参数整定和收敛性验证。无论是做毕业设计、课题预研,还是给实际项目做前期容量测算,这套方法都能直接复用。需要用到的工具箱主要是 Simulink、Simscape Electrical(或 SimPowerSystems)和 Optimization Toolbox;版本方面,R2021b 到 R2024a 的界面差异对以下操作影响不大。
2. 在 Simulink 里搭离网光伏系统的核心拓扑与组件选型
2.1 五要素拓扑:光伏阵列、Boost 电路、蓄电池、逆变器、负载
离网系统不像并网系统那样需要严格的电网同步和孤岛保护,它的拓扑结构相对固定,但每个环节的建模粒度可以差出好几个量级。常见做法是把系统分成五个部分:光伏阵列(PV Array)、直流变换器(DC-DC)、储能单元(Battery)、逆变器(DC-AC)和交流/直流负载。其中直流母线的电压等级决定了后续所有参数:如果选 48V 母线,Boost 输出要稳定在 48V 附近;如果选 400V 母线(为了匹配后级逆变器),那 Boost 的占空比和电感参数就得重新算。
建模粒度是第一个要做的决策。如果目标是看系统级能量调度,光伏阵列用 Simscape Electrical 里的PV Array模块就够了,它基于单二极管五参数模型,输入是辐照度和温度,输出是 I-V 曲线;如果你要研究 MPPT 算法本身的动态性能,比如在局部阴影下的多峰寻优,那就要用PV Array的P-V特性输出,配合自己写的 MPPT 控制器。蓄电池模型同理,Battery模块(默认是锂离子模型)适合看 SOC 和端电压,如果要精确模拟铅酸电池的析气过电位,就得换用 Simulink 自带的Lead-Acid Battery模型或自己搭等效电路。
2.1.1 直流母线的电压等级选择
先定母线电压,再往下选器件,这个顺序不能反。48V 母线对应小功率户用系统(1kW-3kW),安全电压低,但电流大,线损高;400V 母线对应 5kW 以上系统,对绝缘和安规有要求,但传输效率高,逆变器选型更容易。在仿真里,母线电压等级直接影响 Boost 电路的升压比和电感的电流纹波。例如 24V 光伏阵列输入、48V 母线输出,Boost 占空比大约在 0.5 附近;如果光伏阵列开路电压是 36V,最大功率点电压是 29V,那占空比就是 1 - 29/48 ≈ 0.396。这个数不是随便填的,它决定了电感电流是连续模式(CCM)还是断续模式(DCM),进而决定 MPPT 算法会不会因为电流纹波过大而震荡。
2.2 参数设置的关键:从组件数据手册提取等效参数
Simulink 里的PV Array模块有两种参数输入方式:一种是用默认的预设模块,比如1SolTech 1STH-215-P;另一种是自己填参数,包括Cells per module(每块板子串联电池片数)、Open circuit voltage、Short-circuit current、Voltage at MPP、Current at MPP。实际上,PV Array模块会基于这五个参数反推单二极管模型的五个未知量——光电流、反向饱和电流、串联电阻、并联电阻、理想因子。如果你的组件数据手册里没有并联电阻值,直接用模块自带的算法计算就行。
但这里有个很常见的坑:PV Array模块里填的Series resistance和Shunt resistance如果直接用典型值,会导致最大功率点的仿真值和数据手册差 3%-5%。解决方法是把模块的Parameter选为Array-based,然后用实际组件的 I-V 曲线上的三个点——短路点、开路点、最大功率点——让 Matlab 用fsolve反推。参考代码如下:
% 根据组件数据手册三点反推 PV Array 等效参数 % 输入: Voc, Isc, Vmp, Imp, Ns(串联电池片数), Np(并联组串数) Voc = 45.8; Isc = 9.08; Vmp = 37.2; Imp = 8.55; Ns = 72; Np = 1; % 初始猜测: Rs通常很小, Rp通常很大 x0 = [0.01, 1000, 1.2]; % [Rs, Rp, a(修正理想因子)] % 定义误差函数: 以单二极管模型在三个关键点的电流误差为目标 fun = @(x) pv_param_error(x, Voc, Isc, Vmp, Imp, Ns, Np); options = optimoptions('fsolve', 'Display', 'off', 'MaxIterations', 200); x = fsolve(fun, x0, options); fprintf('Rs = %.4f Ohm, Rp = %.1f Ohm, a = %.3f\n', x(1), x(2), x(3)); function F = pv_param_error(x, Voc, Isc, Vmp, Imp, Ns, Np) Rs = x(1); Rp = x(2); a = x(3); Vt = Ns * 1.380649e-23 * 298.15 / 1.602176634e-19; % 热电压(串联) Iph = Isc * Np; % 近似取光电流等于短路电流 Io = Isc * Np / (exp(Voc / (a * Vt)) - 1); % 反向饱和电流 % 在最大功率点计算误差 I_mp = Iph - Io * (exp((Vmp + Imp * Rs) / (a * Vt)) - 1) - (Vmp + Imp * Rs) / Rp; % 在开路点计算误差 I_oc = Iph - Io * (exp(Voc / (a * Vt)) - 1) - Voc / Rp; % 在短路点计算误差 I_sc = Iph - Io * (exp(Isc * Rs / (a * Vt)) - 1) - Isc * Rs / Rp; F = [I_mp - Imp; I_oc - 0; I_sc - Isc]; end代码的逻辑是:把单二极管模型的方程在短路、开路、最大功率点三个工况下分别列出来,然后用fsolve找到最能同时满足这三个工况的 Rs、Rp 和理想因子 a。说白了这个过程就是在拟合数据手册上的 I-V 曲线。注意optimoptions里把MaxIterations提到 200,是因为参数初值猜得不好时,100 次迭代可能收不到一个能用的解。完成反推后,把得到的 Rs、Rp 填进PV Array模块的Detailed model选项卡里,你会发现仿真得到的 P-V 曲线和厂商曲线几乎重合。
3. MPPT 模块的工程实现:从扰动观察到增量电导
3.1 为什么固定电压法在离网系统里不够用
离网系统的负载是随时变的,蓄电池的端电压也会随着 SOC 变化而波动。固定电压法(Constant Voltage,CV)把光伏阵列的工作点固定在某个电压上,比如 0.8 倍的 Voc(开路电压)。这个方法的致命伤在于:“0.8 倍 Voc 是最大功率点”这个结论只在标准测试条件(STC,即 1000W/m²,25°C)下成立。当温度升高到 60°C 时,最大功率点电压可能掉到 0.7 倍 Voc 以下,固定电压法会在一个偏离真实最大功率点 8%-12% 的位置工作,发电量直接损失掉这一截。所以真正做离网控制器,至少要上扰动观察法(P&O)。增量电导法(IncCond)比 P&O 好在光照快速变化时不容易误判方向,代价是计算量稍大——但对现代 MCU 和 Matlab 仿真来说根本不是问题。这两种算法在 Simulink 里都可以用 Stateflow 实现,也可以用普通的 Enabled Subsystem 搭。
3.2 P&O 与 IncCond 的仿真实现与参数设置
我一般建议在仿真阶段直接用 MATLAB Function 块写 IncCond,因为它和 C 代码的移植非常接近,后期做嵌入式代码生成时改造成本最低。下面这个代码块是一个可以直接放进 MATLAB Function 模块的实现,注意输入输出端的设置:
function D = IncCond(V, I, D_prev, V_step) % 增量电导法MPPT: 输入光伏阵列电压V、电流I、上一周期占空比D_prev、电压扰动步长V_step % 输出: 更新后的占空比D persistent V_old I_old D_old if isempty(V_old) V_old = 0; I_old = 0; D_old = 0.5; end dV = V - V_old; dI = I - I_old; if abs(dV) < 1e-6 % 电压没有变化, 用电流变化方向判断 if dI > 0 D = D_old - V_step; % 仍在最大功率点左侧, 继续升压 else D = D_old + V_step; % 已越过最大功率点, 降压 end else dIdV = dI / dV; if abs(dIdV + I/V) < 1e-5 D = D_old; % 工作点已到达最大功率点附近, 保持 elseif dIdV > -I/V D = D_old - V_step; % 工作在最大功率点左侧, 增大占空比 else D = D_old + V_step; % 工作在最大功率点右侧, 减小占空比 end end D = min(max(D, 0.1), 0.9); % 限幅, 防止占空比越界 V_old = V; I_old = I; D_old = D; end注意几个参数的设置逻辑。V_step是电压扰动步长,它直接决定 MPPT 的稳态精度和跟踪速度的折中——步长取小了(比如 0.1V),稳态波动小但光照突变时要几百毫秒才能追上新工作点;步长取大了(比如 1V),跟踪快但稳态时会在最大功率点附近来回震荡,造成功率损失。在仿真里先用 0.5V 起步,观察 MPPT 的输出功率波形,如果波动超过 3%,就把步长减半。persistent变量在第一次调用时初始化,这个机制保证了每个仿真步长之间状态是连续的,但要注意:如果你把这段代码用在不同的仿真任务里(比如分别测 STC 和 200W/m² 低辐照),必须用clear all或者给模块加一个外部复位信号,否则旧的D_old会污染新工况。
3.2.1 占空比扰动和电压扰动的区别
上面的代码是“电压扰动”实现——先算电压变化量,再映射到占空比。另一种做法是“占空比扰动”,直接令D_new = D_old + D_step,然后比较功率增减来修正方向。电压扰动的优点是:在不同辐照度下扰动步长对系统动态的影响是均匀的——因为光伏阵列的 I-V 曲线在不同光照下形状差异很大,同样的 D_step 在低辐照时造成的电压变化可能比高辐照时大一倍;而电压扰动就没有这个问题。缺点是:需要额外读取 V 和 I 计算 dV 和 dI,传感器噪声会被直接放大。在 Simulink 里做闭环验证时,我倾向于在电压测量通道上接一个 Transfer Function 做一阶低通滤波,时间常数设 1ms 到 5ms,滤波后dV的抖动会明显改善。
3.3 辐照度突变时的 MPPT 压力测试
MPPT 参数是否合理的验证方式不是看稳态,而是看瞬态。在 Simulink 里用 Signal Builder 或 Step 模块构造一个从 1000W/m² 跳到 400W/m² 的辐照曲线,观察占空比输出和光伏功率变化。合格的响应是:功率在两三个扰动周期内重新收敛并稳定在新最大功率点附近,占空比不产生超过 10% 的过冲。如果仿真时发现 P&O 算法在辐照下降的瞬间把占空比往错误方向调(因为功率下降被误判为扰动方向错了),这就说明步长和采样频率的比值偏高。解决办法有两个:一是把 MPPT 的采样周期从 0.1s 缩短到 0.01s——让功率比较的时间间隔小于光照变化的斜率,减少误判窗口;二是改用 IncCond,因为它用dI/dV的符号而不是功率变化的符号来判断,对抗误判的能力更强。下表是三个参数在不同组合下的表现对比,来自同一套仿真模型的多次运行:
| 采样周期 (s) | 电压步长 (V) | 稳态功率波动 | 辐照突变后收敛时间 | 是否出现误判 |
|---|---|---|---|---|
| 0.1 | 1.0 | ±4.2% | 0.8s | 是 |
| 0.01 | 0.5 | ±1.1% | 0.2s | 否 |
| 0.001 | 0.2 | ±0.3% | 0.05s | 否,但PWM开关纹波明显 |
4. 蓄电池与逆变器的平衡控制:SOC 保护与 PI 参数整定
4.1 蓄电池建模:把 SOC 估算误差压到 5% 以内
Simulink 的Battery模块有锂离子、镍氢、铅酸三种预设模型。离网系统用铅酸还是锂电,直接决定 SOC 估算策略。铅酸电池在浮充阶段端电压变化非常平缓,靠电压估 SOC 误差极大;锂电池在 SOC 20%-80% 区间内端电压斜率同样平缓。常用的方法是安时积分法——对电流积分来算 SOC。这有个致命缺陷:电流传感器的零点漂移会积分成 SOC 偏移。一小时 10mA 的漂移,在一个 200Ah 的电池组上,一天下来就是 1.2% 的 SOC 误差。所以仿真里要用卡尔曼滤波对 SOC 做修正:状态量是 SOC,观测量是端电压,模型的测量方程就是电池开路电压与 SOC 的对应关系,再用 RC 网络拟合极化效应。
在 Simulink 里实现电池 SOC 的扩展卡尔曼滤波,需要先用Battery模块的Terminal voltage和SOC输出拉一组数据,离线拟合 OCV-SOC 曲线。然后用下面的 MATLAB Function 块做在线估计:
function [SOC_est, P_out] = EKF_SOC(term_voltage, current, Ts, SOC_prev, P_prev) % 扩展卡尔曼滤波SOC估计: 状态SOC, 观测端电压 % Ts: 采样周期, 单位秒 % 电池容量已知(示例值200Ah), 电流正方向为放电 Ccap = 200 * 3600; % 电容转库仑 % 状态更新: SOC(k+1) = SOC(k) - I*Ts/Ccap (放电为正) A = 1; % 状态转移矩阵 B = Ts / Ccap; % 观测方程: OCV_SOC(SOC) + R0*I + 极化电压 [R0, R1, C1] = get_battery_params(); % 从Battery模块辨识 OCV = ocv_function(SOC_prev); % 查表函数 h = OCV + R0 * current; % 简化观测模型 H = (ocv_function(SOC_prev + 0.001) - OCV) / 0.001; % 线性化 % 预测 SOC_pred = SOC_prev - B * current; P_pred = A * P_prev * A' + 1e-6; % 过程噪声协方差 % 更新 K = P_pred * H' / (H * P_pred * H' + 1e-3); % 测量噪声协方差 SOC_est = SOC_pred + K * (term_voltage - h); P_out = (1 - K * H) * P_pred; % SOC限幅 SOC_est = min(max(SOC_est, 0), 1); end注意代码里的ocv_function是用interp1建的查表函数。过程噪声协方差设1e-6,对应的物理意思是:SOC 状态转移本身的误差很小——安时积分内的误差主要来自电流测量漂移和库仑效率;测量噪声协方差设1e-3,对应的是电压传感器的测量噪声标准差约 0.03V。这两个值不能随意改:过程噪声设太小会“迷信”安时积分,卡尔曼增益算出来很小,修正作用弱;测量噪声设太大则相反,SOC 估计值会跟着电压波动乱跳。仿真中的验证方法是把估计出的 SOC 和Battery模块直接输出的 SOC 放在同一个 Scope 里对比,看误差是否稳定在 5% 以内。
4.2 充放电切换逻辑:滞回控制避免振荡
离网系统控制器最核心的逻是防止蓄电池过充和过放。仿真里如果用纯粹的阈值判断——SOC > 0.9 停止充电,SOC < 0.1 停止放电——会发现在临界点附近,只要负载或光照稍有波动,系统就会在充电和放电之间来回切换,继电器和 MOSFET 的平均开关频率上升,损耗和器件应力都变大。正确做法是滞回控制:充电截止阈值设 0.9,重新投入充电的阈值设 0.85;放电截止阈值设 0.1,重新投入放电的阈值设 0.15。这段逻辑用 Stateflow 写流动图比用 Enabled Subsystem 清晰得多,状态的跳转条件一目了然。
在 Simulink 里实现时,把 Stateflow 的输出接给 Boost 电路的使能端和逆变器的 PWM 使能端。注意此时系统的能量流有三个状态:光伏单独供负载(蓄电池不工作)、光伏给蓄电池充电(负载被光伏覆盖)、蓄电池单独供负载(光伏被切断或 MPPT 降功率)。切换到“蓄电池单独供负载”时,Boost 电路必须停止工作,否则光伏阵列的空载电压会直接顶到蓄电池管理系统的过压保护。很多仿真里这个细节没处理好,导致 SOC 很低时母线电压反而飙升,就是这个原因。
4.3 逆变器双闭环 PI 参数整定
逆变器控制是离网系统中另一个核心模块。Simulink 里常用 SPWM 或 SVPWM 调制,电压外环加电流内环。PI 参数整定最直接的方法是:先单独整电流内环,断开电压外环,给电感电流一个阶跃参考,调Kp和Ki让电流的上升时间在 1ms 到 5ms 之间,超调量控制在 10% 以内。然后把电流环闭好,再闭合电压外环,用同样的阶跃方法调电压环。两个环的响应速度必须拉开差距——电流环带宽至少是电压环的 5 到 10 倍,否则外环调节时内环跟不上相位,系统会震荡。
逆变器模型可以用 Simscape Electrical 里的Mosfet加Series RLC Branch搭三相全桥,也可以用 Simulink 自带的平均模型Average-Value Inverter。平均模型省去开关器件,仿真速度快 10 倍以上,适合做 SOC 调度和能量管理的长时间仿真;但如果你要看 PWM 开关频率导致的电流纹波和电压谐波,那就得用详细的开关模型。下表是两种建模粒度的一个快速对比:
| 模型类型 | 仿真速度 | 可观测内容 | 适用场合 |
|---|---|---|---|
| 平均模型 | 快(秒级/天) | 母线电压趋势、SOC走势、功率流 | 容量规划、能量调度 |
| 开关模型 | 慢(分钟级/百毫秒) | 电流纹波、THD、开关损耗 | 控制器参数整定、滤波器设计 |
5. 仿真验证的三步走:从波形观察到故障注入
5.1 第一步:稳态工况下的三处关键波形检查
模型搭完后不要急着接复杂控制。先把辐照度固定在 1000W/m²,温度固定在 25°C,负载电阻固定,跑一次纯稳态仿真。检查三个波形:第一是光伏输出电压是否落在最大功率点电压附近(对比数据手册的 Vmp 值);第二是 Boost 电路输出电压的纹波是否在设定值的 2% 以内;第三是蓄电池电流方向是否正确——太阳充足时光伏给电池充电,入夜后电池放电。如果第二个波形纹波超标,优先检查电感值:Boost 电感电流纹波公式是ΔI = V_in * D / (f_sw * L),把目标纹波设为额定电流的 20%,反推最小电感值。另外检查仿真步长设置:固定步长求解器(如 ode3)时步长要小于开关周期的 1/20,否则 PWM 波形会失真。
5.2 第二步:SOC 边界与负载阶跃的联合测试
把蓄电池初始 SOC 分别设为 95% 和 5%,跑一遍带光照变化的 24 小时仿真(光照曲线用 Signal Builder 构造梯形波,模拟日出日落和中午云遮)。95% SOC 场景下,观察充电回路是否在 SOC 接近 0.9 附近触发滞回下限,切断 Boost 输出——此时光伏功率应该被转移到泄放电阻上(离网系统如果要保持 MPPT 继续工作,必须有泄放负载否则母线会过压);5% SOC 场景下,观察负载是否在 SOC 小于 0.1 时被切断,蓄电池停止放电。这两个测试同时也在验证数值求解器会不会因状态跳变而产生非物理振荡——如果切断瞬间母线电压波形出现超过 20% 的尖峰,检查 PI 控制器的积分限幅是否生效。
5.3 第三步:故障注入与收敛性检查
最后一个技巧是人为注入故障,看模型和控制器是否有“自我保护”的反应。常见做法是:把某一个光伏组串的辐照度突然变为 0(模拟遮挡),观察 MPPT 是否快速把工作点迁移到剩余组串的最大功率点;或者把母线电容值减小 30%,观察是否引发电压环振荡——如果振荡了,说明电压环相位裕度不足,需要降低电压环Ki或增加输出端的小电容做阻尼。这个场景也是验证模型适用于硬件在环(HIL)测试的前提。
跑完这三步后,如果模型的收敛性依然好——即同一工况下两次独立仿真结果差异不超过 0.1%——这套离网系统仿真骨架就可以投入实际使用:改组件参数评估不同光伏板方案的发电量,改电池容量评估备电时长,或者把 MPPT 控制器的 C 代码通过 Embedded Coder 部署到目标 MCU 上。最后提醒一下,仿真永远是模型对模型的闭环验证,离网系统里真正的变量——蓄电池老化、光伏板积灰、负载功率因数变化——在仿真阶段要预留参数接口,别把模型写死成固定值。用set_param或 Mask 参数把这些变量暴露出来,后续做蒙特卡洛分析时能省大量改模型的时间。
本文还有配套的精品资源,点击获取