☰
模型预测控制(MPC)在微网储能优化调度中的工程实践
2026/10/19 18:08:58 网站建设 项目流程

1. 先说清楚:微网储能优化到底难在哪

微电网这个词这些年听得很多,但真正上手做过能量管理系统(EMS)的人都知道,难点不在设备选型,不在通信组网,而在“怎么把能量调度这件事做聪明”。光伏出力随风飘、负荷一天几个尖峰、峰谷电价又在那里明晃晃摆着,储能系统夹在中间,充也不是、放也不是。如果你只会写几条固定规则,比如“光伏大于负荷就充电、电价峰时放电”,那大概率会出现两种情况:要么储能整天闲着,要么电池用不了两年就衰减得没法看。

我最早接触这类项目时,某园区微网配了一套2兆瓦时的磷酸铁锂储能,甲方给的诉求很直白:让光伏尽量自用,躲开高价电,同时别把电池搞坏。听起来很合理,但真到做策略的时候,问题就来了——今天中午光伏大发,可明天上午才是真正的电费高峰,你是今天把电存满,还是留着容量给明天?如果只看当前时刻,永远做不出这种跨时间的取舍。后来我把策略从“规则判断”换成“模型预测控制(MPC)”,效果完全不一样,储能利用率上去了,电费账单也明显降下来了。

这篇我就把自己做模型预测储能优化时的一些思路、公式、代码和踩坑记录摊开讲。适合的对象是正在做微网EMS、储能系统控制、或者想从固定策略转向优化控制的工程师,也适合想搞清楚“预测控制到底怎么落地”的入门者。不用你有很强的优化理论底子,但最好会一点Python和线性规划的基本概念。

2. 为什么规则控制干不过模型预测

2.1 储能调度的本质是一个“带约束的时序决策”

把微网能量管理看成一个数学问题,其实很清晰:未来24小时里,每个时刻我要决定储能充多少、放多少、电网买多少,目标是电费最低,同时要满足负载、电池容量、功率限制等一堆条件。这跟“今晚吃什么”不一样,它不是一次性选择,而是一连串互相影响的决策——今天晚上多充了10度电,并不意味着明天就一定赚,因为电池容量就那么大,你可能因此装不下明天早上的便宜电。

储能调度的核心矛盾就在这里:它既是空间问题(各个设备的功率怎么分配),又是时间问题(今天的选择会影响明天的收益)。规则控制本质上是一堆“如果-那么”的映射,它没有全局优化的能力,只能按当前状态做局部反应。你写“电价大于1.2元就放电”,但如果放电之后电价继续涨,提前放完就是亏的;如果一个小时内电价涨了三次,固定阈值策略永远慢半拍。

2.2 规则控制的具体痛点

我在现场见过很多典型的规则策略,也测过它们的实际效果,问题基本集中在几个方面:

  • 不具备预见性:规则只看当前测量值,对未来的光伏突变、负荷高峰没有预判。某天上午阴天,规则判断“不充电”,结果下午突然出太阳,光伏大发,电池容量是空的,白白浪费了清洁电力。
  • 容易触发振荡:阈值附近反复启停,导致储能PCS频繁切换充放电状态。一次两次没问题,一个小时内来回折腾十几次,对设备寿命和并网电能质量都是打击。
  • 多目标冲突处理不了:既要削峰填谷,又要防电池过充,还要响应需求响应信号,这些目标经常打架。规则只能靠优先级强行排序,结果要么牺牲收益,要么牺牲安全。
  • 参数调起来要命:什么时段充、充多少、转换阈值设多少,全部要靠经验拍脑袋。换一个季节、换一批负荷,原来的参数又不好使了。

2.3 模型预测控制为什么对路

模型预测控制的核心就八个字:模型预测、滚动优化。每一轮控制周期到来时,我先基于预测模型算出一个未来N步的最优充放电计划,但只执行第一步,等到下一个周期,再根据最新的实测数据重新预测、重新优化。这就像开车时边走边看地图,而不是出发前把全程路线定死。

