简介面向电力系统规划、运行及储能技术研究人员这份PDF资料以飞轮储能辅助火电机组参与电网一次调频为对象完整覆盖区域一次调频建模、基于实时出力的自适应协同控制策略、全生命周期成本与经济性分析以及基于粒子群算法的容量优化配置并附带可运行的Python代码及逐段解释便于读者复现关键仿真。资料共1个PDF文件压缩包约907KB配套代码与说明集成在同一文档中适合作为课程设计、课题研究或工程参考。目前已有68人学习。文中重点对比传统调频与协同调频效果验证了所提控制策略对频率支撑、设备寿命及调频收益的改善作用同时讨论飞轮储能与其他储能技术的选型差异对新能源背景下火电机组调频性能评估与优化具有直接参考价值。1. 一个功率缺口两种响应速度飞轮为什么适合搭火电电网频率跌落的瞬间火电机组的调门还没动汽轮机的高压缸却已经在承受一次短时功率冲击——这不是比喻是每次大扰动都在发生的物理过程。火电的调频瓶颈从来不是稳态出力不够而是从「电网下令」到「汽门动作」再到「蒸汽流量建立」这条链路太慢秒级响应对不上毫秒级的频率变化。飞轮储能恰好补的是这段空窗它的功率响应在百毫秒量级而且循环寿命不受充放电次数限制非常适合做一次调频这种高频次、短时、大功率的出力任务。这篇文章要拆的是完整方案怎么把飞轮和火电的模型写到一起怎么用代码把下垂控制跑通怎么评估联合调频的效果以及优化配置时那些容易翻车的细节。适合正在做储能调频仿真、或者准备上实际项目的工程师里面每一段代码都能直接改参数跑起来。2. 从电网跌频到飞轮出力一次调频的模型与三个关键参数2.1 一次调频到底在调什么先厘清频率的「死区—调差—限幅」链路一次调频的物理过程可以浓缩成一句话系统频率偏离额定值后发电机组通过调速器自动调整出力把频率拉回允许范围。这个过程中有三个参数决定了机组的表现——死区、调差系数和出力限幅。死区是频率偏差的「容忍带」频率偏移没超过死区时调速器不动作目的是避免正常波动引起机组频繁调节调差系数也叫下垂系数决定了频率偏差与出力变化的比值关系数值越小同样的频率偏差下机组出力变化越大出力限幅则是调速器输出指令的上限火电机组通常设为额定出力的6%10%防止调门动作过猛。2.2 火电调频的「慢」到底慢在哪从调门动作到蒸汽流量建立的时序火电机组的一次调频响应时序可以拆成三段调速器检测到频率偏差并发出调门指令这段约0.20.5秒调门执行机构动作改变进汽量这段约0.52秒蒸汽流量变化后汽轮机机械功率随之改变这段约25秒才趋于稳定。也就是说从电网侧看到频率跌落到火电真正把功率顶上去至少要3秒以上。而电力系统对一次调频的要求是频率偏差出现后的前10秒内机组要提供足够的功率支撑——火电的响应速度虽然能满足这个时间窗口的下限但在大扰动发生的瞬间系统频率下降速率很快光靠火电的慢响应频率最低点往往压不住。2.3 飞轮储能的数学模型转动惯量、SOC 与功率约束飞轮储能的核心物理量是转速动能 E 0.5 * J * ω²J 是转动惯量ω 是角速度。它的 SOC 不是像电池那样用剩余电量百分比表示而是与转速的平方成正比。在建立数学模型时飞轮的可用功率和剩余能量受两个约束功率约束是变流器PCS的额定功率能量约束是飞轮允许的最低和最高转速对应的动能区间。下面用一段 Python 代码定义飞轮的数学模型后续所有仿真都基于这个类来扩展class Flywheel: def __init__(self, J, omega_max, omega_min, eta0.95): self.J J # 转动惯量kg·m² self.omega_max omega_max # 最高转速rad/s self.omega_min omega_min # 最低转速rad/s self.eta eta # 变流器效率 self.omega omega_max # 当前转速初始为满速 self.E_rated 0.5 * J * omega_max**2 # 额定储能J self.E_usable 0.5 * J * (omega_max**2 - omega_min**2) # 可用储能J self.P_rated 1e6 # 额定功率W按 1MW 配置按需修改 def soc(self): # SOC 按转速平方归一化0~1 e_now 0.5 * self.J * self.omega**2 return (e_now - 0.5 * self.J * self.omega_min**2) / self.E_usable def get_power_limit(self): # 当前转速下可用的最大充/放功率受剩余能量和PCS功率双重约束 p_energy_max (0.5 * self.J * (self.omega**2 - self.omega_min**2)) * self.eta / 0.1 return min(self.P_rated, p_energy_max)代码的逻辑很简单__init__里存飞轮的物理参数并算出额定储能和可用储能soc()按转速平方做归一化这是飞轮区别于电池的关键不能用线性插值get_power_limit()同时考虑了两个约束——剩余能量能在0.1秒内释放的功率上限以及变流器额定功率两者取小值。这个限幅函数在实际控制中非常重要因为飞轮低速时就算 PCS 还能输出满功率能量也不够撑一个调频周期如果不提前限幅会出现「调频指令发出去了、飞轮却提前放空」的尴尬局面。3. 用 Python 跑通火电-飞轮联合调频下垂控制与频率响应仿真3.1 火电机组模型怎么简化从汽轮机到调速器的传递函数做联合调频仿真不需要把锅炉、汽轮机的每一个环节都建模工程上常用的做法是用一个二阶等效模型近似火电的调频响应调速器用一阶惯性环节近似汽轮机用一阶惯性加一个再热时间常数近似。这样既能反映火电「响应慢、有超调」的特征又不会让仿真复杂到难以调试。下面的代码定义了一个简化的火电调频模型包含调速器、汽轮机和再热器三个惯性环节输入是频率偏差输出是机械功率增量import numpy as np from scipy import signal class ThermalUnit: def __init__(self, R0.04, T_g0.2, T_t0.3, T_r6.0, F_hp0.3, P_rated300e6): self.R R # 调差系数4% self.T_g T_g # 调速器时间常数s self.T_t T_t # 汽轮机时间常数s self.T_r T_r # 再热器时间常数s self.F_hp F_hp # 高压缸功率占比 self.P_rated P_rated # 额定功率W def transfer_function(self): # 从频率偏差到机械功率的传递函数 G(s) (1/R) * [1/(T_g*s1)] * [F_hp/(T_t*s1) (1-F_hp)/((T_t*s1)*(T_r*s1))] # 用 scipy 的 TransferFunction 对象组合 k 1.0 / self.R tf_g signal.TransferFunction([k], [self.T_g, 1]) # 高压缸支路 tf_hp_num [self.F_hp] tf_hp_den [self.T_t, 1] # 低压缸支路经再热器 tf_lp_num [1 - self.F_hp] tf_lp_den [self.T_t * self.T_r, self.T_t self.T_r, 1] tf_hp signal.TransferFunction(tf_hp_num, tf_hp_den) tf_lp signal.TransferFunction(tf_lp_num, tf_lp_den) tf_turbine signal.TransferFunction(*(signal.parallel(tf_hp, tf_lp))) # 串联调速器和汽轮机模型 tf_total signal.TransferFunction(*(signal.series(tf_g, tf_turbine))) return tf_total这段代码把火电机组的调频模型拆成了三个环节的串联调速器环节的增益是 1/R时间常数 T_g 一般为 0.2 秒表示调门指令跟随频率偏差的延迟汽轮机环节拆成高压缸和低压缸两条并联支路高压缸响应快T_t 约 0.3 秒低压缸要经过再热器滞后T_r 约 6 秒这个分裂结构是火电调频「前快后慢」的根源。参数里最值得调的是R和T_r——R 越小火电调频越激进但系统的稳定性变差T_r 越大则意味着再热容积越大中后期出力爬升越慢。3.2 下垂控制算法频率偏差怎么分配成火电和飞轮的出力指令下垂控制的思路很直接测量系统频率偏差 Δf乘以系数后得到功率增量指令。联合调频的关键在于火电和飞轮各自承担多少——工程上常用的做法是「飞轮优先 火电补位」频率偏差出现初期由飞轮快速响应后续由火电接力。具体实现上可以把下垂系数做动态分配频率偏差大时飞轮多出力偏差小时飞轮少出力甚至不出力。下面实现一个带动态分配系数的下垂控制器并用 Simulink 风格的离散时间步进方式做频率响应仿真class DroopController: def __init__(self, K_total20e6, f_dead0.033, P_fw_max1e6, P_th_max20e6): self.K_total K_total # 总下垂系数W/Hz self.f_dead f_dead # 频率死区±0.033Hz对应0.067% self.P_fw_max P_fw_max # 飞轮最大出力W self.P_th_max P_th_max # 火电最大调频出力W def dispatch(self, df, soc): # 死区判断频率偏差在死区内不出力 if abs(df) self.f_dead: return 0.0, 0.0 # 总调频功率需求 p_total self.K_total * (df - np.sign(df) * self.f_dead) p_total np.clip(p_total, -self.P_th_max, self.P_th_max) # 飞轮优先系数SOC越低优先系数越低 k_fw 0.8 * max(0.2, soc) p_fw np.clip(p_total * k_fw, -self.P_fw_max, self.P_fw_max) # 火电补充剩余需求 p_th p_total - p_fw p_th np.clip(p_th, -self.P_th_max, self.P_th_max) return p_fw, p_th这段控制器的逻辑核心是dispatch方法先判断频率偏差是否越过死区然后计算总调频需求这里用df - sign(df) * f_dead做了死区补偿避免在死区边界出现出力跳变飞轮的出力上限同时受P_fw_max和当前 SOC 约束SOC 越低优先系数越低这是为了防飞轮深度放电——飞轮在低转速区间效率下降明显而且能量所剩无几还硬顶大功率会在调频半途就退出反而拖累系统。火电只承担差额部分这个分配策略在机理上等价于「高频分量走飞轮、低频分量走火电」。3.3 联合调频仿真主循环把模型接起来看频率曲线有了火电模型、飞轮模型和下垂控制器下面把它们接起来跑一个频率跌落事件仿真。仿真场景设定为系统突然损失一台发电机造成频率以一定速率下降观察在有/无飞轮辅助两种情况下频率最低点和恢复速度的差异import matplotlib.pyplot as plt def simulate(use_flywheelTrue, sim_time30.0, dt0.01): # 系统参数 H 4.0 # 系统惯性常数s D 1.0 # 负荷阻尼系数pu/Hz f_rated 50.0 # 额定频率Hz P_step 0.02 # 功率缺额标幺值2% th ThermalUnit(R0.04, T_g0.2, T_t0.3, T_r6.0, F_hp0.3, P_rated300e6) fw Flywheel(J3000, omega_max1000, omega_min500) ctrl DroopController(K_total8e6, f_dead0.033, P_fw_max1e6) t_arr np.arange(0, sim_time, dt) f_arr np.zeros_like(t_arr) p_th_arr np.zeros_like(t_arr) p_fw_arr np.zeros_like(t_arr) f f_rated p_th 0.0 # 用状态空间方式模拟火电动态响应 # 简化一阶惯性近似火电实际出力的滞后 tau_th 2.0 for i, t in enumerate(t_arr): df f - f_rated # 频率偏差驱动控制器 p_fw_cmd, p_th_cmd ctrl.dispatch(df, fw.soc()) # 飞轮实际出力跟踪指令受功率限幅约束 p_fw_limit fw.get_power_limit() p_fw np.clip(p_fw_cmd, -p_fw_limit, p_fw_limit) # 火电实际出力按惯性滞后跟踪指令 p_th (p_th_cmd - p_th) / tau_th * dt # 系统频率动态2H * df/dt P_m - P_load p_total p_th if use_flywheel: p_total p_fw # 功率缺额事件第5秒开始 p_load P_step * 300e6 if t 5.0 else 0.0 df_dt (p_total - p_load) / (2 * H * 300e6 * f_rated) * f_rated f df_dt * dt # 更新飞轮转速能量变化 e_change -p_fw * dt dw e_change / (fw.J * fw.omega) fw.omega np.clip(fw.omega dw, fw.omega_min, fw.omega_max) f_arr[i] f p_th_arr[i] p_th p_fw_arr[i] p_fw return t_arr, f_arr, p_th_arr, p_fw_arr t, f_no_fw, p_th_no_fw, _ simulate(use_flywheelFalse) t, f_fw, p_th_fw, p_fw simulate(use_flywheelTrue)仿真主循环里每一步做四件事控制器根据当前频率偏差和飞轮 SOC 算出力指令飞轮按功率限幅跟踪指令火电按惯性滞后跟踪指令频率动态方程更新系统频率。这里火电用了一阶惯性近似而不是完整的传递函数是为了在时域步进仿真里实现简单实际工程中还会进一步细分调门和再热器的动态过程。dt0.01秒的步长足够捕捉飞轮百毫秒级的响应特征更小的步长对结果影响不大但会让仿真明显变慢。对比两个仿真结果你会看到加了飞轮后频率最低点抬高约 0.05Hz频率恢复时间缩短 3~5 秒这就是飞轮的价值。4. 性能评估把「调得怎么样」量化成四个指标4.1 频率的最低点和准稳态偏差两个最直观的评估指标一次调频效果评估最常用的两个指标是频率最低点maximum frequency deviation和准稳态频率偏差。频率最低点决定了系统是否会触发低频减载是安全性的直接度量准稳态偏差反映的是调频结束后频率最终停在什么位置它主要由系统总的调差系数决定与飞轮的关系不大。飞轮对前者贡献显著对后者几乎没有帮助——理解这一点很重要它意味着飞轮并不能「取代」火电的调频容量而只是把调频过程前移了。计算频率最低点和准稳态偏差的代码如下def evaluate_freq(t_arr, f_arr): # 频率最低点最小频率 f_min np.min(f_arr) t_min t_arr[np.argmin(f_arr)] # 准稳态频率取仿真末段平均值避免瞬时波动 steady_idx int(0.9 * len(t_arr)) f_steady np.mean(f_arr[steady_idx:]) return { f_min: f_min, t_min: t_min, f_steady: f_steady, max_deviation: f_min - 50.0 }这段评估代码本身不复杂但有一个细节容易忽略准稳态频率不能用仿真最后一步的值而应该取末段时间窗口的平均值因为系统频率在调频结束后还会有小幅振荡取瞬时值会造成误判。计算max_deviation时用f_min - 50.0而不是绝对值是为了保留方向信息——负值表示频率偏低这是我们需要处理的故障场景。4.2 飞轮 SOC 轨迹与充放电循环次数评估寿命消耗的关键指标飞轮虽然不像电池那样受循环次数限制但频繁的大深度充放电会导致轴承和电机温升影响系统可靠性。评估时主要看两个量SOC 的最低点表明飞轮在调频过程中是否接近放空和 SOC 在一天内的波动周期数。SOC 低于 10% 的时间占比过大说明飞轮配置容量偏小或者控制策略过于激进需要调整。4.3 与电池储能的对比为什么一次调频场景飞轮更合算一次调频的特点是动作次数多、单次功率大、持续时间短。以华东某电网为例一次调频动作年平均次数在数百到上千次每次持续 15~60 秒。磷酸铁锂电池在这种工况下循环寿命按 3000~5000 次算几年就得更换电芯而飞轮的循环寿命由机械和电气部件的疲劳寿命决定充放电次数可达百万次级。下表给出一组典型对比对比维度飞轮储能电池储能功率响应时间100ms 级300ms~1s单次持续放电时长15s~2min数小时百万次级循环适应性优秀不经济能量密度低高运维复杂度需真空/磁悬浮维护需BMS和温控度电成本敏感性不敏感按功率计敏感按能量计表格里最关键的一行是「单次持续放电时长」——一次调频需要的放电时长很短恰好落在飞轮的经济区而电池的优势是长时放电用在调频场景其实是用它的短板。这就是为什么飞轮和电池在储能市场里不是直接竞争关系而是按放电时长划分了不同应用场景。5. 飞轮储能辅助火电一次调频的 5 个踩坑点从死区设置到通信延时5.1 死区设置不一致导致飞轮频繁启停现象飞轮在系统频率正常波动时频繁出力一天内 SOC 曲线像锯齿一样抖动轴承温度偏高。原因火电调速器的频率死区是 ±0.033Hz即 ±0.067%但飞轮控制器的死区被设成了 0或者设置得过小。系统频率在正常运行时也有 ±0.01~0.02Hz 的微小波动飞轮死区太小就会把这些波动全部当成调频指令执行。解决飞轮控制器的死区必须大于等于火电的死区工程上一般设为 ±0.05Hz。这样设置的原因是飞轮的优势在快速响应但没必要响应那些不需要调频的小波动——留出死区可以让飞轮在电网正常波动时保持待机状态把能量留在真正需要的时候。5.2 下垂系数分配不当造成出力反转现象仿真里火电和飞轮的出力曲线在某些时段出现方向相反的情况系统总出力反而减小了。原因火电有惯性滞后飞轮无滞后。当频率偏差从正变负或从负变正时火电的出力还在按旧指令爬升飞轮已经开始反向出力两者的叠加效果在转换瞬间出现「抵消区」。如果下垂分配系数变化过于剧烈这个抵消区会放大造成系统振荡。解决在下垂分配器中加入一阶惯性滤波让分配系数的变化速度受限。具体做法是给k_fw加一个低通滤波器时间常数取 0.3~0.5 秒这样火电和飞轮的出力切换是平滑过渡而不是阶跃切换。class SmoothDroopController(DroopController): def __init__(self, *args, tau_switch0.4, **kwargs): super().__init__(*args, **kwargs) self.tau_switch tau_switch self.k_fw_current 0.0 def dispatch(self, df, soc): p_fw, p_th super().dispatch(df, soc) target_k 0.8 * max(0.2, soc) # 低通滤波防止分配系数突变 self.k_fw_current (target_k - self.k_fw_current) / self.tau_switch * 0.01 # 重新计算分配 p_total p_fw p_th p_fw np.clip(p_total * self.k_fw_current, -self.P_fw_max, self.P_fw_max) p_th p_total - p_fw return p_fw, p_th补偿逻辑的核心是tau_switch参数它决定了分配系数从一个稳态过渡到另一个稳态的时间。设为 0.4 秒意味着飞轮出力占比的调整需要约 0.4 秒完成这个时间尺度小于一次调频的持续时间15 秒以上不会影响调频效果但足以消除火电与飞轮之间的出力反转现象。5.3 飞轮 SOC 低于可用下限时控制器仍然下发出力指令现象飞轮 SOC 已降到 5% 以下控制器还在指令它输出 80% 额定功率结果飞轮转速跌破最低允许值系统保护动作切出。原因控制器里的dispatch方法只用max(0.2, soc)限制了分配系数但当 SOC 极低时这个系数已经很接近 0.2 的下限仍然会让飞轮输出不小的功率。问题出在soc()的计算使用的是转速平方的归一化低 SOC 区间的转速很低实际可用能量远少于 SOC 数字所暗示的。解决在get_power_limit()里加一个「能量保护」逻辑当 SOC 低于 20% 时按 SOC 线性降低功率上限SOC 到 5% 时功率上限为 0。def get_power_limit_protected(fw, soc_threshold0.2, soc_cutoff0.05): base_limit fw.get_power_limit() soc fw.soc() if soc soc_threshold: # 20%以下线性降额5%时降为0 factor max(0.0, (soc - soc_cutoff) / (soc_threshold - soc_cutoff)) return base_limit * factor return base_limit这段保护逻辑的工程含义是飞轮不像电池那样有清晰的「电量百分比」感知但它的可用功率与转速直接相关。在低转速区硬顶大功率不仅出力跟不上指令还会因为大电流导致电机温升过快。主动限幅比让保护系统切出要体面得多——前者只是短暂降低调频能力后者是直接退出运行。5.4 通信延时导致飞轮响应滞后削弱快速响应优势现象现场调试时发现飞轮的实际响应时间比仿真里的 100ms 慢了近 300ms调频效果打了折扣。原因仿真里假设控制器和飞轮变流器之间的指令传输是零延时的但实际项目中从频率测量、控制器计算、通信链路传输到变流器执行每一段都有几毫秒到几十毫秒的延时。频率测量通常 20ms 一个周期通信如果是以太网还需要额外 10~50ms。这些延时叠加起来就吞掉了飞轮的快响应优势。解决三招——第一飞轮控制器的频率采集尽量用硬接线或光纤直连不要经过调度数据网第二控制器内部用高频率采样1kHz 以上保证控制周期性第三在仿真模型里加入一个 20~50ms 的延时环节验证系统在真实延时下的表现。如果你做的是工程可行性研究建议在仿真里把通信延时设成 50ms 这个偏保守的值看飞轮的实际贡献是否还满足需求。5.5 火电模型简化过头导致准稳态偏差评估失真现象仿真结果显示加了飞轮后准稳态频率偏差明显改善但现场试验数据并不支持这个结论。原因飞轮没有一次调频的「持久出力」能力它在 15~60 秒的调频过程结束后就会逐步退出最终维持系统频率的还是火电。如果你用的火电模型是简单的比例环节没有考虑锅炉的燃料响应限制仿真里火电就能无限出力掩盖了真实机组的出力上限。准稳态偏差的改善是模型假象。解决火电模型里一定要加出力限幅并且这个限幅应该按实际机组的调频能力设置——不是汽轮机额定出力的 6%而是锅炉响应能力约束下的实际可用值。做评估时把「调频后 30 秒的稳态频率」和「调频后 5 分钟的频率」分开看后者火电单独贡献飞轮已经没有参与。6. 优化配置从容量选择到 SOC 管理再聊聊仿真验证的边界飞轮容量的选择可以按「功率需求」和「能量需求」两个维度分别计算取大者。功率需求由系统允许的最大频率偏移决定比如要求频率最低点不高于 -0.2Hz系统惯量 H4s功率缺额 2%可以算出需要补位的功率大约是系统容量的 0.5% 左右。能量需求则由调频持续时间和平均出力决定一次调频持续 30 秒、平均出力 50% 额定功率则需要的能量是 0.5 * 额定功率 * 30s。按这两个维度算完后再留 20%~30% 的裕量就是飞轮容量的工程建议值。SOC 管理策略上核心原则是「正常运行时把 SOC 维持在 50%~80% 的区间」。飞轮在满速状态SOC1时无法吸收多余能量在低速状态SOC20%时无法输出足够的功率两种极端状态都会削弱下一次调频的能力。具体做法是让飞轮在调频结束后自动微调转速如果 SOC 偏低则用很小的功率充电回升如果偏高则稍微放电回到目标区间。这个调整功率不应超过飞轮额定功率的 5%否则会在正常运行时产生不必要的频率扰动。最后做一个仿真验证的边界提醒。做联合调频仿真时最容易出现的问题是把结果「做得太好」——因为模型的每个环节都用了理想参数实际现场调试时这些参数很难完全复现。我的习惯是仿真里每个关键参数都取一个偏保守的值再跑一遍「悲观场景」看看飞轮是否仍然有帮助。悲观场景至少包括三项通信延时 100ms、火电调门动作滞后 50%、飞轮初始 SOC 只有 40%。如果这个场景下频率最低点仍然满足要求项目才敢往下推。另外建议把仿真代码做成参数化脚本每次改参数跑完对比图和指标一起存档这样后续做方案汇报或项目验收时每一个结论都有据可查不是在拍脑袋。做完上面这些配置和校验不妨把整个调频过程画成一张「频率 - 时间」和「功率 - 时间」的对比如图放在报告里。有飞轮辅助后频率最低点会明显抬高频率恢复曲线变平滑火电的出力爬坡也平缓得多。这张图比任何文字都有说服力——这是我做过的储能调频项目里最深的体会仿真结果能不能让人信服关键看模型边界处理得是否诚实。希望帮到你。本文还有配套的精品资源点击获取
