去年做园区综合能源系统调度优化的时候,我踩过一个特别典型的坑:第一版调度模型没有把电池损耗算进去,优化结果出来年化收益很漂亮,结果被运维负责人一句话问住了——电池一天来回充放两个半循环,一组储能电池五年就要换,换一组成本接近整套系统的三分之一,这笔账你算了吗?当时我确实没算。
也就是从那次之后,我花了不少时间把电池损耗模型在综合能源系统里的应用逻辑彻底理了一遍。现在最常用的有两类思路:一类是计算量小、适合嵌入调度优化的等效循环寿命法,另一类是精度高、适合离线评估的雨流计数法结合半经验老化模型。这篇文章就用一个园区微电网实例,把两种模型的原理、Matlab实现、结果对比和避坑经验完整写出来,给正在做综合能源系统仿真或者储能经济性评估的朋友作参考。
1. 为什么综合能源系统必须把电池损耗算明白
1.1 电池在综合能源系统里的角色,决定了损耗不能忽略
综合能源系统通常包含光伏、风电、燃气轮机、电锅炉、储能电池和多种负荷。在这个系统里,电储能电池承担的任务非常核心:削峰填谷、平滑新能源出力、提供短时功率支撑。相比燃气轮机和电锅炉,电池的调节速度最快,小时级甚至分钟级响应,所以几乎所有的调度优化模型都会优先让电池去承担波动调节。
问题恰恰出在这里。电池的灵活性越强,优化器就越倾向于频繁使用它。一个不考虑损耗成本的调度模型会把电池当成“零磨损设备”,结果往往是日内多次充放循环,表面上看削峰填谷收益很高,实际寿命消耗和更换成本被完全掩盖。在综合能源系统的全生命周期经济评估里,电池更换成本通常占储能系统总投资的三分之一甚至更高,忽略损耗模型,等于把最大的一项隐性成本漏掉了。
1.2 不算损耗账,优化结果很容易南辕北辙
我用一组数字来算笔直观的账。假设一个1MWh磷酸铁锂电池系统,厂家标定100%放电深度下的循环寿命是6000次。如果每天的调度策略让电池等效循环2次,那理论寿命大概是8年;如果每天只能等效循环1次,寿命可以达到16年。
再按当前储能系统的典型造价估算,1MWh电池系统整体投资大约在120万到200万之间,电池模组更换成本按总投资的60%计算,一次更换大约要90万。8年更换时,每年摊到电池上的折旧成本是11万左右;16年更换时,每年只要5.6万左右。而一个园区储能靠削峰填谷一年能带来的收益可能也就10万到15万。每年6万的损耗差额,直接决定项目是盈利还是亏损。
所以在我现在的项目框架里,电池损耗模型不是一个可选的精度增强项,而是储能投资回收期测算的必要组成部分。
1.3 两种模型不是竞争关系,要放在不同阶段用
这篇文章要对比的两种模型,很多人容易理解成“哪个更准就选哪个”,但其实它们适合的工作阶段完全不同。
等效循环寿命法简单、快速、线性,可以作为成本项直接放进混合整数规划或线性规划的调度优化目标函数里,让优化器在寻优过程中自动权衡“削峰收益”和“电池磨损”。
雨流计数法结合半经验老化模型计算量大,但有更高的非线性描述能力,能把放电深度、温度、SOC区间等因子都考虑进去,适合用来做离线评估、策略验证和投资规划。实际项目中我通常把两个模型配合使用,调度阶段用快模型,评估阶段用慢模型。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 两种电池损耗模型:原理、公式与适用边界
2.1 等效循环寿命法:线性折算,快而稳
等效循环寿命法的核心思想是把电池寿命看成“累计放电能量”的总额。厂家如果标定100%放电深度下循环6000次,那意味着电池在寿命期内可以累计放出大约6000倍额定容量的能量。不管实际怎么充放,只要统计总放电能量,折算成等效满放次数,再和额定循环次数比较,就能算出寿命消耗比例。
计算过程非常直接。设额定容量为C_bat,统计周期内的总放电能量为E_discharge_total,参考放电深度为DOD_ref,则等效循环次数为:
N_eq = E_discharge_total / (C_bat × DOD_ref)
寿命损耗率就是:
Loss_ratio = N_eq / N_rated
其中N_rated是厂家标定的参考循环寿命。这个模型的关键在于参考放电深度DOD_ref必须和N_rated对应,比如厂家按100%DOD测试得到6000次,那DOD_ref就取1.0;如果厂家按80%DOD测试得到8000次,则DOD_ref取0.8,N_rated取8000。
这个模型的优点是线性、无阈值跳变、计算极快。在调度优化里,可以把损耗折算成一个与放电量成正比的成本项,不会破坏优化模型的凸性或线性结构。缺点也很明显:它假设浅循环和深循环的单位能量损耗相同,而实际电池在深循环下的边际损耗明显更高,所以这个模型在频繁浅充浅放场景下会相对保守,在深度大循环场景下可能低估损耗。
2.2 雨流计数法结合半经验老化模型:精细但计算重
雨流计数法最早用于材料疲劳寿命分析,用来从随机载荷时间序列里提取完整的应力循环。放到电池场景里,就是把一条波动复杂的SOC曲线拆解成若干个充放电滞回环。每个环对应一次充电到放电或放电到充电的完整循环,环的幅值对应放电深度,环的均值对应平均SOC区间。
得到每个循环的DOD之后,再用半经验老化公式计算损耗。工程上常用的一种简化形式是:
Q_loss = a × DOD^b
这里Q_loss是单次循环的容量衰减百分比,a和b是通过老化实验标定的系数。DOD越大,单次循环损耗越大,而且b通常大于1,说明损耗随放电深度呈超线性增长。如果还要考虑温度影响,可以再乘一个Arrhenius形式的温度修正项。
整个计算流程是:SOC曲线先做雨流计数,得到一组DOD值和对应的均值SOC,然后对每个循环累加容量衰减,最终得到容量保持率。这个模型能区分浅循环和深循环的损耗差异,也能评估SOC运行区间偏移带来的影响,明显更接近电池的真实老化行为。
缺点是计算量偏大,而且雨流计数结果无法直接写进线性优化模型里。所以它更适合作为调度策略的“裁判员”,对已经生成的电量序列做精细评估。
2.3 两种模型的关键对比
| 对比维度 | 等效循环寿命法 | 雨流计数+半经验老化模型 |
|---|---|---|
| 计算原理 | 能量吞吐线性累积 | SOC循环识别+非线性老化 |
| 输入数据 | 电池功率/放电能量序列 | SOC序列、温度、倍率信息 |
| 计算时间 | 毫秒级 | 较高,取决于数据长度 |
| 精度表现 | 中等,浅循环场景偏保守 | 较高,能区分DOD和SOC区间影响 |
| 嵌入优化模型 | 容易,线性可导 | 困难,非线性结构 |
| 适用阶段 | 在线调度、策略寻优 | 离线评估、容量规划、方案比选 |
3. Matlab实现:从数据准备到核心代码
3.1 搭建一个园区场景并生成示例数据
我用的实例场景是一个典型园区微电网:光伏装机800kW,风电200kW,常规负荷峰值600kW,电池储能500kW/1000kWh。调度周期24小时,步长15分钟,也就是一天96个时点。
示例数据我直接用Matlab生成,方便复现,实际项目里替换成园区采集的实测数据即可。
matlab复制dt = 15/60; % 时间步长,单位小时
T = 24/dt; % 步数 = 96
t = (0:T-1) * dt; % 时间序列
% 示例负荷:基础负荷叠加日间高峰,加随机扰动
P_load = 350 + 200 * sind((t - 8) * 360 / 24) + 80 * randn(1, T);
P_load = max(P_load, 0);
% 示例光伏:从早上6点到下午6点,带云层扰动
P_pv = max(0, 500 * sind((t - 6) * 360 / 12) + 40 * randn(1, T));
% 示例风电:全天波动
P_wind = 100 + 60 * sind((t - 12) * 360 / 24) + 40 * randn(1, T);
这里的光伏曲线用sin函数近似日出日落的功率包络,负荷加了一些随机波动,目的只是让后续SOC曲线看起来真实。做项目时一定要用场站实际采集数据,尤其是夏天和冬天的典型日要分开建模。
电池功率序列来自一个简单的启发式调度规则:电价低谷充电、高峰放电,同时平抑光伏波动。得到P_bat之后,用累加方式算SOC。
matlab复制P_bat = zeros(1, T); % 电池功率,正为充电,负为放电
C_bat = 1000; % 容量 kWh
soc0 = 0.5; % 初始SOC
eta_c = 0.95; % 充电效率
eta_d = 0.95; % 放电效率
for k = 2:T
if P_load(k) < P_pv(k) + P_wind(k)
P_bat(k) = min(250, (P_pv(k) + P_wind(k) - P_load(k)) * 0.8);
else
P_bat(k) = -min(250, (P_load(k) - P_pv(k) - P_wind(k)) * 0.8);
end
end
SOC = zeros(1, T);
SOC(1) = soc0;
for k = 2:T
if P_bat(k) >= 0
SOC(k) = SOC(k-1) + eta_c * P_bat(k) * dt / C_bat;
else
SOC(k) = SOC(k-1) + P_bat(k) * dt / (eta_d * C_bat);
end
end
SOC = min(max(SOC, 0.1), 0.95);
3.2 模型一的Matlab实现
等效循环寿命法的代码非常短,核心就是统计放电能量然后折算。
matlab复制function loss_ratio = calc_cycle_loss(P_bat, dt, C_bat, DOD_ref, N_rated)
E_discharge = sum(max(0, -P_bat) * dt); % 总放电能量 kWh
N_eq = E_discharge / (C_bat * DOD_ref); % 等效循环次数
loss_ratio = N_eq / N_rated; % 寿命消耗比例
end
这里有一个单位细节要特别注意。P_bat单位如果是kW,dt单位是小时,那P_bat乘以dt得到的就是kWh。C_bat也必须是kWh,保持一致。DOD_ref是无量纲比例,N_eq得到的是“等效满放次数”。比如一天放电500kWh,容量1000kWh,DOD_ref取1.0,那一天等效循环就是0.5次,如果N_rated是6000,当日寿命消耗就是0.5/6000,约0.0083%。
这个结果放进调度优化里时,通常会乘一个损耗成本系数,把寿命消耗折算成金额。比如系统更换成本90万,当天损耗比例0.0083%,折算损耗成本就是90万乘以0.000083,约74.7元。优化器在做决策时就会掂量,一次深循环到底值不值。
3.3 雨流计数如何嵌入Matlab
Matlab基础工具箱里没有内置雨流计数函数,我用的方案是从File Exchange下载的rainflow实现,代码成熟、测试充分。如果你们公司有更严格的代码合规要求,也可以自己实现简化的滞回计数算法,但完整版的雨流计数处理半循环配对逻辑比较复杂,我建议没有特殊需求就直接用成熟实现。
调用方式很简洁:
matlab复制% SOC作为输入,建议转成百分比或0~1标幺值
soc_input = SOC(:);
[cycles, mean_values] = rainflow(soc_input);
% 常见输出下,cycles是循环幅值,mean_values是循环均值
DOD = cycles / 100; % 如果输入是百分比,转为0~1
soc_mean = mean_values / 100;
不同版本的rainflow函数输出结构可能不一样,有的是返回三列矩阵,分别是循环幅值、均值、半循环标记。拿到结果后第一步先画个直方图或者散点图看分布,确认数据合理再往下算。直接闷头算,很容易被异常循环误导。
3.4 半经验老化模型的计算代码
雨流计数得到每个循环的DOD之后,半经验老化公式的计算就是一个循环累加的过程。
matlab复制function capacity_loss = calc_semi_empirical_loss(DOD, T_cell)
% 半经验参数,示例值,来自某磷酸铁锂电芯加速老化数据
a = 0.0008; % 单次循环损耗系数
b = 1.2; % DOD幂指数
Ea = 25000; % 活化能 J/mol
R = 8.314; % 气体常数
T_ref = 298.15; % 参考温度 25℃
k_temp = exp(-Ea / R * (1 / T_cell - 1 / T_ref));
capacity_loss = 0;
for i = 1:length(DOD)
d = DOD(i);
if d < 0.01
continue; % 极小循环忽略
end
capacity_loss = capacity_loss + a * d^b * k_temp;
end
end
这段代码里我加入了温度修正项,T_cell是电芯温度。这里用的a、b系数是我在某磷酸铁锂电芯加速老化实验数据上拟合出来的示意值,不同电芯差异很大。最稳妥的做法是用厂家规格书里的循环寿命表做标定,或者拿到加速老化测试数据后用Matlab的曲线拟合工具箱重新拟合a和b。
3.5 完整的运行流程
把整个流程组织成模块,我会建三个脚本:
main_ies_simulation.m:读入数据、生成调度策略、输出电池功率和SOC;calc_cycle_loss.m:等效循环寿命法损耗计算;calc_rainflow_loss.m:雨流计数加半经验老化计算。
main脚本里串联的逻辑是:先得到P_bat和SOC序列,然后分别调用两个损耗计算函数,最后输出损耗对比结果。这个结构也方便后续替换不同的调度策略,只要P_bat和SOC是同一套输出格式,损耗计算模块完全不用动。
4. 应用实例:两种模型在园区场景下的结果对比
4.1 设计三组对照调度策略
为了把两种损耗模型的差异直观展示出来,我设计了三组调度策略:
策略A:完全不考虑电池损耗,调度目标只有购电成本最小,电池自由充放,削峰填谷力度最大。
策略B:在调度目标中加入模型一的损耗成本项,优化器会自动权衡“多充放一次能省多少购电费”和“多产生多少损耗成本”。
策略C:人工设定电池使用限制,每天只允许在电价低谷充一次、高峰放一次,SOC波动幅度控制在40%以内,属于非常保守的策略。
三组策略跑完之后,分别用两个模型计算损耗指标。这里注意,策略B的调度内部已经用了模型一,所以模型一的损耗会主动压低;而模型二作为独立评估者,对所有策略都做同样标准的精细化计算。
4.2 结果数据解读
仿真得到的一组典型结果如下:
| 策略 | 日购电成本(元) | 日等效循环次数 | 模型二年容量衰减率 |
|---|---|---|---|
| 策略A | 3200 | 2.35 | 6.8% |
| 策略B | 3250 | 1.15 | 3.2% |
| 策略C | 3450 | 0.70 | 2.1% |
先看策略A和策略B。策略A一天能比策略B少花50元购电费,一年下来省约1.8万元。但代价是电池等效循环次数翻倍,模型二评估的年容量衰减率从3.2%上升到6.8%。如果电池更换成本按90万计算,策略A比策略B一年多产生约3.24万的损耗成本。购电节省的1.8万还不够补损耗亏空,策略A实际上得不偿失。
再看策略C。它确实把电池损耗压到了最低,但日购电成本比策略B高出200元,一年就多花7.3万。这显然矫枉过正,电池保护得很好,系统经济性却垮了。
综合来看,策略B是三者里最合理的:它通过模型一把损耗成本引入优化目标,让调度器主动降低了无效循环,同时仍然保留了足够多的削峰填谷收益。
4.3 损耗成本折算的实操口径
把容量衰减率折算成年度损耗成本时,有一个口径问题必须注意。我上面用的是“年容量衰减率乘以电池更换成本”,这个做法在方案对比阶段够用,但更严谨的做法是考虑“容量衰减到80%即寿命终止”的行业标准。
举例来说,策略A的年衰减率6.8%,按线性衰减到80%计算,寿命约2.94年;策略B年衰减率3.2%,寿命约6.25年。这时每年的电池折旧成本就是更换成本除以寿命年数。策略A每年折旧约30.6万,策略B每年折旧约14.4万,差距更骇人。
比较两种口径,线性换算相对直观,而基于80%寿命阈值的折算法更适合写进投资回报率模型。实际汇报时我一般两个指标都给出,一个说明年损耗率,一个说明等效寿命年限。
5. 常见问题与避坑指南
5.1 雨流计数之前,SOC曲线一定要预处理
这是我最开始跑模型二时踩的坑。直接把原始SOC序列丢进rainflow函数,结果出来一大堆幅值0.5%的小循环,损耗被严重高估。原因很简单:调度模型输出的SOC本身带数字噪声,再加上控制器的小幅波动修正,雨流算法会把这种微小的锯齿全识别成循环。
解决办法是在雨流计数前做两步预处理。第一步用滑动平均或中值滤波平滑SOC曲线,时间窗口取1到2个调度周期;第二步按电池的实际控制精度做数据舍入,比如SOC控制精度是0.5%,就把SOC数据舍入到0.5%的整数倍。这两步能把虚假循环数量压掉一大半。
另外,半循环的处理也要心里有数。SOC序列首尾两端的未配对半循环,有的rainflow实现会单独返回,有的会直接包含在结果里。我在代码里统一把半循环按半个循环计算损耗,保证口径一致。
5.2 等效循环寿命法别直接照搬厂家参数
厂家规格书里的循环寿命数据,测试条件五花八门。有的厂家标100%DOD循环6000次,有的标80%DOD循环8000次,有的标到容量剩60%算寿命终点,有的标80%。如果拿到参数不看测试条件直接套进模型,计算结果能差出30%以上。
我自己的习惯是把厂家数据整理成一张“放电深度-循环次数”表,然后用模型一计算时,DOD_ref取实际运行的平均放电深度,N_rated取对应DOD下的循环次数。这样虽然还是线性模型,但至少和厂家的测试口径对齐了。
还有一点,等效循环寿命法在高频浅循环场景下会高估损耗,它把浅循环的放电能量按深循环的标准折算,导致优化器过度排斥电池使用,削峰填谷收益被白白牺牲。所以如果调度结果出现大量浅循环,建议把模型一的损耗系数适当调低,或者直接用模型二做月度校准。
5.3 半经验模型参数标定数据从哪里来
a和b两个参数是整个模型二的灵魂,但也是最难拿到的数据。文献里有很多经验公式,但直接抄到你的项目里风险很大,因为电芯材料体系、封装工艺、热管理方式都不同。
我的建议有三个数据来源。首选是厂家规格书里的循环寿命表,虽然不是直接的容量衰减曲线,但可以通过不同DOD下的循环次数反推b值。其次是可以要求厂家提供加速老化测试报告,一般会有60℃下不同DOD循环的容量保持率数据,直接拿来做拟合。最后是实际运行的运维数据,如果这个储能站已经运行了一两年,把每月的容量测试结果和运行记录对应起来,用cftool拟合出最贴近实际的老化参数。
5.4 性能与数值稳定性的处理
雨流计数的复杂度跟数据长度强相关。做全年8760小时、逐小时粒度的SOC曲线雨流计数时,如果不做任何处理,计算时间可能会到分钟级甚至更久。我的做法是先压缩SOC序列,把连续变化小于阈值的平台段合并,再跑雨流计数,计算量能降一个量级。
单位问题也经常出错。P_bat用kW、dt用小时、C_bat用kWh,这三个单位必须统一。SOC参与损耗计算时我建议用0到1的标幺值,因为很多半经验公式的DOD指数项对量纲敏感,用百分数可能导致结果差几个数量级。
还有一个细节是SOC初始值。一天的SOC曲线首尾相连做雨流计数时,如果初始SOC和末尾SOC不同,会出现一个明显的伪循环。建议在计数前把SOC序列首尾拼接处理,或者至少先检查首尾SOC差值,如果差值很大,说明这一天的调度没有日内闭环,结果里会有一个大的半循环需要特别注意。
最后说一点我个人的体会
两个模型都跑通之后,最直观的感受是它们完全不是替代关系。调度优化阶段,模型一能帮你盯住大方向,防止优化器为了省几十块钱电费把电池往死里用;到了容量规划、收益测算、方案汇报阶段,模型二才是能拿给投资方看的硬证据。我现在做综合能源系统项目,固定套路就是“快模型在线寻优、慢模型离线校核”,两边结果一对照,方案基本不会跑偏。如果你的项目里要换电池型号,或者新增储能容量,直接把这套框架的参数替换一下就能重新出结果。这也算是我在这次实践中觉得最值得分享的思路。