这样做的好处是,它天生具备前瞻性,能看未来,又能用实时反馈纠偏,能抗预测误差。MPC也不是什么新东西,工业过程控制里用了好几十年,但过去没在微网里普及,主要原因是算力和求解器不方便,现在这些问题都解决了。

3. 储能优化MPC的核心设计思路

3.1 第一步:把微网设备模型写清楚

做MPC先得有模型。微网里最常见的几个设备:光伏、储能电池、PCS变流器、负荷,外加一个和外部电网连接的关口计量点。设备模型不需要特别精细,但关键物理关系必须准确。

储能的核心是电池电量SOC递推关系。离散化之后可以写成:

E(k+1) = E(k) - P_bat(k) * dt * eta_d - P_bat(k) * dt / eta_c(充放电分情况)

实际建模时我喜欢用互补拆分的办法,把充电功率和放电功率拆成两个非负变量,再加一个互斥约束,这样避免出现“既充又放”这种数学上可行、工程上荒谬的解。电池的功率上下限、SOC上下限也要写成约束。

光伏在MPC里通常当成一个负的负荷,或者说一个给定的功率注入序列。每个时刻光伏功率是预测值,不需要建模成决策变量,除非你还要做降功率控制。负荷同样处理成已知量,作为功率平衡方程右侧的常数项。

功率平衡是整条约束链的锚点:

P_grid(k) + P_pv(k) + P_bat_dis(k) = P_load(k) + P_bat_ch(k)

3.2 第二步:目标函数怎么定

目标函数非常关键,直接决定优化的方向。最常见的目标是最小化运行成本:

J = sum( price(k) * P_grid(k) * dt ) + battery_penalty

价格是外部的分时电价或者需量电价:如果按需量计费,目标里还要加入“月最大需量”这一项,比如把max(P_grid)变成一个线性近似的松弛变量,或者用一个软约束把它压住。这部分我建议的简化做法是:分成电能量费用和需量超标惩罚两项,用权重系数去平衡。

电池损耗项要不要加?我个人的建议是加,但不要加得太重。用一个与充放电功率绝对值成正比的损耗惩罚,或者用一个简单的吞吐量惩罚,可以防止MPC为了省电费让电池疯狂调度。注意惩罚系数过大会让储能干脆不动,过小又会让电池过度磨损,这个系数只能靠仿真和现场试验来定。

3.3 第三步:约束条件逐条列干净

约束条件我习惯逐条检查,每少一条,将来现场就要出一次问题。最常见的几类约束:

  • 电池SOC上下限,一般取10%~90%,防止过充过放。
  • 电池功率上下限,由PCS容量和电池倍率决定。
  • 功率平衡等式,不下等于电网功率可能无限大,直接失去优化意义。
  • 关口功率限制,这是很多微网并网验收的硬性指标,可以用不等式约束加上限。
  • 充放电互斥,防止出现同时充放的情况。

有些朋友一开始把约束写得太宽松,比如忘了加SOC末端约束,结果求解器给出一个极端方案:前半夜拼命放电,到最后一个时刻正好放完,看起来电费最低,但第二天早上电池是空的,完全没法用。所以我在优化里一定会加末端约束:每个优化周期的最后一步,SOC要回到一个合理范围,或者至少不低于设定值。这样前后周期才能衔接起来。

4. 预测部分怎么做:光伏、负荷、电价的实战处理

4.1 光伏出力预测:数值天气预报加相似日修正

MPC算得再好,预测不准也是白搭。光伏预测的误差来源主要就是云层变化和温度,晴天模型很简单,难的是多云天,光照曲线毛刺特别多,预测值和实际值能差40%以上。

