增量式 PI 控制器在储能功率调节中的工程实践
一、我为什么在 EMS 里选「增量式」而不是「位置式」
做储能 EMS 功率闭环时,我面对的不是教科书上的理想控制对象,而是:电表、PCS、并网点功率的测量噪声、通信抖动、策略目标 target_power 的阶跃变化,以及充放电两套完全不同的对象增益。
若直接把 PID 写成位置式——每一步都算一个「绝对输出」:
在工程上会遇到两个老问题:
- 目标或工况切换时,积分项里的历史误差会「顶」在新工况上,表现为输出猛跳或长时间拖尾;
- 输出端已受上层限幅约束(功率上下限、SOC、并网点约束),位置式积分在饱和边界上很容易 windup,补偿量很难「体面地」退回来。
增量式(velocity form)的核心思想是:不直接维护「绝对控制量」,而维护「本周期相对上一周期要加多少修正」。在我们代码里,比例项用的是误差变化量:
积分项用的是当前误差的一步累加,二者合成 output_delta,再叠加到状态量 fCompensation 上,也就是「补偿量跨周期累积」。
这样做的好处,我用工程语言概括三条:
第一,工况切换时,旧误差的历史不会以「一整块积分」压在新目标上。 当然仍需配合清零与限幅,但行为比位置式更可控。
第二,输出端饱和时,增量式 + 显式限幅更容易做 anti-windup。 补偿被钳住时,至少不会每周期再往积分里灌无解的误差。
第三,和功率指令的语义贴合。 EMS 往往先有一个「策略给出的目标功率」,PID 只负责「在目标附近做细调」;把修正量做成 fCompensation 累加在 target_power 上,结构清晰:raw_output = target_power + fCompensation。
位置式不是不能用,但在「目标频繁跳、约束多、执行器非线性重」的储能场景里,增量式更常见——不是因为它数学上更优,而是它把「大目标」和「小修正」拆开了,调试时脑子更清楚。
二、对照代码:这条环里到底算什么 PI
在 Power_Control_Loop() 里,误差定义为 error = target_power - meter_power(表计侧功率),充放电分支选用不同的 PID 参数(stPIDChgParams / stPIDDischgParams)。比例增量与积分增量合成后写入补偿:
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);
完整的输出链路是:
- 计算
p_term_delta和i_term_delta,合成后累加进fCompensation; - 对
fCompensation做fCompensation_Lmt对称限幅; - 合成
raw_output = target_power + fCompensation; - 对
raw_output再做fMaxOutput_Lmt/fMinOutput_Lmt输出限幅。
从控制理论严格来说,这是「增量型 PI」的一种离散实现。其中积分通道写成 ,等价于在实现里把采样周期吸收进 Ki 的标定。
有一点我必须说清楚:调参时不要把 Ki 当作课本上的 ,而要把它当作「每步往补偿里塞多少」的工程增益,否则会和仿真对不上,现场整定也会越调越迷糊。
三、死区:小误差不等于小问题
电表功率、PCS 反馈在几十到几百瓦上抖动是常态。如果死区设为零,PI 会在噪声带上做无意义的高频修正——PCS 收到的是一串小锯齿指令,现场表现为继电器式抖动或效率损失。
我们在参数里显式放了 fDead_Band:当 fabsf(error) 小于死区时,直接把 error 置零。
这不是「偷懒」,而是承认测量与执行分辨率有限,控制系统不应比传感器更神经质。
工程上我的死区不会只定一个数:充放电、轻载重载、是否处于并网点功率闭环模式,噪声水平各不相同。此外,死区还会和「目标稳定判据」配合使用——代码里有 fPrevTarget 与 nTargetStableCount 一类逻辑,目标在抖动时先别急着让 PI 当真,否则等于追着噪声跑。
四、积分分离:大误差时先别积分
积分分离(integral separation)的经典动机是:误差很大时,积分通道会疯狂累计,等误差掉下来时,积分里已经塞满了「过冲燃料」,表现为大幅超调或长时间反向功率输出。
实现上通常是:当 |error| 超过 fIntegral_Term_Sepa_Thres,令 i_term_delta = 0,只允许比例项工作,把系统先「拉回到线性区」。
在我们工程里,积分分离和死区是两个不同维度的保护:
- 死区解决「小误差噪声」问题;
- 积分分离解决「大误差积分饱和风险」问题。
从实际整定经验来看,分离阈值要大于死区,且需要与 PCS 响应时间匹配——阈值太小,积分永远起不来,稳态误差消不掉;太大,大偏差阶段响应又太慢。
五、比例分离:名字容易误会,工程意图要拆清
「比例分离」这个词在教科书里的讲法是:超大偏差时减弱比例,避免动作过猛。但我们仓库里的实现与此略有不同:
当 |error| 超过 fProportional_Term_Sepa_Thres 时,不仅把 p_term_delta 置零,还把 error 置零——其效果是后续积分项也按「当前被清零后的误差」计算。在大偏差区间,实质上会同时关掉 P 与 I 的增量贡献,与教科书里「纯积分」的说法并不相同。
我更愿意把这种策略解释为:在极端偏差区间,先切断 PI 的增量注入,把行为交给上层目标刷新、限功率与其它保护——避免在并网点功率已经异常时,闭环还在持续堆补偿,让问题越来越难收。
最后有一条必须写进调试文档的铁律:比例分离阈值、积分分离阈值、死区三者的相对大小要画在一张表上,否则半年后你自己都忘了为什么充放电两套参数不对称。
六、补偿量 fCompensation:跨周期累积、限幅与 Anti-Windup
fCompensation 是这条环的「记忆」,它承载着历史误差的所有累积效应。围绕它有两层限幅,顺序至关重要:
- 先限
fCompensation:每周期加完output_delta后,立刻对fCompensation做对称限幅; - 再限
raw_output:合成后的输出根据 PCS 能力做最终上下限约束。
限幅顺序不能颠倒——若只做输出限幅、不限补偿,积分状态会在看不见的地方胀满;若只限补偿、不审视输出,又可能和 PCS 实际能力脱节。
Anti-windup 在文献里有很多变体(条件积分、反算、跟踪抗饱和)。在嵌入式 EMS 里,我常用的策略是:先限补偿、再限输出,并在工况切换或禁能时清零状态。代码路径里,当 PID 未使能、目标未稳定、或接近总功率限时,会把 fPrevError、fCompensation 等清掉或暂停误差累积。这不是高深的算法,而是用状态机把 PI 放在「该工作的时候」才工作。
此外还有一个「小目标清零补偿」的判据:当 fabsf(target_power) < fClearCompensationThres 时,把 fCompensation 置零。这是为了避免目标回到近零时,历史补偿还挂在上面,造成莫名其妙的充放电指令输出。
七、Kp、Ki 怎么整定:Ziegler-Nichols 与现场经验
Ziegler-Nichols(临界比例度法)在课堂里很经典,但在储能功率环,我很少照搬。原因很现实:
- 对象随 SOC、温度、电池内阻、PCS 工作点变化,名义传递函数一直在漂;
- 现场不允许为了 ZN 做「破坏性的临界振荡试验」;
- 功率环往往还有外环策略、内环电流环,ZN 假设的单回路理想模型根本不成立。
我更常用的是分段手动法,分四步走:
第一步,Ki 小、Kp 中,保证不发散,观察表计功率跟踪目标的时间常数。
第二步,加大 Kp,提高响应速度,直到出现明显振荡或噪声放大,再往回退一档。
第三步,略增 Ki,消除稳态误差,观察大阶跃下是否超调、补偿是否顶满限幅。
第四步,微调死区与分离阈值,用现场数据(CSV 录波)复盘,覆盖轻载、重载、充放切换等典型工况。
第一人称结论:ZN 给我的是数量级,真正上线靠的是工况覆盖与限幅配合。
八、AI 调参:贝叶斯优化与强化学习,我怎么看
贝叶斯优化(BO)适合「仿真代价高、试验次数有限」的场景:把 (Kp, Ki, 死区, 分离阈值) 当作超参数,用高斯过程建模目标函数(例如 IAE、超调量、约束违反惩罚的加权和),在可行域内主动采样。它的优点是样本效率高于网格搜索;缺点是若仿真模型和真机偏差大,BO 找到的是「假最优」,迁移到实机会直接翻车。
强化学习(RL)适合「策略本身也要学」的问题。但直接用 RL 替代 PI 控制器,在储能工程里我持谨慎态度——安全约束与可解释性是电网侧项目的硬门槛,甲方和电网公司不会接受一个黑盒在控制功率指令。更现实的路线是:
- RL 或 BO 只调外层少量参数,PI 结构保持不变;
- 或者 BO 在硬件在环(HIL)上跑,再迁移到实机微调;
- 任何自动调参都必须配故障注入与约束检查,否则优化器会钻目标函数的空子,例如把振荡当成快速响应来奖励。
我的态度只有一句话:AI 是加速器,不是免责牌。上线仍要保留手动降级参数与禁能路径,任何情况下工程师都必须能接管。
九、收束:一条可落地的实践清单
如果你也在 EMS 里实现增量式 PI,建议把下面几条当作上线前的 checklist:
| # | 检查项 | 说明 |
|---|---|---|
| 1 | 误差定义与符号 | 充放电目标功率符号是否统一,表计功率方向是否与 EMS 约定一致——否则 PID 越聪明越反向 |
| 2 | 三者阈值文档 | 死区、积分分离阈值、比例分离阈值分工明确,大小关系有文档 |
| 3 | 补偿与输出双层限幅 | 明确限幅顺序,以及何时清零状态 |
| 4 | 目标稳定与 PID 使能 | 避免目标抖动时 PI 全功率追逐噪声 |
| 5 | 充放电两套参数 | 对象增益不同,不要指望一组 Kp/Ki 通吃两种工况 |
| 6 | 关键量打日志 | Kp、Ki、死区、分离阈值、fCompensation、fPrevError 打在同一行,排障会省一半时间 |
增量式 PI 在储能里不是什么炫技,它是在噪声、约束、工况切换三者夹击下,让功率调节「能稳住、能解释、能上线」的一种工程选择。
我写的每一行限幅与分离,本质上都是在给物理世界留余地——控制器再聪明,也要尊重电表和 PCS 的脾气。