先说结论:储能辅助火电机组二次调频,不是让储能去替代火电,而是让储能去干火电不擅长的那部分活。火电机组本身能做AGC,但爬坡速率、调节死区、锅炉惯性这些物理条件卡在那里,面对几秒到几十秒的高频扰动时经常跟不上。储能正好相反,响应快、调节精度高,但能量有限,扛不了长周期。把两者在二次调频控制策略层面绑在一起,再做容量优化配置,是现在做火电灵活性改造、储能调频项目前期方案时很常见的研究方向。这篇博文就基于我自己用Matlab和Simulink搭这套系统的经验,把控制策略怎么设计、仿真模型怎么建、容量怎么优化、中间有哪些坑,一次讲清楚。适合正在做相关课题的学生,也适合想快速摸清技术路线的工程人员。
1. 储能为什么必须掺合二次调频
1.1 火电做AGC的问题不在“能不能”,而在“快不快”
二次调频在电网里通常通过AGC下发有功指令到机组,机组再按指令调整出力。频率偏差大的时候,AGC指令变化会很频繁,火电机组机械上不是不可以跟,但中间隔着调速器、汽轮机、再热器、锅炉这几个大惯性环节。锅炉侧燃料变化到功率变化,经常要几十秒甚至分钟级,负荷指令一段时间内反复变化时,机组实发功率很难完全贴合指令,随之而来的就是ACE波动、调节性能评分下降。
储能系统在这条时间轴上几乎是完全互补的。电池储能通过变流器出力,响应时间能做到几十毫秒到几百毫秒,而且出力精确可控,不存在爬坡率限制和迟延。二次调频的偏差大部分是短周期分量,储能可以马上顶上去,火电再去吃长周期分量和经济负荷调整。这就是“储能辅助火电二次调频”最底层的逻辑:用储能的高频快速分量去补偿火电低频慢速分量。
1.2 整体控制策略:储能冲在前,火电稳在后
我通常把控制策略拆成三个层次。第一层是AGC/ACE信号生成,即根据频率偏差和联络线功率偏差形成总调节需求;第二层是功率分配层,把总调节需求分解成储能出力指令和火电出力指令;第三层是底层响应层,储能按指令快速出功,火电按经过限幅、限速后的指令平稳跟踪。
功率分配层的核心是一个高通/低通滤波结构。总调节需求先通过高通滤波器,高频分量给储能,剩余的低频分量给火电。这样储能只负责短时冲击,火电只负责缓慢持续调节,避免火电机组频繁加减负荷。滤波时间常数直接决定储能的参与强度:常数越小,储能拿到的分量越少,火电压力大;常数越大,储能频繁充放电,SOC管理难度上升,循环成本也上去了。
在分配之外还要加一个SOC恢复回路。储能不能无限充放电,所以当SOC偏离中间值时会生成一个很小的回充/放电功率,叠加到火电出力上,让火电多扛一点,储能慢慢回到合适的工作区间。这个回路必须很慢,否则会和二次调频主回路互相干扰。
1.3 为什么选择Matlab和Simulink来完成这项研究
这个方向选Matlab+Simulink基本是行业默认选项。原因有三:一是电力系统经典LFC、汽轮机、调速器模型在Simulink里有现成模块,拖拽参数就能搭出来;二是在二次调频领域大家习惯了传递函数和状态空间描述,Matlab里做线性化、频域分析都很顺手;三是容量优化配置需要大量仿真迭代,用sim(‘model’)在Matlab脚本里批量跑仿真,天然适合做粒子群、遗传算法这类启发式优化。
搜“matlab光学工具箱”“matlab图像处理”这些热词的朋友可能会觉得Matlab只是个数值计算工具,但在这个场景下,Simulink的连续/离散混合仿真、Saturation、Rate Limiter、Enable Subsystem这些都是做控制策略验证的利器。我建议至少在模型层面先跑通,再做代码生成和硬件在环,一上来就写嵌入式代码风险很大。
2. Simulink模型搭建与核心控制回路实现
2.1 火电汽轮机-调速器模型的取舍
做二次调频仿真,我不建议把锅炉、汽轮机物理模型做得特别细。那种精细化模型适合研究锅炉燃烧优化,不适合研究调频控制策略。针对AGC研究,常用的是汽轮机经典模型,包含调速器和汽轮机惯性传递函数。
火电部分的简化传递函数可以写成:
调速器: Gg(s) = 1 / (1 + Tg*s) 汽轮机: Gt(s) = (1 + Kr*Tr*s) / ((1 + Tch*s) * (1 + Tr*s)) 电力系统: Gp(s) = Kp / (1 + Tp*s)其中Tg是调速器时间常数,一般0.08-0.3秒;Tch是汽容时间常数,0.2-0.5秒;Tr是再热器时间常数,8-15秒;Kr是再热器增益系数,0.3-0.5。把这些参数放进Simulink的Transfer Fcn模块,就能建立一个足够反映火电响应特性的线性模型。若机组参与一次调频,需再并联一个频率偏差死区模块。
实操中我特别强调:不要把火电模型建成“阶跃响应完美”的理想模型。火电的调节死区、出力限幅、负荷变化速率限制必须保留。很多仿真结果好看,是因为模型里没有Rate Limiter,火电出力的变化速率不受限,储能优势完全体现不出来。
2.2 储能模型:别把重点放在电化学模型上
储能系统建模时,大家容易陷入电池电化学模型里出不来。实际上,对于二次调频仿真来说,SOC变化和功率响应特性远比你模拟锂离子扩散过程重要。储能部分我通常用一阶惯性环节表示变流器响应,再加上功率限幅、SOC积分环节和SOC上下限保护。
核心公式如下:
储能功率响应: dP_storage/dt = (P_ref - P_storage) / T_es SOC变化: SOC = SOC0 - integral(P_storage) / E_ratedT_es一般取0.02-0.1秒,体现变流器的快速响应。SOC单位是百分比,E_rated是储能额定能量,单位与功率和时间单位保持一致。Simulink里直接用Integrator模块就能实现SOC计算,不需要自建电池模型。
这里要提醒一个坑:如果模型里储能只在调频需要时出力,而没有SOC恢复逻辑,那仿真一天的SOC会漂移很厉害。后面算容量时,SOC上下限约束几乎必然被触发,结果就很难看了。所以即便储能模型再简单,SOC回充回路也要在2.3节里的控制逻辑一起搭上。
2.3 ACE分配、滤波与SOC回充逻辑
在控制回路里,第一次调频和二次调频要分开处理。一次调频靠机组调速器自己响应,二次调频通过AGC生成指令。我在Simulink里常把ACE写成:
ACE = ΔP_tie + β * Δf其中β是频率偏移系数,单位为MW/0.1Hz。在仅研究频率控制的单区域模型里,也可以直接用Δf作为负荷频率控制输入。送进PI控制器后得到总调节指令,再按高通/低通滤波分配。
分配那部分我一般这样搭:
总调节指令 -> Low-Pass Filter -> 火电指令 总调节指令 - 火电指令 -> 储能指令也就是火电拿到低通后的慢速分量,储能拿到总指令减去火电指令后的高频残差。这种结构的优点是天然满足“两路指令之和等于总指令”,不存在分配不平衡问题。
SOC回充逻辑则是把SOC偏差通过一个很慢的低通环节叠加到火电指令上:
ΔP_soc = K_soc * (SOC_ref - SOC),再经过限幅 火电指令_final = 低通后的AGC指令 + ΔP_soc 储能指令_final = 总指令 - 火电指令_final注意,ΔP_soc不能直接加到储能指令上,否则会把SOC恢复动作又分回储能自身,没意义。要加到火电指令上,让火电多出力或少出力,把储能“挤”回目标SOC区间。K_soc一般很小,我常取0.01-0.05,回充速度不能影响AGC性能。
2.4 离线仿真与优化调参的接口设计
如果你的目标是控制策略研究,那Simulink模型跑起来即可;如果后续要做容量优化,就得考虑怎么让Matlab脚本批量调用模型。我的做法是把储能额定功率、额定容量、滤波时间常数、控制参数都通过assignin('base', ...)写入工作区,模型里的参数直接用变量名引用。
这样在循环里就能反复修改参数并调用仿真:
assignin('base', 'P_storage', 30); assignin('base', 'E_storage', 30); assignin('base', 'T_filter', 0.5); simOut = sim('LFC_with_Storage.slx', 'StopTime', '2000');如果模型里某些参数必须用常量表达式,建议用evalin('base', '...')或者直接在模型初始化回调函数里统一处理。别在仿真脚本里散落大量set_param去改模块参数,万一模块名字改了,脚本容易崩。
3. 容量优化配置方法与Matlab实现
3.1 决策变量、目标函数和约束条件
容量优化配置的目标是确定储能额定功率P和额定容量E,但这不是拍脑袋定的,而是要在调频性能提升和投资成本之间找最优解。设计变量至少包含P和E,也可以把控制策略里的滤波时间常数、AGC控制参数一起优化,但那样搜索空间大,容易收敛慢。我建议先固定控制参数,只优化P和E,跑稳定后再放开一个控制参数去精细调整。
目标函数我一般写成:
min J = C_inv(P,E) + C_o&m(P,E) - B_reg(P,E)其中C_inv是储能投资年化成本,C_o&m是年运行维护成本,B_reg是储能参与二次调频带来的收益。收益部分可以是调频性能提升带来的辅助服务补偿提升,也可以是火电煤耗下降、设备磨损下降折算的费用。具体核算方式取决于你做的是学术研究还是工程可行性方案,但目标函数一定要把“性能提升”和“成本”放到同一个衡量维度里。
约束条件常用下面几项:
0.1*P_base <= P <= 0.2*P_base P*0.5 <= E <= P*2.5 SOC_min <= SOC(t) <= SOC_max |P_storage(t)| <= P 频率偏差峰值 <= 限值 调节响应时间 <= 限值P_base是火电机组额定容量,储能功率通常按机组容量的2%-10%考虑,储能时长按0.5-2小时考虑。这些约束既保证储能配置在合理区间,也保证仿真结果满足一次调频和二次调频的基本性能要求。
3.2 目标函数里的效益怎么量化
效益量化的难点在于调节性能指标和收益之间不是简单的线性关系。二次调频的性能通常看调节速率K1、调节精度K2、响应时间K3,综合成Kp。储能参与后,K1和K2提升最明显,因为储能出力快且精确。实际做项目时,会用调频里程乘以里程单价来计算收益,仿真阶段我一般简化成:
B_reg = r_mileage * N_mile * (Kp_with_storage - Kp_thermal_only) + r_capacity * PN_mile是年调节里程,r_mileage是单位里程收益,r_capacity是容量补偿收益。这样储能带来的性能提升自动转化成了年收益,可以和投资成本直接相减。
这里要特别注意,Kp的计算要基于同一条负荷扰动曲线。优化过程中所有粒子跑的仿真工况必须一致,否则性能差异是工况差异而不是方案差异,结果没有可比性。我通常把负荷扰动和频率扰动做成一组固定的时间序列,在Simulink里用Signal Builder或From Workspace模块加载。
3.3 用PSO加Simulink做容量寻优
容量优化常用粒子群算法,代码不算复杂,核心就是每一代把每个粒子的P和E写入工作区,调用Simulink仿真,读回频率偏差、储能功率、SOC等信号,再计算适应度。示意代码如下:
for iter = 1:maxIter for i = 1:nPop P = particle(i, 1); E = particle(i, 2); assignin('base', 'P_storage', P); assignin('base', 'E_storage', E); simOut = sim('LFC_with_Storage.slx', 'StopTime', num2str(simTime)); fitness(i) = calcFitness(P, E, simOut); end % 更新粒子速度和位置 particle = updateParticle(particle, fitness, w, c1, c2); endcalcFitness里有一个很多人容易忽略的点:如果某个粒子方案导致储能在仿真中途达到SOC上下限,不能靠罚函数一笔带过,而是要在适应度里加入明显惩罚,否则算法会倾向选择“刚好不越限但没有任何安全裕量”的方案。工程上要留SOC裕量,所以我把SOC越限惩罚设成非线性项,越界越深惩罚越大。
粒子群算法初始种群规模我习惯取30-50,迭代次数80-120次。如果每个方案仿真时长是2000秒,一次完整优化可能要跑几千次仿真。这个计算量在普通PC上可能要十几小时,所以仿真模型尽量用变步长求解器,别在模型里放高频PWM开关信号,否则优化过程会把人等崩溃。
3.4 参数敏感性:不是算出来就完事
容量优化算出最优解只是第一步,我一般还会做两组敏感性分析。第一组是改变调频里程单价,看最优容量怎么变;第二组是改变储能单位成本,看容量配置的拐点在哪。这两个参数在实际项目中波动很大,如果最优容量对它们特别敏感,那决策时就要留更多余量。
另外,容量优化结果还受负荷扰动场景影响。如果只用单一扰动序列优化,得到的结果可能过于乐观或悲观。我建议至少准备三组场景:日常小幅波动、AGC持续调节工况、频率越限紧急工况。三组场景下分别优化,再看有没有一个折中解。
4. 仿真结果分析与策略对比
4.1 工况设计
仿真工况我建议这样设计:一个600MW火电机组模型,负荷扰动曲线包含多个持续几十秒到几分钟的阶梯扰动和随机波动,模拟AGC下发指令的连续变化。储能配置在30MW/30MWh附近。这个量级足以让储能功率在一段时间内连续参与调频,但又不至于大到让SOC长期不变化。
为了对比控制策略的效果,我一般设四组:
| 场景 | 说明 |
|---|---|
| 纯火电 | 不含储能,作为基准 |
| 储能固定比例出力 | 储能按固定比例分担总指令 |
| 储能高频分配+SOC回充 | 本文采用的滤波分配策略 |
| 储能SOC限制过严 | 用于观察SOC约束对性能的影响 |
4.2 结果怎么看
仿真结束后我不会只看频率偏差曲线,而是用几个量化指标去判断:
频率偏差最大值:直接反映系统安全性 ACE均方根值:反映AGC整体调节效果 调节性能Kp:反映储能带来的补偿收益潜力 SOC变化范围:反映储能容量是否够用 储能出力次数/等效循环:反映电池寿命损耗其中ACE均方根值比最大值更能反映控制策略的日常表现,因为最大值往往由大扰动决定,而AGC考核是长期累积的。Kp计算需要从仿真结果里提取响应时间、调节速率和调节精度,这几个量在Simulink里可以用To Workspace模块保存信号后计算。
4.3 容量优化典型结果
根据我个人的经验,在一个典型600MW机组二次调频场景里,储能功率约等于机组额定容量的3%-5%时,Kp提升就很明显了;继续增加储能功率,频率偏差改善幅度会明显放缓,也就是边际效用递减。储能时长方面,如果主要是AGC调频,1C左右功率容量比已经比较合适,也就是30MW/30MWh这种配置。超过2C增加的容量更多是冗余,收益不明显,成本却线性上升。
当然,这是基于常规AGC扰动曲线的结论。如果你面对的具体机组煤种差、锅炉惯性大,或者AGC考核时间窗口很长,那最优时长还会往上走。所以我一直强调容量配置一定要结合仿真,而不是照抄别的项目结果。
5. 工程落地中的常见问题与实操心得
5.1 Simulink侧的高频坑
第一个常见坑是代数环。控制回路里如果存在无迟延的直通环节,Simulink会报代数环,导致步长缩短、仿真速度变慢。解决方法是把前向通道里某个比较环节换成Memory模块,或者把储能一阶惯性时间常数设成很小的正数,而不是绝对零秒。
第二个坑是求解器设置。系统里同时有连续积分器和离散逻辑时,我建议用连续求解器ode23tb或ode15s,并设置合理的最大步长。如果滤波时间常数很小,最大步长太大会丢掉高频响应,仿真结果失真。如果模型中带PWM或非常窄的脉冲,尽量用离散求解器,但这也会显著拖慢速度。
第三个坑是Enable Subsystem的误用。想在储能SOC过高时暂停储能调频,很多人会直接把储能子系统用Enable端口包起来。这样会导致储能功率瞬间清零,在功率曲线上制造阶跃,反而引起频率波动。正确做法是不去“关闭”储能,而是通过SOC回充逻辑渐进调整功率指令,让储能平滑退坡。
5.2 优化求解和仿真耦合的坑
容量优化迭代过程中,最容易出的问题是仿真结果不稳定。同一组参数跑两遍,如果储能SOC初始值没有复位,第二遍仿真结果可能完全不一样。这会导致粒子群算法误判适应度。我每次调用sim之前都会把模型里的积分器初始状态清零,或者用simOut里的最终SOC作为下一轮初值,并且在同一轮优化中统一采用固定初始SOC。
另一个问题是仿真时长不够。如果每次仿真只跑几百秒,SOC还没形成完整循环,储能容量对SOC约束的影响体现不出来,优化结果会偏向小容量。我一般会把仿真时长设为2000秒以上,覆盖至少几个完整的AGC指令周期。
还有一点,优化过程中不要频繁调用set_param改模型参数,尽量用基础工作区变量。这样不仅避免模型重新编译,还能利用Simulink的快速加速模式rapid accelerator,把几千次仿真时间压缩到可接受的范围内。
5.3 控制策略落地时的经验
仿真做出来是一回事,工程落地是另一回事。真正现场运行时,储能PCS的功率响应、通信延迟、AGC指令刷新周期都会对策略产生影响。比如现场AGC指令刷新可能是2-8秒,仿真如果按连续时间处理,会把储能优势放大。我在搭建模型时会把AGC指令离散化,带一个零阶保持器,这样仿真结果更贴近实际。
再就是储能系统自身要设置调频出力死区。频率偏差很小时,储能没必要频繁动作,否则一天内等效循环次数很高,对电池寿命影响很大。死区大小要根据所在电网的调频死区标准设定,通常0.01-0.033Hz。死区设置过大,二次调频性能会下降;太小,电池白白磨损。我自己通常取0.02Hz左右,再结合SOC区间做分段调节。
关于SOC管理,我强烈建议不要用固定上下限,而是采用动态SOC窗口。平时把SOC控制在40%-60%附近,以应对双向调节需求;预测到下一时段频率偏差方向性强时,再提前偏移SOC目标。这个预测不用很复杂,简单根据AGC指令变化趋势估计即可。加了这个逻辑后,储能容量利用率会有明显提升。
最后再分享一个小技巧:容量优化不要一开始就上完整Simulink模型。先用简化的线性传递函数模型把优化框架跑通,确认目标函数、约束、收敛性都没问题后,再把模型细化。否则每次改模型都要重跑一轮几十小时的优化,心态容易崩。这个方向真正花时间的地方不在理论推导,而在把控制策略、仿真模型、优化算法三件事闭环起来,只要闭环通了,后面的结果和结论都是水到渠成的事。