我目前在工程上常用的做法是“三层结合”:第一层用数值天气预报的辐照度数据做基准,折算到光伏阵列倾角下的有效辐照;第二层用过去两周的历史出力数据训练一个简单的机器学习模型,比如随机森林或者轻量梯度提升树,把辐照、温度、湿度、时刻都作为特征;第三层加一个实时修正模块,用上一小时的实测出力PV测,对当前时段的预测值做残差补偿。

pred_pv(k) = clamp( model_output(k) + alpha * (last_measured - last_predicted), 0, P_pv_cap )

这个修正系数alpha是一个经验值,我一般取0.3~0.5,调得太大会跟着噪声抖,太小又起不到纠偏作用。

4.2 负荷预测:工作日和休息日必须分开

园区负荷一般有很强的周期性。工作日白天八九点开始爬坡,中午一个峰值,下午又一个峰值,晚上回落;休息日负荷低得多。如果只用同一个模型,误差很难看。所以我在做负荷预测的时候,第一步不是建模,而是先把历史负荷按“工作日/休息日/节假日”分桶,每个桶里再分别做预测。

特征方面,时刻、星期几、前三个时刻的实测负荷、温度,这几个就够用了。有个容易被忽略的点:负荷预测也需要“滚动修正”,但和光伏不同,负荷修正不要用线性残差,因为滞后性太强,我更喜欢用最近一小时的平均误差来做慢速修正,效果平滑不少。

4.3 电价序列:直接从市场化交易平台对接

如果微网参与的是分时电价,那电价序列可以直接从市场化平台接口拿到,这没什么好预测的。但如果电价是实时的、波动很大的现货价格,就得上电价的短期预测,常见的有自回归模型、向量自回归或者时序神经网络,特征里可以加前几天的同一时刻价差。

有个工程技巧:把电价预测的结果转成“相对电价”,也就是每个时刻电价除以全天平均电价,然后用到目标函数里。这样做的好处是,即便预测的整体水平有系统性偏差,优化结果依然偏向于在相对低价的时段充电、高价的时段放电,鲁棒性好很多。

5. 滚动优化的求解落地:从理论到能跑的代码

5.1 求解器选型:不一定要上重型武器

很多初学者一上来就想用复杂的非线性求解器,其实储能MPC绝大多数情况下是线性规划或者混合整数线性规划,完全可以用开源工具求解。我自己的习惯是先把问题线性化,再用一个轻量级的求解器跑。只有在考虑了PCS效率随功率非线性变化、或者要做电池寿命非线性建模时,才考虑换成非线性求解器。

工程上用下来,Gurobi和Cplex自然是性能标杆,但开源方案也完全够用。我个人比较推荐用Python的CVXPY建模,后端可以无缝换求解器,调试起来非常方便。下面是简化的储能MPC优化代码,可以跑通一个基础版本:

import cvxpy as cp import numpy as np T = 24 dt = 1.0 E_max = 100.0 # 电池容量 kWh P_bat_max = 30.0 # 功率上限 kW etas = 0.95 # 充电效率 etad = 0.95 # 放电效率 E0 = 50.0 E_end_min = 40.0 # 预测序列:来自预测模块 pv_pred = np.array([...]) # 24小时光伏功率预测 load_pred = np.array([...]) # 24小时负荷功率预测 price = np.array([...]) # 24小时电价 # 决策变量 p_grid = cp.Variable(T) p_ch = cp.Variable(T, nonneg=True) p_dis = cp.Variable(T, nonneg=True) e_bat = cp.Variable(T) constraints = [] # 功率平衡 for k in range(T): constraints.append(p_grid[k] + pv_pred[k] + p_dis[k] == load_pred[k] + p_ch[k]) # 电池SOC递推 for k in range(T-1): constraints.append(e_bat[k+1] == e_bat[k] - p_dis[k]*dt/etad + p_ch[k]*dt*etas) constraints.append(e_bat[0] == E0) constraints.append(e_bat[T-1] >= E_end_min) # SOC上下限 constraints.append(e_bat >= 10.0) constraints.append(e_bat <= E_max) # 功率上下限 constraints.append(p_ch <= P_bat_max) constraints.append(p_dis <= P_bat_max) # 充放电互斥 M = P_bat_max * 10 u = cp.Variable(T, boolean=True) constraints.append(p_ch <= M * (1 - u)) constraints.append(p_dis <= M * u) # 目标:最小化购电费用,加轻微的电池损耗惩罚 objective = cp.Minimize(cp.sum(price * p_grid * dt) + 0.01 * cp.sum(p_ch + p_dis)) prob = cp.Problem(objective, constraints) prob.solve(solver=cp.SCIPY)

