储能仿真系统-需求和设计
-
- 写在前面
- [1. 需求来源:我们要解决什么问题](#1. 需求来源:我们要解决什么问题)
-
- [1.1 仿真范围(端到端)](#1.1 仿真范围(端到端))
- [1.2 可扩展与可配置](#1.2 可扩展与可配置)
- [1.3 联调友好](#1.3 联调友好)
- [2. 总体架构:三层分工](#2. 总体架构:三层分工)
-
- [2.1 模拟层(`EssDeviceSimModel/`)](#2.1 模拟层(
EssDeviceSimModel/)) - [2.2 接口与数据服务层](#2.2 接口与数据服务层)
- [2.3 展示与交互层(`Display/`)](#2.3 展示与交互层(
Display/)) - [2.4 基础设施](#2.4 基础设施)
- [2.1 模拟层(`EssDeviceSimModel/`)](#2.1 模拟层(
- [3. 数据流与线程模型(设计要点)](#3. 数据流与线程模型(设计要点))
-
- [3.1 仿真主循环](#3.1 仿真主循环)
- [3.2 Modbus 侧](#3.2 Modbus 侧)
- [3.3 PCS 功率爬坡](#3.3 PCS 功率爬坡)
- [3.4 并发安全](#3.4 并发安全)
- [4. 配置与点表设计](#4. 配置与点表设计)
-
- [4.1 `appsettings.json`](#4.1
appsettings.json) - [4.2 CSV 点表](#4.2 CSV 点表)
- [4.1 `appsettings.json`](#4.1
- [5. 健壮性与错误处理(设计目标)](#5. 健壮性与错误处理(设计目标))
- [6. 结语](#6. 结语)
- 写在结尾
写在前面
本文对应 EssSimulator 的方案层描述:项目要达成什么目标、模块如何划分、数据如何流动。
1. 需求来源:我们要解决什么问题
1.1 仿真范围(端到端)
在方案层面,本系统面向 储能站(ESS)端到端 的可运行替身,典型包括:
- 多套电池堆(Rack)及 BMS 语义下的簇/包/单体状态演化;
- 多台 PCS:有功/无功指令、爬坡、并网/离网、直流/交流侧关键量、故障与保护检验;
- 主断路器、变压器(含主变与单元变)、计划负载;
- 对外提供 Modbus TCP(以及方案中预留的 IEC61850 等)接口,便于上位机/EMS/网关联调。
1.2 可扩展与可配置
- 拓扑与通道数 由配置(如
Simulator.Devices)驱动,而非写死在代码里; - 点位与内部变量通过 CSV 映射到对象路径,新增寄存器或调整地址时尽量不改核心模型代码;
- 参数化 PCS 物理限值、变压器阻抗与损耗、负载计划、仿真步长与加速倍率 等,便于不同站型复用同一程序骨架。
1.3 联调友好
- 可无可视化运行(
NoGui),便于 CI 或服务器侧长期挂起; - 提供控制台 GUI、命令(如
dpc/esscmd)、自动化脚本入口,缩短「改配置---观察现象」的反馈回路。
2. 总体架构:三层分工
2.1 模拟层(EssDeviceSimModel/)
职责:物理与状态行为。
EnergyStorageSystem:作为托管后台服务,按固定步长推进仿真时钟,编排 PCS、电池、断路器、变压器、负载之间的能量与电气量耦合。- 设备子模型:电池堆、PCS、断路器、变压器、计划负载等,各自封装状态更新与保护逻辑。
2.2 接口与数据服务层
职责:把内部对象暴露成外部世界能消费的协议与数据形态。
- Modbus:从站模拟、按点表读写、worker 与控制线程分工(详见方案文档中的线程模型描述)。
EssSimModelApi/:BMS、PCS/EMU、电表等数据服务与映射,将模型输出整理为对外通道所需结构。- IEC61850(方案/相关工程):对象模型、报告与事件方向的能力预留,与对象路径体系对齐。
2.3 展示与交互层(Display/)
职责:人机可读的状态与调试入口。
- 主接线、电池堆/簇/单体视图、连接信息、日志等页面;
- 命令解析与联调辅助(含基于 JSON 的自动化步骤)。
2.4 基础设施
CSV 解析、TCP 通讯抽象、对象路径解析与聚合、日志(log4net)等,为上述三层提供共用能力。
3. 数据流与线程模型(设计要点)
3.1 仿真主循环
- 以配置的 仿真步长(真实休眠间隔 × 加速倍率)为 tick;
- 典型耦合关系包括:交流侧电流采样与负载叠加 → 断路器逻辑 → 变压器一次侧电压与 PCS 并网条件 → 直流侧与电池堆的电压/电流互换等(具体以
EnergyStorageSystem实现为准)。
3.2 Modbus 侧
- 按模型类型或通道划分 worker,结合优先级队列调度下一次刷新,减少无效写;
- 使用影子缓存(shadow)避免重复写、并在控制通道上记录外部写入的变化;
- 控制线程周期性读取 FC=6 等控制点,解析后写回模拟器内部变量。
3.3 PCS 功率爬坡
- 有/无功可分别由后台线程按阶段目标推进;
- 新设定到达时可打断重算,以贴近真实 PCS 的非阶跃响应;
- 爬坡参数支持全局默认 + 单台 PCS 覆盖,便于 A/B 对比同一策略下的执行差异。
3.4 并发安全
共享状态在关键路径上使用锁保护;线程优先级与睡眠策略用于在「实时感」与 CPU 占用之间折中。
4. 配置与点表设计
4.1 appsettings.json
集中承载:运行期(步长、加速、无头)、协议端口规划、设备清单、PCS/变压器/负载物理与计划参数等。
{
"Simulator": {
"Runtime": {
"SimStepMs": 200,
"Speedup": 1.0,
"NoGui": false
},
"Protocol": {
"BaseBmsModbusPort": 1501,
"BmsPortStep": 1,
"BaseEmuModbusPort": 1601,
"EmuPortStep": 1,
"EmModbusPort": 1500
},
"Devices": [
{
"Name": "Unit-1",
"Pcs": [
{ "Name": "PCS-1A", "PcsRamp": { "Slope": 0.5, "IntervalMs": 100, "DelayMs": 0 } },
{ "Name": "PCS-1B", "PcsRamp": { "Slope": 0.5, "IntervalMs": 100, "DelayMs": 0 } }
],
"Bms": [
{
"Name": "BMS-1A",
"ClusterCount": 12,
"PackCount": 4,
"CellSeriesCount": 104,
"CellParallelCount": 1,
"CellNominalVoltage": 3.2,
"CellNominalCapacity": 314,
"CellInitialSoc": 0.55,
"CellInitialSocRandomRange": 0.03,
"PackInternalResistance": 0.05,
"ClusterInternalResistance": 0.1,
"RackInternalResistance": 0.02
},
{
"Name": "BMS-1B",
"ClusterCount": 12,
"PackCount": 4,
"CellSeriesCount": 104,
"CellParallelCount": 1,
"CellNominalVoltage": 3.2,
"CellNominalCapacity": 314,
"CellInitialSoc": 0.50,
"CellInitialSocRandomRange": 0.03,
"PackInternalResistance": 0.05,
"ClusterInternalResistance": 0.1,
"RackInternalResistance": 0.02
}
]
},
{
"Name": "Unit-2",
"Pcs": [
{ "Name": "PCS-2A", "PcsRamp": { "Slope": 0.5, "IntervalMs": 100, "DelayMs": 0 } },
{ "Name": "PCS-2B", "PcsRamp": { "Slope": 0.5, "IntervalMs": 100, "DelayMs": 0 } }
],
"Bms": [
{
"Name": "BMS-2A",
"ClusterCount": 12,
"PackCount": 4,
"CellSeriesCount": 104,
"CellParallelCount": 1,
"CellNominalVoltage": 3.2,
"CellNominalCapacity": 314,
"CellInitialSoc": 0.60,
"CellInitialSocRandomRange": 0.02,
"PackInternalResistance": 0.05,
"ClusterInternalResistance": 0.1,
"RackInternalResistance": 0.02
},
{
"Name": "BMS-2B",
"ClusterCount": 12,
"PackCount": 4,
"CellSeriesCount": 104,
"CellParallelCount": 1,
"CellNominalVoltage": 3.2,
"CellNominalCapacity": 314,
"CellInitialSoc": 0.45,
"CellInitialSocRandomRange": 0.02,
"PackInternalResistance": 0.05,
"ClusterInternalResistance": 0.1,
"RackInternalResistance": 0.02
}
]
},
{
"Name": "Unit-3",
"Pcs": [
{ "Name": "PCS-3A", "PcsRamp": { "Slope": 0.5, "IntervalMs": 100, "DelayMs": 0 } },
{ "Name": "PCS-3B", "PcsRamp": { "Slope": 0.5, "IntervalMs": 100, "DelayMs": 0 } }
],
"Bms": [
{
"Name": "BMS-3A",
"ClusterCount": 12,
"PackCount": 4,
"CellSeriesCount": 104,
"CellParallelCount": 1,
"CellNominalVoltage": 3.2,
"CellNominalCapacity": 314,
"CellInitialSoc": 0.60,
"CellInitialSocRandomRange": 0.02,
"PackInternalResistance": 0.05,
"ClusterInternalResistance": 0.1,
"RackInternalResistance": 0.02
},
{
"Name": "BMS-3B",
"ClusterCount": 12,
"PackCount": 4,
"CellSeriesCount": 104,
"CellParallelCount": 1,
"CellNominalVoltage": 3.2,
"CellNominalCapacity": 314,
"CellInitialSoc": 0.45,
"CellInitialSocRandomRange": 0.02,
"PackInternalResistance": 0.05,
"ClusterInternalResistance": 0.1,
"RackInternalResistance": 0.02
}
]
},
{
"Name": "Unit-4",
"Pcs": [
{ "Name": "PCS-4A", "PcsRamp": { "Slope": 0.5, "IntervalMs": 100, "DelayMs": 0 } },
{ "Name": "PCS-4B", "PcsRamp": { "Slope": 0.5, "IntervalMs": 100, "DelayMs": 0 } }
],
"Bms": [
{
"Name": "BMS-4A",
"ClusterCount": 12,
"PackCount": 4,
"CellSeriesCount": 104,
"CellParallelCount": 1,
"CellNominalVoltage": 3.2,
"CellNominalCapacity": 314,
"CellInitialSoc": 0.60,
"CellInitialSocRandomRange": 0.02,
"PackInternalResistance": 0.05,
"ClusterInternalResistance": 0.1,
"RackInternalResistance": 0.02
},
{
"Name": "BMS-4B",
"ClusterCount": 12,
"PackCount": 4,
"CellSeriesCount": 104,
"CellParallelCount": 1,
"CellNominalVoltage": 3.2,
"CellNominalCapacity": 314,
"CellInitialSoc": 0.45,
"CellInitialSocRandomRange": 0.02,
"PackInternalResistance": 0.05,
"ClusterInternalResistance": 0.1,
"RackInternalResistance": 0.02
}
]
},
{
"Name": "Unit-5",
"Pcs": [
{ "Name": "PCS-5A", "PcsRamp": { "Slope": 0.5, "IntervalMs": 100, "DelayMs": 0 } },
{ "Name": "PCS-5B", "PcsRamp": { "Slope": 0.5, "IntervalMs": 100, "DelayMs": 0 } }
],
"Bms": [
{
"Name": "BMS-5A",
"ClusterCount": 12,
"PackCount": 4,
"CellSeriesCount": 104,
"CellParallelCount": 1,
"CellNominalVoltage": 3.2,
"CellNominalCapacity": 314,
"CellInitialSoc": 0.60,
"CellInitialSocRandomRange": 0.02,
"PackInternalResistance": 0.05,
"ClusterInternalResistance": 0.1,
"RackInternalResistance": 0.02
},
{
"Name": "BMS-5B",
"ClusterCount": 12,
"PackCount": 4,
"CellSeriesCount": 104,
"CellParallelCount": 1,
"CellNominalVoltage": 3.2,
"CellNominalCapacity": 314,
"CellInitialSoc": 0.45,
"CellInitialSocRandomRange": 0.02,
"PackInternalResistance": 0.05,
"ClusterInternalResistance": 0.1,
"RackInternalResistance": 0.02
}
]
}
]
},
"Pcs": {
"RatedPower": 2508,
"MaxPower": 2508,
"Efficiency": 0.99,
"DcVoltageRangeMin": 1000,
"DcVoltageRangeMax": 1500,
"AcVoltageNominal": 690,
"FrequencyNominal": 50,
"MaxCurrent": 2200,
"GridLossCoefficient": 0.11
},
"Transformer": {
"RatedPower": 2500,
"PrimaryVoltage": 220000,
"SecondaryVoltage": 35000,
"NoLoadLoss": 50,
"LoadLoss": 200,
"ImpedancePercent": 4,
"ReactiveVoltageInfluenceCoefficient": 1.0,
"NoLoadCurrentPercent": 2
},
"UnitTransformer": {
"RatedPower": 2500,
"PrimaryVoltage": 35000,
"SecondaryVoltage": 690,
"NoLoadLoss": 50,
"LoadLoss": 200,
"ImpedancePercent": 4,
"ReactiveVoltageInfluenceCoefficient": 1.0,
"NoLoadCurrentPercent": 2
},
"Load": {
"ActivePowerPlan": -500,
"ReactivePowerPlan": 0
}
}
4.2 CSV 点表
字段通常涵盖:地址、功能码、参数名、缩放、数据类型与宽度、ModelSim 到内部路径的映射等。电表的点位表(.csv)示例如下:
FunctionCode,Address,Type,Size,ParamName,Scale,Description,ModelSim
4,0,int32,32,yc0,1000,A相电压,model=4|arg1=em.PhaseAVoltage|arg2= |arg3= |arg4=100
4,2,int32,32,yc1,1000,B相电压,model=4|arg1=em.PhaseBVoltage|arg2= |arg3= |arg4=100
4,4,int32,32,yc2,1000,C相电压,model=4|arg1=em.PhaseCVoltage|arg2= |arg3= |arg4=100
4,6,int32,32,yc3,1000,AB线电压,model=4|arg1=em.LineVoltageAB|arg2= |arg3= |arg4=100
4,8,int32,32,yc4,1000,BC线电压,model=4|arg1=em.LineVoltageBC|arg2= |arg3= |arg4=100
4,10,int32,32,yc5,1000,CA线电压,model=4|arg1=em.LineVoltageCA|arg2= |arg3= |arg4=100
4,12,int32,32,yc6,1000,A相电流,model=4|arg1=em.PhaseACurrent|arg2= |arg3= |arg4=100
4,14,int32,32,yc7,1000,B相电流,model=4|arg1=em.PhaseBCurrent|arg2= |arg3= |arg4=100
4,16,int32,32,yc8,1000,C相电流,model=4|arg1=em.PhaseCCurrent|arg2= |arg3= |arg4=100
4,18,int32,32,yc9,1000,A相有功功率,model=4|arg1=em.PhaseAActivePower|arg2= |arg3= |arg4=100
4,20,int32,32,yc10,1000,B相有功功率,model=4|arg1=em.PhaseBActivePower|arg2= |arg3= |arg4=100
4,22,int32,32,yc11,1000,C相有功功率,model=4|arg1=em.PhaseCActivePower|arg2= |arg3= |arg4=100
4,24,int32,32,yc12,1000,总有功功率,model=4|arg1=em.TotalActivePower|arg2= |arg3= |arg4=100
4,26,int32,32,yc13,1000,A相无功功率,model=4|arg1=em.PhaseAReactivePower|arg2= |arg3= |arg4=100
4,28,int32,32,yc14,1000,B相无功功率,model=4|arg1=em.PhaseBReactivePower|arg2= |arg3= |arg4=100
4,30,int32,32,yc15,1000,C相无功功率,model=4|arg1=em.PhaseCReactivePower|arg2= |arg3= |arg4=100
4,32,int32,32,yc16,1000,总无功功率,model=4|arg1=em.TotalReactivePower|arg2= |arg3= |arg4=100
4,34,int32,32,yc17,1000,总视在功率,model=4|arg1=em.TotalApparentPower|arg2= |arg3= |arg4=100
4,36,int32,32,yc18,1000,功率因数,model=4|arg1=em.PowerFactor|arg2= |arg3= |arg4=100
4,38,int32,32,yc19,1000,频率,model=4|arg1=em.Frequency|arg2= |arg3= |arg4=100
4,40,int32,32,yc20,1000,正向总有功电能,model=4|arg1=em.ForwardActiveEnergy|arg2= |arg3= |arg4=100
4,42,int32,32,yc21,1000,反向总有功电能,model=4|arg1=em.ReverseActiveEnergy|arg2= |arg3= |arg4=100
5. 健壮性与错误处理(设计目标)
- 影子写与防抖,降低 Modbus 写风暴;
- 分从站隔离失败影响,避免单点通讯异常拖垮整体;
- PCS 过载、电压/温度/孤岛等条件进入故障态的可预期路径;
- 指令限幅与并网前电网可用性检查,减少「非法设定导致状态发散」。
6. 结语
本系统的需求 是:用可配置、可协议化的方式,在桌面上复现 ESS 关键行为,并服务多团队联调。
设计上采用「模型 / 协议与映射 / 展示」分层、显式线程与数据流、对象路径 + CSV 解耦点表,从而在扩展性与可维护性之间取得工程上可落地的平衡。
写在结尾
下一篇《储能仿真系统-功能和用途》将面向使用者,整理具体能力与典型场景。天道酬请,与君共勉!