# 储能系统 EMS 核心架构解析
充放电控制、防逆流、防过载与 PID 调节

* * *

在现代储能电站与工商业储能系统中，能量管理系统（EMS）扮演着"大脑"的角色，负责在电池硬件、电网以及本地负载之间进行智能调度。

本文将深入解析一个典型 EMS 工程项目的核心源代码逻辑，重点探讨从底层 BMS 硬件限制采集，到中层防逆流、防过载及 PID 功率平滑，再到上层状态机驱动的完整业务链路。

* * *

## 一、整体代码链路与核心思路

整个充放电过程的核心思路可以用一条自底向上的数据流和控制流来概括：

1.  **硬件限制层（CAN 协议解析）**：通过协议（如 Infy BMS、PL BMS 等）读取底层电池的最大允许充放电电流（`fAllow_MaxChargeCurr`），以及禁止充放电标志位（`bIsBatt_ChargeForbidden` / `bIsBatt_DisChargeForbidden`）。
    
2.  **EMS 能量管理层（策略运算）**：在 `ems_management.c` 中，结合电网表和系统关口表的数据，计算当前是否存在逆流和过载情况，动态调整当前可用的总充电功率（`fTotal_PessChgAvaliable`）和放电限制功率（`fTotal_PessDischgLmt`）。
    
3.  **PID 闭环调节层**：利用设定的 Kp、Ki 等参数，消除目标功率与实际计量表功率的偏差，输出最终平滑过的充放电目标值（`fTotal_PessChg_PidOut`）。
    
4.  **状态机执行层（State Machine）**：`st_batt_statemachine.c` 根据上述所有约束、策略及当前电芯状态，驱动电池系统在 Idle、Charging、Discharging 等不同状态之间安全切换。
    

* * *

## 二、底层硬件约束：CAN 报文与 BMS 标志位

EMS 的首要原则是绝对的安全，硬件自身的保护优先级永远是最高的。

在底层的 CAN 驱动代码（如 `can_infy_batt.c`、`can_pl_batt.c`）中，系统会实时解析 BMS 报文，将其转化为通用结构体：

```c
pSingleRunInfo->bIsBatt_ChargeForbidden    = s_pl_BattRunData[n].bIsBatt_ChargeForbidden;
pSingleRunInfo->bIsBatt_DisChargeForbidden = s_pl_BattRunData[n].bIsBatt_DisChargeForbidden;
```

如果 BMS 上报了不允许充电（例如电池充满、单体过压、温升过高或 BMS 触发保护），`bIsBatt_ChargeForbidden` 就会被置为 `TRUE`。当该标志位为 `TRUE`，或允许充电电流 `fAllow_MaxChargeCurr < 5.0A` 时，EMS 系统无论处于何种计划中，都会立刻下发停止指令（`GRP_ACDC_STOP`）。

* * *

## 三、EMS 策略控制：防逆流与防过载逻辑

EMS 不仅要保护电池，还要保护电网变压器。防逆流（防止储能向电网倒送电）和防过载（防止市电输入超出变压器容量）是 `ems_management.c` 中的核心模块。

### 3.1 负荷功率计算

通过函数 `calcOverLoadAndReflux_By_Grid2CabMeter`，系统读取电网关口表（`f_PgridMeter`）和储能机柜表（`f_PcabMeter`）来推导负载功耗：

```c
pEMS->fPacload4Dischg = pEMS->f_PgridMeter - pEMS->f_PcabMeter; // 用于放电防逆流
pEMS->fPacload4Chg    = pEMS->f_PgridMeter - pEMS->f_PcabMeter; // 用于充电防过载
```

### 3.2 功率限幅推算

计算出负载功率后，系统结合保护阈值 `fPreProt_Chrg` 和 `fPreProt4RefluxAndOverLoad` 限制最终充放电功率：

*   **防过载（限制充电）**：若判定即将触发过载，在 `Calc_ESS_ChgLmtPower` 中会限制 `pEMS->fTotal_PessChgAvaliable`。当进入防过载状态时，可用充电功率甚至会被乘以 **0.8 系数**强制降载。
    
