接手一套工业锅炉的过程控制系统时,我最先做的不是打开编程软件,而是先问自己一个问题:如果锅炉突然断水,程序能不能在足够短的时间内把燃烧停下来,而不是先想着把PID调得多漂亮。这套基于PLC的工业锅炉过程控制的设计与仿真,表面上看是写逻辑、调参数、画画面,实际上是在跟一个水位、压力、温度互相耦合的大惯性对象打交道。汽包水位会虚假波动,炉膛负压和风煤比互相牵扯,任何一个回路处理不好,轻则产量波动,重则触发保护停车。我前阵子完整做了一套从I/O表梳理、硬件通道分配、控制程序编写到仿真验证的全流程,这里把设计思路、程序组织方式和仿真环节里踩过的坑一次性讲清楚,给准备入门或者正在做同类项目的朋友一个参考。
1. 锅炉过程控制的核心任务:不只是三套PID
1.1 汽包水位:最会“骗人”的控制回路
工业锅炉多数是自然循环汽包炉,汽包里的水位是给水量和蒸发量平衡的结果,但它并不是一个老老实实的积分对象。蒸汽负荷突然增大的瞬间,汽包压力会下降,水面下的汽泡体积迅速膨胀,水位反而先往上冲一下,然后再持续下降。这个现象就是常说的“虚假水位”。如果此时单纯靠水位偏差去关小给水阀,等于在给锅炉火上浇油——它先要涨水,你还在关阀,等真实缺水趋势露出来,水位已经掉到危险区域了。
因此在设计水位回路时,不能只做单回路PID。工程上基本都会上三冲量控制:蒸汽流量作为前馈信号,给水流量作为反馈信号,汽包水位作为主信号。蒸汽流量一变化,给水调节阀马上朝对应方向动作,不需要等到水位偏差出现。这个回路设计好之后,等于给水位控制装了一双“预判的眼睛”。
1.2 燃烧控制:风煤比和炉膛负压必须同步
燃烧回路比水位回路更复杂一点。燃料量、送风量、引风量三个变量互相约束:燃料量决定发热量,送风量决定燃烧是否充分,引风量决定炉膛负压是否稳定。鼓风机增大风量时,引风机如果不动,炉膛负压马上往正方向跑;送风量不变只加燃料,烟气含氧量会掉,燃烧不完全,排烟热损失上升。
设计上我用的是成熟的两层结构:蒸汽压力作为主调,输出作为燃料量和送风量的偏置基准,燃料和送风保持一个比值系数,同时用烟气氧含量修正风煤比;炉膛负压单独一个回路,引风机跟随鼓风机的前馈变化动作。这样压力波动时,燃料和风同步增减,负压回路只做微调,系统才不会“打架”。
1.3 顺序启停与联锁:安全必须独立于调节回路
调节回路管的是“正常运行时的稳定性”,但锅炉真正要命的是启停过程和异常工况。点火前没有吹扫、点火失败不切断燃料、汽包低水位还继续烧,这些都是恶性事故的典型诱因。因此程序里必须有一套独立于PID之外的顺序控制和联锁逻辑。
启动顺序我这边按“检查准备—吹扫—点火试验—升温升压—并汽运行”走:先确认鼓引风机启动、炉膛负压合适、水位在正常范围内,然后开始一定时间的吹扫,把炉膛里残留的可燃气体吹干净,之后才能点火。任何一步条件不满足,程序就停在当前阶段并给出提示。联锁保护更像是踩刹车:汽包水位过低、蒸汽压力过高、火焰熄灭,都直接触发跳闸停炉逻辑,这些动作不受手自动状态影响,用的是硬逻辑旁路的方式处理。
2. 设计前必须清点清楚的一件事:I/O表和信号类型
2.1 从工艺参数反推I/O点表
很多人写程序喜欢边写边加点位,结果到最后通道不够、地址冲突。我的习惯是第一步就把I/O点表列全,并且按照信号类型分好类。一套典型的4吨/小时左右蒸汽锅炉,DI、DO、AI、AO的点位大致是这样的规模:
| 信号类型 | 典型点位 | 说明 |
|---|---|---|
| 数字量输入DI | 泵运行/故障、阀门全开/全关、火焰检测、压力开关、液位开关 | 反映设备状态和开关量保护 |
| 数字量输出DO | 泵启停、阀门开/关命令、声光报警、点火变压器、燃料切断阀 | 控制执行机构与报警指示 |
| 模拟量输入AI | 汽包水位、给水流量、蒸汽流量、蒸汽压力、炉膛负压、烟气氧含量、排烟温度、炉膛温度 | 参与PID调节与监视 |
| 模拟量输出AO | 给水调节阀开度、鼓风机频率、引风机频率、燃料调节阀开度 | 输出连续控制量 |
这里有个很容易漏的点:差压变送器测水位在启停机时误差很大,因为汽包内压力变化会影响差压读数。所以除了正常量程内的差压式水位计,很多项目会单独加一套独立液位开关作为硬保护信号,不经过调节回路的变送器,联锁动作更可靠。
2.2 模拟量通道为什么比你想的更占资源
数字量一个点就是一个位,但模拟量不是。一套AI通道从接线到组态,要经过变送器供电、信号隔离、线缆屏蔽、通道量程设置、滤波、断路诊断等好几道环节。一个AI点至少在程序里对应一个原始值地址、一个工程量缩放,还要考虑报警上下限的存储。如果用了冗余通道或者安全栅,占用的通道数还会翻倍。
我在清点I/O时坚持按“备用不低于15%”来留。现场调试最怕的就是发现某个回路坏了想换点,结果通道全部占满。模拟量通道还要特别注意双绞屏蔽线的单端接地,屏蔽层在PLC侧接地一次就够了,两头都接反而会产生地环路,引入共模干扰。
2.3 执行机构与阀门的反馈处理
很多人设计点位时只设计了输出命令,忘了阀门有没有到位反馈,或者反馈信号脏了怎么办。实际项目里,调节阀的阀位反馈(通常4-20mA)必须做,否则程序无法判断阀门是卡住还是真的按指令动作了。DO输出的电磁阀控制也要区分得电开还是失电开,涉及到故障安全类型,宁可失电时回到安全位置,也不能失电后保持危险状态。
电动执行机构的行程开关反馈是用DI接入的,但行程开关触点在水汽环境里容易氧化,我遇到过反馈信号接触不良导致阀门动作后就“失联”的情况。后来统一要求执行机构配置4-20mA阀位反馈,顺便把行程开关作为辅助信号,诊断能力强了很多。
3. 控制程序的正规组织方式:面向功能块,不面向扫描周期
3.1 程序结构分层:组织块、功能块与数据块
PLC程序如果全部写在同一个扫描块里,眼前看是方便,往后维护就是灾难。我按“组织块—功能块—数据块”的方式来做,组织块相当于总调度,只负责调用顺序;功能块封装相对独立的控制逻辑,比如水位控制块、燃烧控制块、联锁保护块;数据块集中存放参数、设定值、报警限值和中间变量。
这样做的最大好处是能单独调试。仿真阶段水位控制块有问题,我只需要给这个功能块制造输入信号,不需要把燃烧部分、顺序部分全部跑起来,定位速度快得多。功能块内部尽量少用全局地址,接口参数全部通过变量名传递,以后换型号、改点位时,功能块内部几乎不用动。
3.2 水位三冲量调节的实现逻辑
三冲量控制本质上是给PID加前馈和反馈修正。我习惯用这样的结构:主PID接收水位设定值与实际水位的偏差,输出作为基础给水指令;蒸汽流量信号经过量程转换后乘以一个前馈系数,直接叠加到给水指令上;给水流量信号作为反馈,与综合指令比较后形成真正的执行器输出。
公式看起来简单,实际处理时有几个细节:前馈系数不能过大,否则负荷波动时给水阀会过冲,给水流量和水位之间形成新的振荡;给水流量反馈的作用是克服调节阀非线性,让阀位指令和实际流量之间尽量线性;三个信号必须做相同的工程单位换算和时间常数匹配,信号滤波时间差异太大会让前馈变成扰动源。
3.3 手自动无扰切换看起来容易做起来难
程序里每个重要回路都要设计自动/手动切换。这里的坑是切换瞬间的执行器输出跳变。比如手动状态阀门开在40%,切到自动之前PID一直在那积分,输出值可能已经累计到70%,一切过去阀门猛地一跳,水位跟着跟着就晃。
我的做法是让PID输出在手动状态时持续跟踪实际阀位,也就是“输出初始化”。自动状态下,PID输出跟随手动给定值,只在偏差为零附近才放开积分。这样切换的瞬间执行器指令不变,之后再平滑过渡。调试时这条必须逐回路验证一遍,否则现场操作工人切一下会发现蒸汽压力突然大幅波动。
3.4 报警与联锁的独立性设计
联锁逻辑不能和调节逻辑混在一起。调节回路里的PID可能被人切到手动,可能参数调乱,但联锁保护必须任何时候都起作用。我的联锁块采用单独的功能块,输入直接接原始物理信号,输出直接接跳闸继电器或者主燃料切断阀,中间不经过任何手自动开关。这相当于给锅炉装了一个独立的“急刹车系统”。
联锁动作条件和延时也需要逐条梳理:水位低保护要躲过虚假水位波动,通常加2到5秒延时;压力高保护要躲过安全阀起跳瞬间的压力波动;火焰检测信号一定要选带自检功能的火焰探测器,否则探头脏了自己都不知道。每一项联锁动作后要记录触发源、动作时间和当时的工况参数,这组数据在现场事故分析时非常关键。
4. 仿真环境搭建与验证:把锅炉搬进电脑里
4.1 选什么仿真路线:软PLC加组态,还是半实物
程序写完之后,我建议至少留出和程序设计同等的时间来做仿真验证。仿真的形式我试过两种:一种是用软PLC运行程序,通过OPC或者厂商接口把变量链接到组态画面,用内置的模拟量脚本去模拟水位、压力的变化;另一种是半实物仿真,实际PLC接上,把现场变送器和执行机构换成模拟器。预算有限、时间紧张的项目,第一种足够了;要验证硬件通道和实际接线逻辑,才需要第二种。
我用的是软PLC加组态的方式。把水位、炉膛负压这些被控对象做成一个“虚拟锅炉”模型,PLC程序通过输入映像区读取模型计算的传感器值,输出指令回到模型计算下一次的值,形成一个闭环。这个闭环跑起来之后,不用去现场就能把启停顺控、联锁保护、PID调节全部过一遍。
4.2 对象模型:给锅炉一个“惯性”
把锅炉搬进电脑里,核心是先给它一个差不多的数学模型。汽包水位在我这里简化成两个部分:一个是给水量与蒸发量之差对水位的积分效应,另一个是蒸汽负荷变化引起的汽泡体积变化。仿真里我用的是一阶惯性加纯延迟再串积分的近似对象,采样周期取0.5秒,水位的响应参数大致按实际设备的时间常数来估算。
例如用给水流量扰动测试水位时,我让模型产生这样的行为:给水阀开度增加5%,给水流量缓慢上升,水位先延迟4到6秒,然后以一个相对缓慢的斜率上升。炉膛负压回路则简单得多,把它当做一个快速一阶惯性环节。模型不追求精确复现现场,只要能反映“大惯性、有延迟、相互耦合”这三个特征,验证控制逻辑就足够。
4.3 用趋势曲线做PID整定:试凑法的真实手感
仿真最大的价值是可以大胆试凑PID参数,不用承担现场风险。我习惯分三步走:先只加比例,让系统出现临界振荡,记录振荡周期;然后加入适当的积分时间,消除稳态偏差;最后一点点加微分,观察扰动抑制效果。水位回路的惯性大,微分作用不能给太强,否则给水流量信号里的噪声会被放大。
我仿真时记录了一组参数变化的过程:初始比例系数从2往上试,水位在阶跃扰动后出现明显振荡,周期大概90秒;这时把比例系数减小到1.2,把积分时间放在150秒附近,系统慢慢稳定下来,超调量大约在8%左右;再加一点微分时间20秒之后,抗扰动性能略有改善,但给水阀动作频率变高,最后我把微分时间压回15秒才平衡下来。这些数值直接搬到现场肯定对不上,但给了一个很好的起点。
4.4 联锁逻辑的仿真验证清单
联锁保护不出问题则已,一出问题就是大问题。我把联锁逻辑的仿真验证做成了一个清单,逐条触发看动作结果:
| 联锁项目 | 仿真触发条件 | 程序应执行动作 | 结果 |
|---|---|---|---|
| 汽包水位过低 | 将水位模拟值降到低低限以下并保持延时 | 停炉、切断燃料阀、声光报警 | 验证通过 |
| 汽包水位过高 | 将水位模拟值升到高高限 | 打开紧急放水阀、报警 | 验证通过 |
| 蒸汽压力过高 | 蒸汽压力模拟值超限 | 报警并触发停炉 | 验证通过 |
| 火焰熄灭 | 火焰检测信号变为无火 | 切断燃料阀、报警 | 验证通过 |
| 给水泵故障 | 泵故障信号置位 | 备用水泵自动启动 | 验证通过 |
这组验证不要只测正常触发条件,还要测边界值。比如水位低低限的动作值设在-250mm,那就要分别把水位放在-240、-250、-260附近各试一次,确认动作值的回差不会造成频繁动作。延时时间也要反复验证,既不能太灵敏让扰动误触发,也不能太迟钝让事故扩大。
5. 试过才明白的现场经验:仿真和实际的差距
5.1 信号干扰比程序bug更难查
仿真环境干干净净,到了现场就是另一回事。变频器刚启动的时候,附近感觉是引发了电磁“风暴”一样,模拟量信号瞬间波动很大。锅炉房电动机多,变频器柜和PLC柜如果挨得太近,屏蔽做得不好,4-20mA信号会被拉出几微安的噪声,反映到工程量上就是水位曲线出现锯齿。
解决办法是信号线全程屏蔽,屏蔽层在PLC侧单端接地;模拟量信号用隔离器,别省这个钱;变频器的输出侧加载电抗器,动力电缆和信号电缆分桥架走,保持距离。如果不能改变布线,程序里也要加一阶低通滤波,但不能过度滤波,因为水位信号本身就有一定的真实波动,滤波太狠会把回路的实时性拖没。
5.2 阀门非线性和行程漂移
仿真模型里我默认阀门是线性的,给多少开度就对应多少流量。实际阀门的气蚀、摩擦、阀芯磨损都会让流量特性偏离理想曲线,尤其是调节阀在小开度区域,流量几乎不动,过了某个点猛地变大。这会直接让PID参数在现场变得“有时灵敏有时迟钝”。
处理办法有两步:一是尽量选择流量特性近似等百分比的阀门,让控制量在小开度下不那么陡;二是现场做一次静态标定,记录阀位指令和实际流量的对应关系,在程序里做线性化修正。另外要留意阀门行程漂移,电动执行机构的阀位反馈零点会随着温度和时间偏移,仿真阶段你根本看不到这个问题。
5.3 不同运行工况需要考虑参数切换
仿真做完,你可能觉得参数已经万事大吉,但锅炉是间歇运行的东西。低负荷点火初期,蒸汽压力低,蒸发量小,对象特性和满负荷时差很多。同一组PID在满负荷下稳定运行,在低负荷下可能频繁振荡,因为被控对象的时间常数随负荷变化很大。
建议在程序里做负荷分段的PID参数切换,低负荷、中负荷、高负荷各准备一组参数,根据蒸汽流量或者压力自动切换。切换也要做无扰处理,两组参数的过渡靠斜坡拉过去,不要瞬间跳变。这个细节在仿真阶段就设计好,现场调试能少挨不少骂。
最后再分享一个体会:仿真做得再漂亮,也替代不了对现场工艺的敬畏。我见过最扎实的程序,不是代码多花哨,而是联锁逻辑完整、参数有出处、操作不违和。做锅炉控制,先学会把安全想清楚,再去追求控制品质,顺序别搞反了。