ARTICLE DETAIL

资讯详情

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

基于MPC的混合储能微电网双层能量管理系统设计与Matlab实现

基于MPC的混合储能微电网双层能量管理系统设计与Matlab实现 做电力电子和微电网仿真这块的朋友应该都遇到过类似的困境模型搭得挺像样但一遇到负荷突变或者光伏波动能量管理策略就开始“犯糊涂”——蓄电池出力忽大忽小超级电容要么闲置要么过载直流母线电压波动得让人心里发慌。我去年在做一个光储微电网的课题时也卡在这个坎上后来把控制架构从单层改成基于模型预测算法的混合储能微电网双层能量管理系统才算是把问题理顺。这篇文章就是把那段时间的踩坑经历、Matlab代码实现的完整思路和调参心得整理出来。这套系统说白了就是把微电网的能量管理拆成“上层全局调度”和“下层实时分配”两层上层用模型预测控制MPC去规划未来一段时间的混合储能总出力曲线解决“充多少、放多少”的问题下层根据蓄电池和超级电容的各自特性把总的功率需求实时拆解到两个储能单元解决“谁来充、谁来放”的问题。全文会围绕这个双层架构的原理、Matlab实现的关键模块、仿真结果分析和调参经验展开适合正在做微电网能量管理、混合储能协调控制方向毕设或课题的研究生以及想从仿真进阶到工程实践的工程师参考。1. 为什么非要用“双层”架构混合储能微电网的控制困境先说一个我实际碰到的场景。最初的方案是单层控制也就是用一个MPC控制器同时输出蓄电池和超级电容的功率指令。表面上看好像没什么问题但真正跑起来以后会发现两个储能单元的动作经常“打架”——蓄电池的功率变化速率本身就慢MPC给它分配的功率却是高频抖动的超级电容本该去处理那些瞬态分量却因为控制器优先追求全局经济性被迫跟着蓄电池一起承担稳态出力。这个问题的根源在时间尺度上。微电网里的能量管理需求天然就分成两个层次一层是分钟级甚至小时级的能量平衡决定储能系统在一段时间内该充多少电、该放多少电考虑的是电价、光伏预测、负荷预测、SOC恢复这些“大局”另一层是秒级甚至毫秒级的功率平衡决定的是如果负荷突然跳变、光伏云层遮挡导致出力骤降储能系统怎么在几十毫秒内把功率缺口补上考虑的是响应速度、电压支撑、电流限制这些“细节”。如果把这两个尺度的控制目标放进同一个MPC优化问题里就会出现我刚才说的情况预测时域长了瞬态响应的约束会被削弱预测时域短了全局能量分配又看不到全局。说白了单层MPC解决不了“既要马儿跑得快又要马儿少吃草”的矛盾。双层架构的核心逻辑就是各管一段。上层MPC的运行周期取5分钟做一次滚动优化收益是前瞻性的基于当前SOC、负荷预测和光伏预测规划出未来一个控制时域内混合储能系统的总功率参考值相当于给系统画出一条“大方向”下层控制器可以是MPC也可以是滤波规则的运行周期取100毫秒甚至更快它不管电价、不管SOC恢复只管一件事——把上层给的总功率参考值快速、稳定地分解成蓄电池和超级电容各自的功率目标。这里有个容易忽略的点上层跟下层不是简单的“接力”关系而是“参考修正”的关系。下层在实时分配过程中会把蓄电池的SOC、超级电容的SOC、当前实际的母线电压偏差等状态反馈回上层上层在下一次优化时用这些信息修正预测模型。这种结构其实很像自动控制里的串级控制——内环快、外环慢外环给内环设定值内环反馈给外环做校正。从代码实现角度看双层架构还有一个工程上的实际好处上下层可以独立调试。我先让上层MPC跑通把总功率规划曲线调满意了再去做下层的功率分配策略Debug的时候问题定位也清晰不会像单层MPC那样调了半天不知道是预测模型的问题还是目标函数权重的问题。2. 上层调度层模型预测控制如何规划一天的能量曲线2.1 MPC的核心三件套预测模型、目标函数、约束条件上层的MPC用Matlab实现核心其实就是三件事预测模型、目标函数、约束条件。很多新手上来就急着写quadprog的代码反而忽略了前面这两步最后程序报错都不知道错在哪。先看预测模型。对于上层调度来说我关心的状态量是混合储能系统的整体SOC如果你希望更精确可以分别做蓄电池SOC和超级电容SOC但上层一般用等效SOC就够了、以及负荷和光伏的预测功率。控制量是整个储能系统的总功率P_ess扰动是负荷功率P_load和光伏功率P_pv。系统的离散状态方程可以写成SOC(k1) SOC(k) - eta_c * P_ess(k) * T / E_cap; % 充电时 SOC(k1) SOC(k) - P_ess(k) * T / (eta_d * E_cap); % 放电时注意这里充放电效率的处理方式。我踩过的一个坑是一开始为了贪图方便把充放电效率统一取成了0.9结果SOC曲线在长时间仿真里出现明显的漂移——充进去的电和放出来的电对不上账。后来改成分段处理充电时电流进电池、效率作用在能量上放电时电流出电池、效率作用在SOC的减少量上仿真结果才合理。再看目标函数这是让MPC“聪明”起来的关键。我用的目标函数包含以下几项J sum(P_ess_ref - P_ess).^2 * w1 ... % 跟踪调度计划 sum(SOC - SOC_ref).^2 * w2 ... % SOC维持参考区间 sum(diff(P_ess)).^2 * w3; % 减小功率变化率第一项是让储能总出力尽量跟新能源发电预测和负荷预测算出来的“理想交换功率”一致第二项是SOC的保持项防止储能系统一味的充放导致过充过放第三项是平滑项让功率输出曲线不要毛刺太多给下一层留出执行空间。这三个权重w1、w2、w3的整定我后面专门讲。约束条件里最重要的是储能功率上下限和SOC上下限。功率约束很好理解SOC约束稍微讲究一点——除了硬性的10%到90%我还会加一个“软约束”引入松弛变量sa让SOC尽量待在20%到80%这个舒适区间。原因是硬约束一旦到了边界MPC可能会出现无解的情况仿真直接卡死引入松弛变量虽然会让问题变成软约束优化但解的稳定性好很多。2.2 为什么预测时域和控制时域不能随便选关于预测时域P和控制时域M的选择我试过好几组参数踩过不少坑。先说结论上层MPC的预测时域P可以取12到20步步长5分钟对应未来1小时到1.67小时控制时域M取3到5步就够了。为什么P要取这么大因为SOC的变化是慢变量预测时域太短的时候MPC根本看不到未来的负荷高峰就会在当下“过度出力”等SOC快满了才发现后面有一大波充电需求但已经来不及了。我感觉预测时域长度至少要覆盖负荷和光伏变化的一个完整趋势周期对于微电网来说一般取1小时以上比较合适。控制时域M没必要太大这是很多教材上一句话带过但实际很重要的一点。因为MPC是滚动优化的每5分钟就重新优化一次如果M取到和P一样大求解的决策变量个数就会爆炸quadprog的计算时间会明显增加。实测下来M取3到5步的时候计算结果跟M取10步几乎一样但计算速度快了不止一倍。还有一个小技巧用Matlab实现的时候QP矩阵里的变量顺序直接决定代码的复杂度。我以前习惯把控制量、状态量交错排列结果构造Hessian矩阵和约束矩阵时写了一堆索引容易出错。后来改成先排全部控制量再排状态量逻辑清晰了很多代码也短了一半。3. 下层功率分配层扰动发生时怎么让蓄电池和超级电容各司其职3.1 基于频率分离的功率分配思路先问个问题蓄电池和超级电容的区别在哪有的人会说在能量密度和功率密度但放在控制领域更关键的区别是响应时间常数。蓄电池是能量型器件响应慢高效工作的频带窄频繁充放会严重影响寿命超级电容是功率型器件响应快能承受瞬态大电流冲击。所以下层的核心任务就是“按频率分配”稳态和低频分量给蓄电池瞬态和高频分量给超级电容。但这里有个工程误区——不是简单地用一个低通滤波器把总功率的低频成分滤出来给蓄电池、剩下的给超级电容就行。我之前就是这么做的结果发现母线电压在负荷突变时还是会有明显的波动。后来才意识到问题低通滤波是开环的它根本不知道当前蓄电池的SOC和超级电容的SOC不会根据实际情况调整滤波时间常数。蓄电池SOC如果偏低低通滤波器还是把大功率稳态分量分给它很快就过放了。所以我在下层设计里引入了“自适应分配系数端电压反馈”的方法。基础思路仍然是一个一阶低通滤波器alpha exp(-Ts / (T_filter * k_adaptive)); P_bat_lpf alpha * P_bat_lpf_last (1 - alpha) * P_ess_ref; P_uc_ref P_ess_ref - P_bat_lpf;这里的T_filter是基础滤波时间常数k_adaptive是自适应系数。当超级电容SOC接近上限或下限时k_adaptive会增大让滤波时间常数变大更多的功率分量被分给蓄电池当蓄电池SOC接近边界时k_adaptive会减小让高频成分更多地分给超级电容。3.2 下层MPC和滤波法到底哪个好关于下层用MPC还是滤波法我自己的体会是如果只要求母线电压稳定滤波法配合SOC反馈完全够用代码短、调试快、鲁棒性好如果课题需要体现“先进控制”的亮点或者存在强耦合约束比如母线电压和储能电流都需要精确限制的时候下层也可以用MPC。下层MPC的模型跟上层的区别在于状态量是蓄电池SOC、超级电容SOC和母线电压偏差udc控制量是蓄电池功率Pb和超级电容功率Puc目标函数是让Pb跟踪低频分量、Puc跟踪高频分量同时把母线电压偏差压到最小。预测时域P取10到20步步长100ms对应未来1到2秒控制时域M取2到3步。这里有一个我在代码实现里觉得特别容易出错的地方下层的控制步长是100ms但上层传给下层的总功率参考值P_ess_ref是5分钟一个值的离散序列。如果直接在Simulink里用一个零阶保持器Zero-Order Hold把P_ess_ref从5分钟插值成100ms的数据会让下层在一个MPC周期内拿到的参考值始终不变看起来没问题但上层更新参考值的那个瞬间下层会感受到一个阶跃扰动。如果你下层的控制器调节能力弱这个阶跃就会体现在母线电压上。解决办法是在上层输出和下层输入之间加一个斜坡限幅器把阶跃变成斜坡给下层一点“反应时间”。3.3 蓄电池和超级电容的SOC均衡问题混合储能还有一个容易忽略的细节SOC的“均衡”问题。这里说的均衡不是指两个储能单元的SOC要一样高——蓄电池和超级电容的容量差了好几个数量级SOC本来就不可能一样。真正的均衡是让两个单元都在各自舒适的SOC区间内工作蓄电池SOC尽量维持在30%到80%超级电容尽量维持在20%到90%。我遇到过一个比较头疼的情况仿真跑很久之后超级电容的SOC会慢慢漂移到边界附近。原因是滤波器分配的功率高频分量虽然是双向的但如果负荷和光伏的扰动存在不对称性比如负荷增加的时间远大于减小的高频分量的均值就不是零超级电容就会持续单向充电或放电。解决方法是在自适应滤波里加一个“SOC恢复项”。具体做法是如果超级电容SOC偏离50%比较多就把它作为一个附加的功率修正项叠加到分配结果上。修正量的大小用PI控制来算soc_err SOC_uc - SOC_uc_ref; P_restore Kp_uc * soc_err Ki_uc * integral(soc_err);然后把P_restore从超级电容的功率目标中减去相当于让超级电容“先还债再干活”。这个修正项的带宽要设置得很低别影响正常的功率分配实测下来把Kp取0.02、Ki取0.001左右超调的修正过程会持续十几分钟但超级电容的SOC能平稳回到参考值附近。4. Matlab代码实现的几个关键模块与易错点4.1 双层MPC的程序架构与文件组织如果你准备用纯m脚本做这个系统而不是完全依赖Simulink我建议把程序分成四个模块数据初始化模块、上层MPC模块、下层分配模块、仿真循环模块。文件结构大概是这样的% main_microgrid.m - 主程序 % init_params.m - 系统参数、MPC参数初始化 % mp_upper.m - 上层MPC求解函数 % mp_lower.m - 下层功率分配函数 % plot_results.m - 结果绘制函数主循环里的核心逻辑是这样for k 1:N_sim % 1. 更新当前时刻的负荷、光伏功率可以读取实际数据或由模型生成 P_load_cur load_profile(k); P_pv_cur pv_profile(k); % 2. 判断是否到达上层MPC的执行周期比如每300个仿真步执行一次 if mod(k, N_upper_step) 0 [P_ess_ref_sequence] mp_upper(SOC_ess, P_load_forecast, P_pv_forecast); end % 3. 从上层MPC结果中取当前时刻的总功率参考值 P_ess_ref P_ess_ref_sequence(1); % 4. 调用下层分配函数得到Pb_ref和Puc_ref [Pb_ref, Puc_ref] mp_lower(P_ess_ref, SOC_bat, SOC_uc, Vdc_cur); % 5. 更新储能系统状态微分方程离散化或用Simulink模型 ... end这个结构的一个好处是上下层的执行周期解耦你可以在init_params.m里单独设置N_upper_step 300对应5分钟100ms步长而不用改其他代码。我最初把上层MPC的执行频率设成每次循环都算结果仿真一个24小时场景要跑将近20分钟后来改成5分钟一次计算时间降到了2分钟以内而且控制效果差异几乎可以忽略。4.2 quadprog求解器的参数配置与常见报错Matlab的quadprog是内点法实现对中小规模QP问题足够用。常见报错和解决方法我这里总结一下。最常碰到的是“Quadratic objective must be positive semidefinite”或者“Hessian matrix must be symmetric”。这个问题的根源十有八九是构造H时矩阵不对称或者目标函数里含有了二次项之外的非标准形式。解决方法是每次构造完H后强制对称化H_upper (H_upper H_upper) / 2;还有一个容易忽略的点是quadprog默认输出的解可能不满足你的SOC约束特别是当约束矩阵较大时内点法可能会轻微越界。我建议求解完之后对SOC结果做一个后处理校验如果越界就给出警告并做投影修正。这个虽然不严谨但在仿真里比让MPC“硬解出无解”而中断程序要实用得多。另外如果你在Matlab R2022b之后运行quadprog的算法选项里有Algorithm可以选interior-point-convex默认和active-set。对于MPC这种需要反复求解的场合我发现默认的内点法反而更稳active-set在初始点不好的时候偶发求解失败。所以别折腾直接用默认就好。4.3 状态空间模型离散化时的Big-M问题在双层MPC的代码实现里还有一个细节我花了很多时间才注意到——充放电效率的分段处理会导致模型不连续这在MPC里是个隐患。上层的SOC状态方程充电和放电是两个不同的表达式但quadprog只能解连续的二次规划不能直接处理这种“分段切换”。解决方法是引入Big-M法把“充电”和“放电”分别表示成约束分支。具体来说引入一个二进制变量delta当P_ess0时delta1否则delta0然后约束写为-P_ess M * (1 - delta); % 若delta1则P_ess0被允许 P_ess M * delta; % 若delta0则P_ess0被允许 SOC(k1) SOC(k) - (eta_c * delta (1-delta) / eta_d) * P_ess * T / E_cap;不过这会让问题变成一个混合整数二次规划MIQP求解时间会显著增加。我实际用的时候做了一个简化这是我觉得比较实用的处理技巧干脆忽略充放电效率的切换把充放电效率统一取一个数值SOC计算公式改成统一形式。因为在上层调度的时间尺度上SOC的慢动态对大效率差异并不敏感这种简化引入的误差很小但避免了MIQP的求解负担。如果课题需要更精细的SOC模型可以再单独写一个SOC校正模块做后处理。5. 仿真结果怎么看三个典型场景的曲线分析5.1 光伏平稳、负荷阶跃场景第一个典型场景是光伏出力平稳傍晚时分负荷突然从50kW跳到80kW。这种情况下上层的MPC应该在一两个周期内就给出响应——因为SOC还有充足空间MPC会提前增加储能放电功率让负荷突变带来的功率缺额尽量由储能来承接而不是让微电网跟大电网的交换功率突然波动。我在看仿真曲线的时候有个习惯先看母线电压波形再看储能功率分配。母线电压在负荷阶跃的瞬间出现一个小尖峰是正常的关键是尖峰后的恢复速度。PID控制下的恢复时间通常在几十毫秒到几百毫秒之间MPC控制下恢复时间会更短而且几乎无超调。5.2 光伏骤降场景第二个场景更有意思云层遮挡导致光伏出力在10秒内从60kW掉到20kW。这种情况下上层MPC的预测模型中如果包含了对光伏的预测更新就能提前在下一轮优化中调整储能计划但在10秒的尺度上上层根本来不及响应这时候全靠下层。超级电容在这个场景里价值完全体现出来了40kW的功率缺额瞬间出现如果让蓄电池单独扛蓄电池的功率变化率限制会让母线电压在过渡期内掉得比较多而超级电容从零到满功率输出只需要几十毫秒哪怕蓄电池还没反应过来母线电压已经稳住了。等蓄电池的功率慢慢顶上来超级电容的功率又会自动降下来切换过程非常平滑。这个场景我觉得是最能体现“混合储能”价值的一个测试案例。5.3 连续波动场景下的SOC轨迹分析第三个场景是负荷和光伏都带有持续随机波动。这种场景下的目标就是两种储能都不能“越界”。我在仿真里给超级电容设了SOC上下限是5%和95%蓄电池是20%和90%。跑完24小时场景之后我会重点检查两个SOC轨迹有没有触到边界。如果超级电容经常触到上限说明滤波时间常数取得太小高频分量偏多如果蓄电池的SOC变化太剧烈、曲线毛刺很多说明下层分配给蓄电池的功率分量还是带了不少高频成分。这两个都是调参的信号而不是“系统不行”的信号——我前几次做的时候看到SOC触界就想着改约束后来才意识到应该改滤波参数。另外把上下层的控制效果分开检查是一个比较好用的排查手段。我一般先把下层MPC的输出直接断开——只用滤波法分配功率跑一遍记录母线电压波动范围然后接上下层MPC跑一遍再对比同一段波动场景。如果差异不大说明问题不在下层如果差异明显才需要深挖下层的MPC目标函数和权重。6. 调参与实战经验控制器参数、时间尺度、状态量设计6.1 上层MPC权重矩阵的整定顺序关于MPC的权重网上有很多原理性描述但真正调起来是有顺序的。我的经验是先调SOC保持项的权重再调节能功率跟踪项的权重最后调功率变化率的平滑项权重。第一步把SOC参考值的权重调大比如w2100其他权重调很小跑一遍仿真看SOC曲线是否平顺、是否贴着参考值走。这一步验证的是MPC预测模型本身是否正确——如果SOC曲线连参考值都跟不好说明状态方程有bug后面调什么都白搭。第二步逐渐增大功率跟踪项的权重w1让储能总功率的曲线跟上调度计划。第三步再增加平滑项权重w3去除功率曲线上的高频毛刺。每一步都有明确的“检查信号”不至于三个权重一起调的时候互相干扰、无从下手。实测下来当我用P15、M4、w11、w210、w30.5时仿真效果比较理想。注意w3不能太大太大以后功率变化率被过度限制储能会显得“反应迟钝”负荷突变后母线电压波动会更明显。6.2 状态量设计里的小坑SOC要不要归一化关于状态量的设计有一个细节直接关系到MPC求解的数值稳定性——SOC的量纲。SOC通常在0到1之间储能功率P_ess的量纲可能是kW甚至MW两者数值差了好几个数量级。如果直接用这两个量进QPHessian矩阵的条件数会很大quadprog虽然一般不会解不出来但求解精度会变差优化结果可能会出现功率曲线的微小抖动。我的做法是对各物理量做归一化后再进MPCSOC_norm SOC / SOC_max; P_ess_norm P_ess / P_ess_rated;这样所有变量的数量级都落在0到1之间Hessian矩阵的条件数大大改善求解速度更有优势。6.3 关于极端工况的鲁棒性测试建议最后一条建议也算是我做这个课题最大的教训一定要做极端工况测试别只跑“设计工况”。我第一次做这个系统所有参数都是按正常负荷和光伏波动来设计的仿真效果看起来很漂亮。结果有一天我在调试时不小心把负荷数据里加了一个突然从满载瞬间掉到10%的空载突变系统瞬间“傻眼了”——上层MPC给的储能功率参考值在下一轮更新前保持不变而下层在这个极端功率缺口下疯狂动作母线电压跌了一个很离谱的数值。如果你也想避免这个问题建议在验证阶段加入三组极端场景负荷骤变、光伏骤变、SOC接近边界的组合工况。测试的时候重点关注母线电压的峰值偏离和恢复时间这两个指标能直接反映你的系统有没有“留有余量”。这些极端工况不一定要在最终汇报时全部放出来但作为自测是必须的。另外关于Matlab仿真时间步长的选择我建议在100ms和1s两个档位分别测试一遍。100ms适合用来观察瞬态过程但24小时级别的场景仿真如果步长100ms循环次数会有86万次在笔记本上跑下来非常吃力。我的做法是调试阶段用100ms步长、跑短时间的高分辨率场景比如60秒确认响应特性验证阶段用1s步长跑24小时看SOC和能量指标。两种步长下的系统整体表现一致的话说明你的代码在时间尺度上逻辑是对的。这个项目的代码实现和调参经验就先分享到这里。如果你也在做类似的微电网能量管理工作欢迎交流你在双层架构里是怎么处理上下层时间尺度衔接的或者你有没有遇到过比SOC漂移更让人头疼的问题。
返回列表