*   **防逆流（限制放电）**：在 `Calc_ESS_DischgLmtPower` 中，放电限制值被设定为：
    
    ```plaintext
    fTotal_PessDischgLmt = (fPacload4Dischg - fProt) × 输出转换效率
    ```
    
    这保证了电池释放的能量刚好覆盖负载需求，且留有安全裕度（`fProt`），坚决不向电网倒送电。
    

* * *

## 四、PID 调节：让功率输出平滑且精准

为了应对电网负载的瞬时波动，使 PCS 充放电功率柔性跟随而不发生震荡，系统引入了 PID 控制环（`Power_Control_Loop`）。

### 4.1 核心参数

| 参数 | 说明 |
| --- | --- |
| `Kp`（比例项） | 根据误差实时产生反应 |
| `Ki`（积分项） | 消除稳态误差 |
| `fDead_Band`（死区） | 当目标功率与表计功率差异过小时，误差视为 0，防止小幅度频繁波动 |

### 4.2 核心补偿逻辑

根据当前工况（恒功率、防逆流或平滑输出模式），PID 计算误差值 `error = target_power - meter_power`，经死区和分离阈值处理后得出补偿量：

```c
float p_term_delta = pPidParams->Kp * (error - pPID_Ctx->fPrevError);
float i_term_delta = pPidParams->Ki * error;
pPID_Ctx->fCompensation += (p_term_delta + i_term_delta);
```

对 `fCompensation` 进行上下限幅后，最终平滑输出功率赋值给：

*   `fTotal_PessChg_PidOut`（充电应用）
    
*   `fTotal_PessDischg_PidOut`（放电应用）
    

> **注意**：PID 输出值才是真正下发给底层节点分配功率的控制基准。

* * *

## 五、电池状态机：动作的最终执行者

底层硬件标志位、中层 EMS 逻辑和 PID 目标值最终汇总在 `st_batt_statemachine.c` 的状态机中执行。主循环 `STBatt_Management` 根据定时轮询遍历各电池节点，切换执行以下几个核心状态：

### 5.1 OnIdle（空闲待机）

检查各种启停条件。如果收到 EMS 计划任务指令且不处于保护状态，会尝试寻找启动条件。对于离网请求，跳转至 OnOffGrid。

### 5.2 OnWaitCharge（等待充电）

下发 `GRP_ACDC_RECTIFY_START` 后等待 PCS 启动。若在设定时间内输出电流 > 2A，则平滑过渡至 `STBATT_STATE_IN_CHARGING`；否则启动失败超时，回退至 Idle。

### 5.3 OnCharging（充电中）

持续跟踪 PID 下发的平滑电流，同时实时监控停机条件。满足以下任意条件，立刻关停 PCS：

*   硬件级禁止：`pSingleRunInfo->bIsBatt_ChargeForbidden == TRUE`
    
*   管理计划结束：`IsBatt_Plan2_StopCharge() == TRUE`（如 SOC 超过设定的 StopSOC）
    
*   告警和故障：发生通信异常或严重 BMS 告警
    

### 5.4 OnDischarging（放电中）

防逆流动作和放电过程在此闭环。若发生禁止放电标志（`bIsBatt_DisChargeForbidden`），或 `IsBatt_Plan2_CutDischarge()` 判断达到保护 SOC 底线，则立刻下发停止放电（`GRP_ACDC_STOP`）。

### 5.5 OnFaulted / OnOffGrid

异常容错状态及脱网运行的特殊处理状态。

* * *

## 结语：一条闭环的安全防线

梳理整个控制链路，可以看到一个成熟储能系统的多层防御机制：

*   **CAN 协议层**：保障单体电芯绝不越界
    
*   **EMS 管理层**：守护电网和负荷，防止逆流和过载
    
*   **PID 平滑控制**：提升电能输出的质量和柔性
    
*   **状态机**：负责一切动作的原子化与安全调度
    

每一步既独立运作，又紧密耦合，共同确保整个储能电站的长效安全运行。