这里需要注意,充放电互斥用了大M法和二进制变量,求解速度会比纯线性规划慢一点,但安全系数高很多。如果不加互斥约束,有时候优化结果里会出现同时充电又放电的情况,虽然功率平衡等式依然成立,但能源白白浪费了,目标函数值也比真实可执行方案更低。

5.2 控制周期怎么选:5分钟还是1小时

控制周期和预测周期是两回事。预测周期一般取15分钟到1小时,控制周期(也就是滚动优化的触发频率)建议比预测周期短。我常用的组合是:预测步长15分钟,预测范围24小时,每5分钟触发一次重新预测和重新优化。这样做的好处是,5分钟内如果光伏突然被云遮了,系统能快速反应,不用白白等满15分钟。

不过触发频率越高,计算压力越大。如果一个预测范围是96步(15分钟×24小时),加上二进制变量,CVXPY每次求解一般要几百毫秒到几秒,完全够用。但如果整个微网里的储能系统有几十台PCS,变量数量会暴涨,这时候建议把多个储能聚合成一个等效储能模型来优化,算完再做功率分配,速度能提升好几个量级。

5.3 与EMS系统的集成方式

MPC算法本身不是终点,部署到现场时最核心的是数据链路。我见过太多算法在仿真里分数漂亮,一到现场数据不对齐就崩溃。最常见的三个坑:

  • 数据时标不对齐:光伏功率、负荷、SOC来自不同采集终端,各自有几十秒到几分钟的延迟。你在做预测和优化前,必须把所有数据统一重采样到一个时间序列上,不然预测模块拿到的输入是错位的,优化结果必然跑偏。
  • 控制指令闭环:MPC算出来的计划要下发到PCS,但执行机构不一定能精确跟踪。比如你下发30千瓦充电指令,实际PCS只执行了27千瓦,如果优化模块不读取实际值来更新状态,误差就会不断累积。所以每次优化开始前,必须先同步一次真实的SOC和功率状态。
  • 安全约束需要双重保险:MPC算出的极限值不能直接当成控制指令发给设备。因为数模一定存在误差,比如电池SOC中间点预测不准、通信掉线导致指令没执行,这些情况一旦发生,极限指令就可能把设备推向危险边界。更稳妥的做法是:MPC计算出一个“目标值”,然后现场PLC再根据硬保护逻辑对目标值做限幅校验,两层保险。

6. 常见问题排查与参数调优速查

6.1 问题一:优化结果一直逼着电池放电,SOC很快就见底了

这个百试百灵,十有八九是目标函数和末端约束没配合好。检查两个地方:第一,目标函数里电价有没有取对方向,如果电价序列符号反了,优化会专门挑贵的时候放电;第二,末端约束是否在任何时刻都存在。如果你只在每天的最后一个周期约束SOC>20%,那从最后一天倒数第二个周期开始,优化就会觉得“反正明天要清零,现在赶紧放完”,造成一整晚SOC趴在底线上。

我现在的做法是让末端约束跟随时间移动:每一轮优化都要求最后一个时刻的SOC不小于当前时刻SOC减去一个允许的下降幅度,这样就天然限制了“自杀式放电”。

6.2 问题二:求解时间太长,控制周期内算不完

