基于模型预测的混合储能微电网双层能量管理及Matlab实现

📅 发布时间:2026/10/22 5:57:12
基于模型预测的混合储能微电网双层能量管理及Matlab实现
做混合储能微电网能量管理的人最近基本都在聊一个词双层模型预测。标题里的“基于模型预测算法的混合储能微电网双层能量管理系统研究”听起来像个学术项目的名字但落到Matlab里它要解决的核心问题特别直白光伏和负荷不停波动微电网里面的锂电池和超级电容怎么配合才能在保证供电稳定的同时又少花电费、又不把电池冲到过放。这篇文章就是我复现这个系统时的完整思路和Matlab实现记录。适合正在写论文的研究生、想做储能控制仿真的工程师以及被MPC矩阵搞得头疼的初学者。我之前在模拟项目中从单层MPC开始后来发现单层模型要同时考虑经济调度和实时功率分配预测步数一长矩阵规模就爆炸。于是按照多数文献里的做法拆成上层调度、下层分配两层模型预测控制器负责滚动优化Matlab里的quadprog负责把每一步的二次规划问题解出来。今天这篇文章不绕弯路直接从“为什么这么做”讲到“代码怎么落地”再附上我调参数时踩过的坑。1. 整体思路为什么是“双层”加“模型预测”1.1 微电网能量管理要解决什么问题先把问题定义清楚。微电网里一般有光伏、负荷、储能还可能和大电网有功率交换。能量管理系统要做的不是“缺电就放、多电就充”这么简单而是要在满足功率平衡的前提下让运行成本尽量低同时把储能的社会责任管好比如SOC不能越限、寿命不能损耗太快。光伏和负荷都有很强的随机性。光伏中午可能猛增傍晚又骤减负荷可能因为一台大电机启动而产生尖峰。这些扰动发生的时间尺度也不一样有的以小时计有的以秒计。如果只用一个控制器去处理所有这些尺度问题规模会非常大而且不同控制目标的优先级也容易互相干扰。我做单层MPC时就遇到过这个问题把经济性、平抑波动、SOC管理全部塞进一个目标函数预测时域稍微拉长决策变量一下就上百个求解时间和解的稳定性都很难接受。所以双层结构几乎成了标准做法。1.2 双层架构的设计逻辑双层架构的实质是“时间尺度分层”。上层负责长时间尺度通常是15分钟左右一个周期有时候也做一小时。这一层输入光伏和负荷的短期预测结果还有分时电价目标函数是运行成本最小输出是未来一段时间里各单元的基准功率包括并网功率和储能总功率设定值。下层负责短时间尺度也就是秒级甚至毫秒级。这一层接收上层给过来的设定值再根据实时功率偏差把总功率分配给锂电池和超级电容。锂电池承担慢慢变化的低频分量超级电容承担突然冲击的高频分量。这样拆开之后上层解决“该不该充、该不该放、跟电网买多少电”的问题下层解决“谁来充、谁来放、动作快慢怎么配合”的问题。两个控制器都不需要把对方的问题全揽下来矩阵维度和控制目标都清晰很多。1.3 为什么是MPC不是PID也不是单层优化有人会问双层结构里用最简单的那套方法行不行比如上层用优化调度下层用PI控制。其实也可以跑但效果差在两类场景一是约束处理二是未来信息的利用。PID本质上是基于当前误差的反馈控制它看不到未来。当光伏预测到马上要大幅增加时PID不会提前调整储能只会等母线电压或频率变化了才动作。MPC不一样它手里有一份未来Np步的预测轨迹相当于开车时看前方几百米的路况而不是只看车头前那一米的地面。单层静态优化虽然能处理约束也能看到未来但它是一次性算完就不再更新的一旦预测偏差大控制效果就失控。MPC用的是滚动优化每一步算完只取第一个控制量然后再用实时状态做反馈重新预测、重新求解。这就是它名字里“模型预测控制”中反馈校正的含义。2. 系统建模混合储能分工与数学描述2.1 光伏、负荷与电网交互的模型先约定功率方向不然后面代码里正负号会乱。我习惯用这样的规定光伏出力为正负荷消耗为正储能充电功率为正放电为负电网向微电网供电为正向电网送电为负。功率平衡式写成Ppv Pgrid Pbat Psc Pload这里Pbat和Psc可正可负实际就是储能参与平衡的净功率。光伏模型不需要太复杂仿真时直接用给定曲线就行。负荷模型也一样取历史数据或典型日曲线。要额外加扰动的话可以在曲线上叠加一个高频白噪声或阶跃变化。这样做的目的是测试下层的动态响应能力。电网模型主要体现为交换功率限制。比如变压器容量决定了Pgrid上下限如果微电网运行在孤岛状态那Pgrid直接等于0约束变成等式。这是双层模型中一个重要的场景切换开关。2.2 锂电池与超级电容的功率分配混合储能的核心价值是把能量型和功率型储能组合起来。锂电池能量密度高单位能量成本低但它频繁快速充放会严重影响寿命。超级电容功率密度高响应速度快寿命几乎不受充放电次数影响但存不了多少电。所以功率分配的基本思路是让超级电容吃掉功率曲线里的高频毛刺让锂电池承担平缓的整体充放电斜率。工程上最常用的办法是低通滤波。把需求功率P_need经过一个低通滤波器低频部分给锂电池高频部分给超级电容公式就是Pbat LPF(P_need)Psc P_need - Pbat。但光靠低通滤波有个问题它完全不考虑SOC。锂电池快没电了滤波器还是让它出功率最后SOC直接越限。所以更好的做法是把滤波后的结果作为MPC的参考值在目标函数中让实际功率尽量接近参考值同时把SOC偏差作为惩罚项放进优化里。2.3 目标函数与约束条件的数学表达双层MPC里每一步都要解一个优化问题。上层目标函数我习惯写成min Σ( price(k) * Pgrid(k) λ1 * (P_bat_total(k) - P_bat_ref(k))^2 λ2 * SOC_penalty(k) )第一项是买电成本第二项是让储能总功率跟踪计划第三项是SOC越限的保险惩罚。约束条件包括功率平衡等式、Pgrid上下限、电池功率和SOC上下限。下层目标函数和上层不同它不再关心电价而是专注于功率分配和平抑波动。我常用的形式是min Σ( w1 * (P_bat(k) - P_bat_ref(k))^2 w2 * (P_sc(k) - P_sc_ref(k))^2 w3 * (SOC_bat(k) - SOC_bat_target)^2 w4 * ΔP_sc(k)^2 )其中最后一项是为了限制超级电容的功率变化率防止它过度抖动。下层约束包括电池功率限值、电量变化、超级电容功率限值和SOC限值。这套目标函数写成矩阵形式之后就是一个标准的二次规划问题。这也是我选择在Matlab里用quadprog的原因不需要额外装求解器函数原生支持直接构造H矩阵和f向量就能解。3. Matlab实现细节双层MPC的代码结构3.1 总体框架与模块划分整个仿真程序我分成几个文件来写不会全挤在一个脚本里。main.m初始化参数读取光伏/负荷/电价数据启动双层循环存储结果绘图。mpc_upper.m上层MPC函数输入当前状态、预测序列和约束参数输出上层控制决策。mpc_lower.m下层MPC函数输入实时功率需求、SOC状态输出电池和超级电容的功率。model_update.m负责状态更新比如根据控制量计算下一时刻SOC。plot_results.m把仿真结果画出来包括功率曲线、SOC曲线和成本曲线。主循环大概是这个结构for k 1:T_total if mod(k, N_up) 1 % 每个上层周期调用一次上层MPC u_ref mpc_upper(x, pv_pred, load_pred, price, params); end % 每个控制周期调用下层MPC [Pbat, Psc] mpc_lower(x, P_demand_t, u_ref, params); % 更新状态 x model_update(x, Pbat, Psc); endN_up是上层调度周期和控制周期的比值比如上层15分钟一次下层1秒一次那N_up就是900。3.2 上层调度MPC的搭建要点上层MPC的状态变量一般只需要电池SOC控制变量是并网功率Pgrid和储能总功率P_storage。状态空间方程里SOC变化量由储能功率和电池容量决定。构造quadprog输入矩阵时最麻烦的是把未来Np步的所有约束统一写成矩阵不等式。我习惯先把预测模型整理成离散状态空间形式然后循环累加生成预测输出矩阵。代码大致这样function u_opt mpc_upper(x0, pv, load, price, params) Np params.Np; Nc params.Nc; % 构造预测矩阵 % ... % 目标函数H 2*(Model*Q*Model R) H ... f ... % 不等式约束A*u b A ... b ... % 功率平衡等式约束 Aeq ... beq ... lb ...; ub ...; options optimoptions(quadprog,Display,off); u_opt quadprog(H, f, A, b, Aeq, beq, lb, ub, [], options); end这里要特别注意quadprog要求H矩阵严格对称最好在构造时用H (H H) / 2处理一下否则求解器可能报“Hessian must be symmetric”的警告。3.3 下层功率分配MPC实现下层MPC和前者的区别在于控制变量变成了两个P_bat和P_sc而且预测时域短得多。我给的参考值来自上层调度结果加上当前实时功率误差。简单说P_demand u_ref_total (P_need_now - u_ref_total_current)。然后下层在这个总需求下进行混合储能分配。下面是个简化版函数function [Pbat, Psc] mpc_lower(x, P_need, params) % 输入当前SOC、当前需求、参考分配 Np params.Np_lower; u_ref_bat params.u_bat_ref(1:Np); u_ref_sc params.u_sc_ref(1:Np); C ...; % 预测输出矩阵 D ...; % SOC偏差输出矩阵 H params.q1 * (C*C) params.q2 * (D*D); f -params.q1 * C * u_ref_bat - params.q2 * D * (SOC_target - SOC_cur); % 加上功率平衡约束、SOC上下限、功率限值 A ...; b ...; options optimoptions(quadprog,Display,off); u quadprog(H, f, A, b, [], [], lb, ub, [], options); Pbat u(1); Psc u(2); end别把这个当完整代码看主要作用是说明矩阵H和f是怎么拼出来的。实际工程中预测矩阵构造和约束矩阵生成会占据大量代码行数这才是MPC实现里最需要仔细的部分。3.4 滚动优化与状态更新MPC的核心是“滚动”。每个控制周期都执行一次测量/估计当前状态基于预测模型求解未来Np步的优化问题然后把最优序列的第一个控制量作用到系统上下一拍再重复。Matlab仿真里状态更新用差分方程SOC(k1) SOC(k) - η * P_bat(k) * Ts / E_rated充电和放电的效率不同实际代码里要分开写。如果简单处理可以统一用一个充放电效率仿真偏差不会太大但物理上不严谨。还有一点容易被忽略下层MPC执行周期短上层MPC执行周期长。两层之间传递的不是一个静态值而是一组未来的参考轨迹。也就是说上层每15分钟算出来的不是单一功率值而是未来一小时的计划曲线下层在每个控制周期里只从这条曲线上取当前时刻附近的值再叠加实时误差修正。这样即使光伏突然跳变上层还没有重新计算下层仍然有东西可追。4. 参数整定与仿真结果的分析方法4.1 预测时域与控制时域的选择参数整定是另一个大坑。预测时域Np和控制时域Nc的选择直接决定计算量和控制性能。如果上层采用15分钟步长我建议Np至少覆盖4到6小时也就是16到24步。Np太短无法把握电价峰谷和光伏日内规律太长预测精度下降矩阵维度过大quadprog求解时间飙升。Nc可以远小于Np比如Np24Nc6这样只让前几个控制量自由变化后面保持不动能显著降低决策变量个数。下层因为控制周期短Np一般设成5到20步。我在秒级仿真中常用Np10到15。Np过小超级电容来不及出力波动平抑效果差Np过大又容易产生不必要的功率往复让SOC跟着震荡。4.2 权重系数怎么调目标函数里的权重系数w1、w2、w3、w4不同的配比会带来完全不同的行为。我调参的经验是先定框架再细调。先让功率跟踪权重w1、w2为1SOC惩罚权重w3设为0.01功率变化率惩罚w4设为0.1跑一遍看SOC曲线和功率曲线。如果SOC长时间偏离目标就把w3往上调调到SOC曲线能基本回到目标附近但又不至于让功率跟踪变差。如果超级电容功率出现强烈抖动就把w4调大让它的变化率受限。如果电池频繁反向充放说明分层能力不够可以适当提高低通滤波时间常数或者增加上层参考值的平滑度。下表是我常用的一组初始值做仿真时可以以此为起点参数推荐起始值作用Np_upper24覆盖未来6小时Nc_upper6降低决策变量数Np_lower10秒级滚动窗口w1 / w21功率跟踪权重w30.01 ~ 0.1SOC回归权重w40.1 ~ 0.5超级电容变化率抑制4.3 怎么评估控制效果仿真结束后不能只看两张曲线好看。我一般会算几个量化指标。并网功率波动平抑率最直接把系统接入储能后的并网功率标准差和未接储能时的标准差做对比用百分比表示。SOC维持率可以统计仿真时长内SOC处于安全范围内的比例最好接近100%。锂电池SOC如果频繁冲到上限寿命和安全性都会出问题。运行成本就是把每个步长内电网买电费用累加同时考虑储能的损耗模型。注意如果没有电价数据这块只能做相对比较不能当绝对值用。最后画图时建议把以下五条曲线放在同一张图里光伏出力、负荷、电网交换功率、锂电池功率、超级电容功率。再单独画一张SOC变化图。这样一眼就能看出功率分配逻辑是否合理。5. 常见问题与排查技巧实录5.1 QP求解失败或不可行我遇到最多的报错是“Quadratic programming problem is infeasible”。这一般不是控制器本身写错而是约束条件给得太紧或者初始状态就不在可行域里。比如SOC初始值设为95%但上层MPC预计未来几小时光伏很强给电池下了充电指令。充电意味着SOC继续上升而SOC上限约束是90%这个优化问题当然无解。排查思路很简单第一步看初始值是否满足所有约束第二步临时把上下限放宽看看能否解出来能解出来说明约束太紧第三步在目标函数里加松弛变量给SOC越限一个惩罚而不是硬约束这样即便预测稍有偏差优化也不会直接崩溃。5.2 SOC越界与功率震荡仿真跑到中间SOC直接打到上下限通常是因为MPC没有做足够远的预测或者SOC权重太低。只盯着当前几步系统会只顾眼前功率平衡到后面才发现SOC要过界但已经来不及了。解决办法有两个。一是把SOC惩罚项改成非线性程度更高的形式比如SOC偏离目标越远惩罚增长越快。二是加终端约束强制预测时域末尾的SOC落在目标附近比如SOC(Np)和目标SOC的偏差小于某个阈值。终端约束效果很好但要注意别把约束设置得过死否则又会出现不可行问题。功率震荡的问题大多出在下层尤其是超级电容的功率变化率没有被约束。仿真时看起来就是Psc在两三个控制周期内从正的最大跳到负的最大这种高频往复在实际系统里根本没法执行。给Psc加变化率约束或者增加w4权重就能明显改善。5.3 Matlab实现中与quadprog相关的坑quadprog用起来简单但坑不少。最典型的是H矩阵不正定。由于构造矩阵时用的是离散状态空间预测模型如果Q矩阵为半正定且R为零整个H可能变成半正定quadprog会拒绝计算。我的处理方法是给H加一个极小的正则项比如H H 1e-8 * eye(size(H))保证数值上有严格正定性。这样不会改变控制性能但能避免一大堆警告。另一个坑是在循环里反复调用quadprog每次都重新构造稀疏矩阵导致仿真速度极慢。我建议把所有不变的结构矩阵提前算好存到params结构体里循环内只更新与当前状态相关的f向量和b向量。这样速度能提升好几倍。还有一个容易被忽略的点quadprog默认用的算法对于大规模问题不一定快。可以在optimoptions里指定Algorithm,interior-point-convex同时设置MaxIterations和OptimalityTolerance。如果问题规模太大直接把部分约束改稀疏矩阵构造内存占用会小很多。5.4 代码执行慢如何加速双层MPC仿真如果每个步长都做一次完整的二次规划仿真时长可能让你等到怀疑人生。我做了一个15分钟上层、1秒下层、仿真24小时的案例最开始用最笨的写法跑了将近20分钟还不一定能结束。优化之后快了很多。核心操作有四个。第一所有MPC预测矩阵都用稀疏矩阵表示。Matlab对稀疏矩阵的运算在速度上有明显优势。第二上层MPC不需要每步都调用只有到达上层调度周期才重新计算其他时刻沿用上一次的参考轨迹。第三在生成H和f时避免在循环内使用动态增长的向量。提前用zeros初始化好循环里只做索引赋值。第四如果后段仿真只是为了验证算法可以把控制周期从1秒改成2秒甚至5秒。实时响应会差一点但趋势和逻辑不会变用来调参效率极高。6. 工程化落地的几点体会代码跑通以后我最大的感受是仿真里的“完美”和工程里的“能用”之间还有一段不小的距离。模型预测控制确实强但强在假设你知道精确模型而实际系统里光伏预测有误差、通信有延迟、执行器有响应时间。我在实际调参时发现把上层控制周期设成5到15分钟是一个比较平衡的选择。太快了预测信息和计算能力跟不上而且调度指令频繁变化底层的功率分配也跟着乱太慢了光伏突变完全补不上储能压力全堆到下层SOC很容易过界。另外双层结构中上层给下层传参考轨迹时别只传一个单一数值。传一整段预测曲线可以让下层在下一次上层调度到来前有平滑的过渡依据。我在代码里就是这么做的效果比“每个周期只更新一个点”稳定得多。还有一个细节想提醒大家储能SOC的初始值和目标值要跟上层调度的设定保持一致。如果SOC目标设成50%但初始值是80%仿真前几个小时肯定都在努力回归目标后端的功率曲线和成本曲线大概率都偏离正常情况。先让系统运行一段时间进入稳定状态再统计结果才比较有说服力。如果之后要扩展这个项目我建议先把单层MPC跑通再改成双层先把固定负荷跑通再加随机扰动先把并网模式跑通再做孤岛切换。一步步来排查问题会轻松很多。这套框架同样适合加入其他储能类型或者多台机组协调只要下层模型里增加相应状态量和约束矩阵就行。最后再说一个我踩过的坑不要把MPC的所有参数都放到一个巨大的结构体里而不做注释。我有一段时间为了写论文方便把所有参数全堆在init脚本里结果仿真几天后改一个参数都像大海捞针。后来把所有变量按功能模块分组每个参数加一行注释调参效率明显提升。代码能调通不算结束能让别人快速看懂你的代码才是真正把项目做扎实了。