共享储能电站日前优化调度:MATLAB+Yalmip建模与求解实战
发布时间:2026/9/26 7:33:10来源:尧图网络
我做了很久工业用户侧的储能优化项目发现一个扎心的现状很多工厂电费账单里峰谷价差带来的浪费比大家想象中大得多但是让单个工厂掏几百万自建储能很多老板又下不了决心。共享储能电站模式的出现相当于把一个大型储能“切”成容量包多家工业用户合着用成本均摊、容量共享。但是问题紧接着就来了共享储能到底什么时段充电、什么时段放电、每个用户分多少功率这些都得提前一天排好这就是日前优化调度。我用MATLAB配合Yalmip工具箱把这套调度逻辑完整跑通了下面把建模思路、程序实现、算例效果和踩坑经验一次讲清楚给正在做储能调度研究或者准备上共享储能项目的朋友做个参考。1. 共享储能电站对工业用户的价值先算清这笔账1.1 峰谷价差里藏着多大的利润空间工业用户执行的一般是分时电价很多地区把一天24小时分成尖峰、峰、平、谷四段。以典型大工业电价为例尖峰时段约1.25元/kWh峰时段约1.0元/kWh平时段约0.65元/kWh谷时段约0.32元/kWh。峰谷价差接近0.93元尖峰和谷段的价差甚至超过0.9元。储能的核心盈利逻辑就是“低充高放”谷时段给储能充电每度电0.32元峰时段放出来给产线用抵掉1.0元的购电成本。减去充放电损耗和运维费用一次循环每度电净赚0.5元左右。一台200kW/800kWh的储能柜一天完整充放一次理论毛利就有400元如果每天能循环1.5次一年下来利润相当可观。不过这只是静态测算。实际情况中储能什么时候充、充多少、什么时候放、放多少受负荷曲线、电价时序、变压器容量、电池SOC边界等多重因素制约必须靠优化模型来排决策这就是日前调度存在的意义。1.2 自建储能和共享储能怎么选很多工业园区里单个工厂的负荷曲线是“窄而尖”的白天两班倒负荷冲得很高晚上只有照明和保温负荷几乎趴地。自建储能时电池容量必须按自己的峰值需求来配非高峰时段大量容量闲置利用率很低。而且自建储能涉及场地、消防设计、并网审批、后期运维小工厂很难养得起专职电池工程师。共享储能的思路不同运营商建设一个集中式储能电站把容量切成若干“共享包”工业用户按需租赁。不同用户的负荷曲线往往具有互补性——机械加工厂白天重负荷冷链仓库夜间持续耗电化工厂三班倒负荷平稳。大家共用一个电池堆运营商统一调度把容量在不同用户之间腾挪整体利用率显著高于单用户自建。对工业用户来说共享模式最直接的收益是不需要一次性投入巨额建设成本也不需要承担电池衰减和运维风险只需按月支付容量租赁费或按放电量付费。这相当于把固定投资变成了运营支出财务压力小很多。但代价是你能不能用上电、电价省多少全看运营商的调度策略好不好。这个背景下日前优化调度算法就成了共享储能电站的“大脑”。1.3 日前优化调度解决什么问题日前调度简单说就是基于第二天的负荷预测曲线和已知的分时电价提前24小时决定储能系统每个小时的运行状态充还是放、功率多大、给每个用户分配多少放电功率。目标可以设定为系统总运行成本最小也可以延展到兼顾电池寿命、用户用电满意度等。这个问题的难点在于储能本身有容量限制、功率限制、SOC连续性约束充放电不能同时进行多个工业用户的负荷需求各不相同共享储能的放电功率需要合理分配电价随时间变化决策有显著的时段耦合效应。这些问题叠加在一起本质上是一个多时段、多用户、带二进制变量的优化问题用MATLAB建模求解正好合适。2. 日前优化调度模型目标函数与约束条件拆解2.1 变量定义与时间尺度我把调度周期设为一天24小时时间分辨率取1小时离散时段编号 (t1,2,...,24)。工业用户集合记为 (i1,2,...,N)每个用户拥有独立的负荷预测曲线 (P_{load}(i,t))单位kW。模型里的决策变量包括(P_{ch}(t))储能在时段t的充电功率kW(P_{dis}(t))储能在时段t的放电功率kW(soc(t))储能在时段t结束时的荷电状态取值范围0到1(u_{ch}(t))、(u_{dis}(t))二进制变量分别表示充电状态和放电状态(P_{grid}(i,t))用户i在时段t从电网购电的功率kW(P_{es}(i,t))用户i在时段t从储能获得的放电功率kW。为什么要同时设置 (P_{grid}) 和 (P_{es}) 两个变量因为共享储能的放电功率不是自动流向特定用户的必须通过优化决定每个用户分到多少。这样才真正把“共享”两个字建模出来了。2.2 目标函数系统运行总成本最小我们关心的是整体经济性目标函数写成所有用户购电费用加上储能运维费用之和最小[ \min \quad \sum_{t1}^{24} \left[ price(t) \cdot \left( \sum_{i1}^{N} P_{grid}(i,t) P_{ch}(t) \right) c_{op} \cdot \left( P_{ch}(t) P_{dis}(t) \right) \right] ]公式的含义拆开看每个时段电网总购电功率等于各用户购电功率之和加上储能充电功率。储能在谷时充电会增加购电成本但峰时放电又会通过 (P_{es}) 替代用户从电网买电一增一减之间优化器自动寻找最省钱的充放电时机。(c_{op}) 是储能运行维护成本系数单位是元/kWh加上这一项可以防止模型让电池过频地小幅度充放。2.3 约束条件逐条说明约束是整个模型的核心一条都不能少我按功能分组功率平衡约束[ P_{load}(i,t) P_{grid}(i,t) P_{es}(i,t) \quad \forall i,t ]这条保证每个用户每时每刻负荷都被满足要么从电网买要么从储能拿。[ \sum_{i1}^{N} P_{es}(i,t) P_{dis}(t) ]储能在时段t放出的总功率必须等于所有用户分走的功率之和不能凭空消失也不能有缺口。SOC动态约束[ soc(t) soc(t-1) \eta_{ch} \cdot P_{ch}(t) \cdot \Delta t - \frac{1}{\eta_{dis}} \cdot P_{dis}(t) \cdot \Delta t ]这里 (\Delta t 1h)充电效率 (\eta_{ch}) 取0.95放电效率 (\eta_{dis}) 取0.95。SOC的更新是跨时段耦合的这也是日前调度和实时调度最本质的区别——决策必须通盘考虑24小时的时序关系光看当前时段一定会做错决定。充放电功率上下限与互斥约束[ 0 \le P_{ch}(t) \le P_{ch}^{max} \cdot u_{ch}(t) ][ 0 \le P_{dis}(t) \le P_{dis}^{max} \cdot u_{dis}(t) ][ u_{ch}(t) u_{dis}(t) \le 1 ]二进制变量保证储能不能在同一时段又充又放。虽然实际工程里电池管理系统也有互锁但优化模型里如果不加这个约束很容易出现同时充放电的“虚耗”解——模型会利用充电和放电同时产生来套取某种数学上的零成本循环结果完全不可用。SOC边界约束[ 0.1 \le soc(t) \le 0.9 ]电池不建议做到0和1实际运行中留10%以上余量既保护寿命又应对预测误差带来的调度偏差。初值约束[ soc(0) 0.2,\quad soc(24) \ge 0.2 ]soc(0)是调度开始前的荷电状态soc(24)是调度周期结束时的值。末端SOC设置为不低于初始值是为了保证电池“第二天还能接着用”防止优化器把电池彻底放空来压成本。实际项目里这个值可以根据次日调度计划的衔接需求调整。变压器容量约束可选但推荐[ \sum_{i1}^{N} P_{grid}(i,t) P_{ch}(t) \le P_{trans}^{max} ]工业园区变压器容量有限储能充电叠加各用户购电功率不能超过变压器上限。这个约束在算例中容易触发也是判断调度方案是否可执行的重要指标。2.4 为什么最终落到混合整数线性规划目标函数里购电费用是线性项SOC动态约束是线性等式功率上下限约束是线性不等式只有充放电互斥引入了二进制变量。所以整个问题是一个典型的混合整数线性规划MILP。选择MILP而不是非线性规划有几个好处一是理论上能找到全局最优解不会陷在局部最优里二是CPLEX、Gurobi这类商业求解器对MILP的求解效率非常高24时段的共享储能问题规模不大通常几秒钟就能收敛三是线性模型的结果可解释性强调度曲线不会出现奇怪的非线性跳动方便给运营方解释为什么某个时段要这样充放。3. MATLAB实现从数据准备到Yalmip建模3.1 程序文件结构我习惯把程序拆成四个文件职责清晰改参数不用满文件找main_optimization.m主入口读参数、调建模、求解、输出结果load_input_data.m生成或读取电价数据、负荷预测数据、储能参数build_shared_es_model.mYalmip建模包括变量定义、约束装配、目标函数plot_results.m绘制SOC曲线、充放电曲线、各用户购电曲线。3.2 输入数据准备电价数据可以直接用数组写死也支持从Excel读取% 分时电价单位元/kWh长度24 price [0.32*ones(1,6), ... % 0-6点低谷 0.65*ones(1,2), ... % 7-8点平段 1.00*ones(1,4), ... % 9-12点高峰 0.65*ones(1,2), ... % 13-14点平段 1.10*ones(1,4), ... % 15-18点尖峰 0.65*ones(1,2), ... % 19-20点平段 1.00*ones(1,4)]; % 21-24点高峰工业用户的负荷曲线我建议不要用纯随机数据最好基于工厂实际用电模式叠加小幅度扰动。比如机械加工厂白天负荷高、午休有波谷冷链仓库全天平稳、夜间略高。构造出来的曲线要让求解器“有的决策”如果所有用户峰谷趋势完全一致共享储能的价值就大打折扣了。储能参数建议集中放在结构体里para.rated_capacity 800; % 额定容量 kWh para.rated_power 200; % 额定功率 kW para.eta_ch 0.95; % 充电效率 para.eta_dis 0.95; % 放电效率 para.soc_min 0.1; para.soc_max 0.9; para.soc_init 0.2; para.cost_om 0.03; % 运维成本 元/kWh3.3 Yalmip建模核心代码模型构建是精华部分。先定义变量注意二进制变量的声明方式% 定义变量 N 3; % 用户数量 T 24; soc sdpvar(T1, 1); % 荷电状态多一个点存初始值 P_ch sdpvar(T, 1); % 充电功率 P_dis sdpvar(T, 1); % 放电功率 u_ch binvar(T, 1); % 充电状态 u_dis binvar(T, 1); % 放电状态 P_grid sdpvar(N, T, full); % 用户从电网购电 P_es sdpvar(N, T, full); % 用户从储能获得功率约束装配时矩阵化的写法比循环高效也更贴近Yalmip的风格F []; % 功率平衡用户负荷 电网购电 储能放电 for i 1:N F [F, P_load(i,:) P_grid(i,:) P_es(i,:)]; end % 储能放电功率 所有用户获得功率之和 F [F, sum(P_es, 1) P_dis]; % SOC动态方程 F [F, soc(2:T1) soc(1:T) para.eta_ch*P_ch/para.rated_capacity ... - (1/para.eta_dis)*P_dis/para.rated_capacity]; % 充放电互斥与功率限值 F [F, 0 P_ch para.rated_power .* u_ch]; F [F, 0 P_dis para.rated_power .* u_dis]; F [F, u_ch u_dis 1]; % SOC边界与初值 F [F, para.soc_min soc(2:T1) para.soc_max]; F [F, soc(1) para.soc_init, soc(T1) para.soc_init]; % 可选变压器容量约束 P_trans_in sum(P_grid, 1) P_ch; F [F, P_trans_in 500];目标函数写成矩阵形式total_cost sum(price .* (sum(P_grid, 1) P_ch)) ... para.cost_om * sum(P_ch P_dis); optimize(F, total_cost, sdpsettings(solver, cplex));这里有个容易搞错的地方sum(P_es, 1)得到的是一个1×T的行向量而P_dis是T×1列向量两者相加要用转置保持维度一致否则Yalmip会报维度不匹配。我最初写这个程序时就被这个坑耽误了一阵子。3.4 结果提取与输出求解完成后用value()函数提取变量值soc_opt value(soc); p_ch_opt value(P_ch); p_dis_opt value(P_dis); p_grid_opt value(P_grid); p_es_opt value(P_es);绘图部分我习惯画三张图第一张是SOC曲线和充放电功率的堆叠图第二张是各用户负荷和购电曲线对比第三张是储能放电分配柱状图。运营方看第一张图就能直观判断策略优劣第二张图用于核对每个用户的用电保障第三张图用于费用分摊三张图缺一不可。4. 算例验证三工业用户共享一台储能的效果4.1 算例参数设定为了验证模型我设了一个典型场景一个园区内有三个工业用户共享一座800kWh/200kW的储能电站。用户A机械加工厂两班制8:00-20:00负荷高午休时段出现一个明显的功率下凹夜间负荷很低用户B冷链仓库全天负荷平稳夜间比白天略高常年有制冷负荷用户C精密零部件厂三班倒负荷曲线全天波动幅度小但白天仍比夜间高约15%。三个用户的最大负荷分别约300kW、180kW、260kW总峰值负荷约740kW而园区变压器容量只有500kW。过去这根本不够用需要报装增容。现在靠共享储能削峰填谷把超出的部分通过储能放电补足相当于“虚拟增容”。4.2 共享前后的成本对比优化求解后我统计了三种场景下的日用电成本场景日购电成本元储能运维成本元总成本元无储能电网直供698706987共享储能日前优化调度6214426256理想无约束下界598805988共享储能方案让总成本从6987元降到6256元降幅约10.5%。别小看这10%工业用户一年用电300天以上一年省下超过20万元。而用户租赁储能容量支付的费用通常远低于这个节省额所以共享模式在经济上完全成立。对比“无储能”和“理想下界”的差异也可以看出约束条件对成本空间的影响SOC边界、充放电效率、变压器限制都挤掉了一部分理论利润这是物理现实不用遗憾。4.3 调度方案的时序解读看优化结果里的SOC曲线凌晨0-6点谷段储能以接近满功率充电SOC从0.2一路涨到0.86左右上午9-12点峰段储能放电SOC快速下降午间平段基本不充不放下午15-18点尖峰段又一次集中放电夜间平段补了一小段充电赶在次日调度开始前把SOC恢复到0.2以上。值得关注的是放电功率在各用户之间的分配9点左右放电功率主要分给用户A因为这时候机械加工厂正处于上午开工高峰负荷压力最大下午尖峰时段的放电则偏向用户B和C因为用户A午休后负荷相对平坦而精密件厂第三班交接时有用电突增。这个分配结果不是预先设定的是优化器根据各用户负荷余缺自动计算出来的这正是“共享”二字的含义——把有限的储能容量动态分配给最缺电的用户。要特别提醒的是在基本模型里如果目标函数只有总购电成本(P_{es}(i,t)) 的分配会存在多种可行解也就是说总成本相同但分配方案不同。为了让结果可解释、可落地我额外加入了一个极小的正则项目标函数变成[ \min \quad C_{total} \lambda \sum_{i,t} \left( P_{es}(i,t) - \frac{P_{load}(i,t)}{\sum_i P_{load}(i,t)} \cdot P_{dis}(t) \right)^2 ](\lambda) 取0.001作用是让分配尽量接近按负荷比例的自然倾向同时不会干扰成本优化的主导方向。加了这项目标之后(P_{es}) 的解稳定多了画图出来不会出现同一时段某个用户分到能量但另一个用户分文没有的极端情况。5. 实战排错与调参经验从求解报错到结果可信5.1 Yalmip求解器配置与报错排查Yalmip本身不包含求解器需要额外安装CPLEX或Gurobi。新手最容易遇到的错误是错误: No suitable solver found for the KKT conditions.这个报错通常是Yalmip没有识别到求解器。排查步骤先运行yalmiptest看求解器列表确认CPLEX是否被识别如果没识别多半是环境变量没配好或者安装路径包含中文。把求解器安装路径加入系统PATH重启MATLAB后基本能解决。如果求解器正常但求解过程报License Error那就要检查CPLEX/Gurobi的授权状态。Gurobi个人版可以用免费的学术许可申请之后在MATLAB里设置sdpsettings(solver, gurobi, gurobi.TokenServer, ...);5.2 SOL初始化与SOC漂移的坑有一个非常隐蔽的问题如果不设置u_ch u_dis 1MILP会变成一个LP问题求解器可能会让储能“又充又放”。表面上看同时充放电时净功率为零SOC不变但购电成本和运维成本都会被无限拉高最终模型会得到一个荒谬的调度方案。加了二进制互斥约束之后模型才真正符合物理逻辑。还有SOC初值问题我把SOC(0)设为0.2末端约束为0.2。但某些负荷条件下优化器宁愿在最后一个时段降低放电来保住SOC也不愿在晚高峰多放一点电以节省更多成本导致调度曲线“前紧后松”。如果发现末端SOC实际停留在0.35以上说明前一天的调度还有优化空间可以考虑放宽末端约束为0.1或者把SOC(0)抬到0.3看成本是否能进一步下降。Big-M相关的数值问题也需要留意。虽然上面的代码用的是Yalmip的0 P_ch P_max .* u_ch自动生成的约束但如果你手动引入Big-M注意M值不要取太大。标准做法是取该时段功率上限的1.1倍比如额定功率200kW时M取220数值稳定性最好。取10000这种大数会导致MILP求解时出现病态条件数轻则求解慢重则得出违反直觉的伪最优解。5.3 模型扩展方向与工程落地思考当前模型只考虑了储能本身的运行成本和用户的购电成本。实际共享储能电站项目里还有几个方向值得扩展需求响应联动把电网的需求响应信号加进目标函数在削峰时段获得额外补贴光伏接入园区屋顶光伏发电功率作为负的负荷叠加让储能和光伏联合优化电池寿命折损在SOC边界约束之外增加“充放电次数限制”或“日吞吐量限制”把电池循环寿命折损计入目标函数防止优化器为省几块钱电费把电池往死里用多时间尺度滚动日前计划定基调日内每15分钟用模型预测控制修正一次抵抗负荷预测误差。这些扩展在原有模型基础上都是增量修改核心求解框架不用大动。如果你手头的课题只做基础版我的建议是把基础版做到位数紧凑、结果可解释答辩和汇报时讲清楚每个约束的物理含义比堆砌花哨的扩展算法更让人信服。我在实际跑这个模型时还有一个小习惯每次调参数后先保存一份调度结果CSV再对比前一次的SOC曲线和成本明细。连着调三五次基本就能摸清参数和结果之间的敏感度。这个习惯帮我少走了好多弯路你也值得试试。
网站建设高端定制企业官网