这种情况通常出现在把预测范围拉太长、步长太短的时候。96步加二进制变量,求解时间可能到了几秒以上。如果控制周期是5分钟还好,如果是1分钟就危险了。

我的排查顺序是:先看看是不是二进制变量太多。如果不是必须要严格避免同时充放,可以把互斥约束去掉,转成纯LP问题,求解速度能提升十倍以上。还有一个技巧是分时段方案:前4小时用细粒度步长,后20小时用粗粒度步长,把问题规模压下来,效果几乎不变。

6.3 问题三:预测误差一大,储能实际收益还不如规则控制

这是个“千万别以为模型万能”的教训。MPC的竞争力建立在预测质量之上,如果预测误差太大,滚动优化再做得好也没用。解决思路有两个方向:一是提高预测精度,二是提高策略鲁棒性。

鲁棒性方面,我比较常用的是“场景法”:做优化时不只用一个确定性预测,而是同时生成三个场景——乐观场景、基准场景、悲观场景。目标函数取三个场景下的加权总成本,权重可以按历史误差分布来设定。这样做会让优化结果偏向于“不管哪种情况都不太差”的方案,牺牲一点最乐观收益,但换了整体上的稳定性。实测中,这类鲁棒化处理让现场月度电费账单波动小了很多。

6.4 一个实际项目的数据对比

我在某园区的2兆瓦时光伏配储项目上做过一组对比测试,连续跑了一个月。规则策略用的是峰谷分时充放电,MPC用的是一天24小时预测、每5分钟滚动优化。对比结果大概是这样的:

指标固定规则策略MPC策略
月度电费节省1.2万元1.9万元
储能等效循环次数1.9次/天2.4次/天
光伏自发自用率78%86%
计划外充放电切换次数每日平均5次每日平均0.8次

电费节省将近60%的提升,自用率也上去了,关键是充放电切换次数大幅下降,这对设备寿命是一个很大的加分项。甲方看重的是钱和电池寿命,工程师看重的是系统稳定,这组数据两者都照顾到了。

7. 调试和部署过程中的一些个人经验

7.1 仿真闭环与现场闭环是两个世界

我再强调一次,代码跑通和现场稳定运行是两回事,强烈建议先在纯软件环境里做三件事:数据回放测试、故障注入测试、指令跟踪误差测试。回放测试就是把历史数据重新喂给MPC,看它算出的方案和当时的实际方案对比,能快速暴露模型写错的地方。故障注入测试就是模拟通信中断、光伏骤降、负荷跳变这些异常,看MPC会不会算出离谱的功率指令。指令跟踪误差测试是看PCS实际功率相比指令偏差多大,再根据偏差修正模型里的设备参数。

7.2 参数不能一套用到黑

不同季节的光照、负荷、电价特征差异非常大。我建议把MPC的权重参数分成两套配置:一套是春秋过渡季用的,光伏温和、负荷平稳;另一套是夏冬紧张季用的,光伏波动大、峰谷差大。换季的时候不是改代码,而是把配置文件切换一下,这样既不打断运行,又能适应新的环境。

7.3 别忘了记录每一轮优化结果

有时候现场运行出问题,你想复盘都无从下手。因此我强烈建议,MPC每次优化完成后,把预测序列、优化结果、实际执行结果三份数据落到本地数据库或者文件中。等出了偏差,直接对比这三份数据,很快就能定位是预测错了、优化约束没写对,还是执行机构出了问题。这一步看着不起眼,但真的能帮你少加几个星期的班。

微网储能优化没有唯一的标准答案,模型预测算法也不是包治百病的万能药。但经过这两年的项目实践,我个人的体会是,它确实是目前工程落地中性价比最高、最能把储能“用起来”的方案。比起一上来就想堆深度学习、堆强化学习,还是先把MPC这套滚动优化的基本功做扎实更实在。希望这篇文章里的思路和踩坑记录,能帮你少走一些弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询