引言
在工业生产、给排水、食品饮料等众多领域,液位的精准控制直接关系到产品质量、设备安全以及能源消耗。传统的开关量控制往往存在频繁启停、 overshoot(超调)和欠调等问题,而引入 死区(Deadband)、 延时保护、干抽保护 等功能的功能块(FB)则能够在保证液位稳定的同时,大幅降低机械磨损和能源浪费。
本文将以一段典型的 FB_LevelControl(液位控制功能块)为例,逐行解读其结构与工作原理,并探讨其在实际项目中的应用场景、可扩展方案以及使用心得,帮助 PLC 工程师快速上手并进行二次开发。
1
程序代码及介绍
1.1
完整功能块代码
下面是完整的 PLC 程序代码(代码基于 CodeSys 平台的 ST 语言):
FUNCTION_BLOCK FB_LevelControl
VAR_INPUT
level : REAL; // 当前液位(0-100%)
setpoint : REAL; // 设定液位(0-100%)
deadband : REAL; // 死区宽度
highAlarmLevel : REAL; // 高报警液位
lowAlarmLevel : REAL; // 低报警液位
pumpStartDelay : TIME; // 泵启动延时
pumpStopDelay : TIME; // 泵停止延时
dryRunProtection : BOOL; // 干抽保护使能
lowLevelSwitch : BOOL; // 低液位开关
manualMode : BOOL; // 手动模式
manualPumpCommand : BOOL; // 手动泵命令
resetAlarms : BOOL; // 报警复位
END_VAR
VAR_OUTPUT
pumpOutput : BOOL; // 泵控制输出
highAlarm : BOOL; // 高液位报警
lowAlarm : BOOL; // 低液位报警
dryRunAlarm : BOOL; // 干抽报警
controlMode : STRING; // 控制模式显示
END_VAR
VAR
pumpState : BOOL; // 内部泵状态(TRUE=运行)
startTimer : TIME; // 启动延时计时器
stopTimer : TIME; // 停止延时计时器
lastLowLevel : BOOL; // 上一次低液位开关状态
dryRunTimer : TIME; // 干抽保护计时器
END_VAR
// 报警复位
IF resetAlarms THEN
highAlarm := FALSE;
lowAlarm := FALSE;
dryRunAlarm := FALSE;
END_IF;
// 手动模式
IF manualMode THEN
pumpOutput := manualPumpCommand;
controlMode := 'MANUAL';
// 手动模式下的保护
IF dryRunProtection AND lowLevelSwitch AND manualPumpCommand THEN
dryRunTimer := dryRunTimer + T#10ms;
IF dryRunTimer > T#5s THEN // 干抽5秒报警
dryRunAlarm := TRUE;
pumpOutput := FALSE;
END_IF;
ELSE
dryRunTimer := T#0s;
END_IF;
RETURN;
END_IF;
controlMode := 'AUTO';
// 液位报警
highAlarm := level > highAlarmLevel;
lowAlarm := level < lowAlarmLevel;
// 干抽保护
IF dryRunProtection AND lowLevelSwitch AND pumpState THEN
dryRunTimer := dryRunTimer + T#10ms;
IF dryRunTimer > T#5s THEN
dryRunAlarm := TRUE;
pumpState := FALSE;
END_IF;
ELSE
dryRunTimer := T#0s;
IF NOT lowLevelSwitch THEN
dryRunAlarm := FALSE;
END_IF;
END_IF;
// 液位控制逻辑
IF level < (setpoint - deadband/2) THEN
// 液位低于下限,需要启动泵
IF NOT pumpState THEN
startTimer := startTimer + T#10ms;
IF startTimer >= pumpStartDelay THEN
pumpState := TRUE;
startTimer := T#0s;
END_IF;
END_IF;
ELSIF level > (setpoint + deadband/2) THEN
// 液位高于上限,需要停止泵
IF pumpState THEN
stopTimer := stopTimer + T#10ms;
IF stopTimer >= pumpStopDelay THEN
pumpState := FALSE;
stopTimer := T#0s;
END_IF;
END_IF;
ELSE
// 在死区内,保持当前状态
startTimer := T#0s;
stopTimer := T#0s;
END_IF;
// 低液位开关保护
IF lowLevelSwitch THEN
pumpState := FALSE;
END_IF;
// 输出泵状态
pumpOutput := pumpState;
// 更新低液位状态
lastLowLevel := lowLevelSwitch;
1.2
逐段解读
|
代码块 |
功能 |
|---|---|
| 输入输出声明 |
定义了所有可外部连接的变量。 |
| 报警复位 |
一旦 |
| 手动模式 |
当 |
| 自动模式标记 |
若非手动,则把 |
| 液位报警 |
简单比较:超过高报警阀位 → |
| 干抽保护 |
当使能开关、低位开关闭合且泵处于运行状态时,累计 10 ms 周期,累计超过 5 s 触发 |
| 液位控制逻辑(死区+延时) |
- 低于下限: - 高于上限: - 死区内:两个计时器清零,保持现有泵状态,实现 hysteresis(滞后)特性。 |
| 低位开关硬保护 |
即使液位仍在死区内,若低位开关意外闭合(例如液位传感器失效),直接强制 |
| 输出与状态更新 |
将内部 |
通过上述结构,该 FB 集成了 死区控制、延时防抖、干抽保护、手/自切换、报警复位 五大核心功能,能够在多数液位调节场景下提供安全、平稳的控制表现。
2
应用场景
给排水泵站 水位波动大,泵易频繁启停导致电机过热。 死区 + 启停延时抑制频繁动作;低位开关干抽保护防止泵空转。
锅炉給水系统 需要严格维持锅炉内水位在安全范围,否则可能造成干烧或过压。 高/低报警阀值可直接对应锅炉安全限值;干抽保护再增加一层防护。
食品饮料罐体配料 配料罐液位必须保持在目标范围,过高会导致溢出,过低影响配料比例。死区确保液位在目标附近稳定;手动模式便于调试配方;报警可联锁后道工序。
化工反应釜 反应物加料液位波动会影响反应速率和产物质量。 可根据反应釜的惯性时间调节 pumpStartDelay/StopDelay,使液位变化更平缓。
废水处理污泥浓缩 污泥浓缩罐液位过低易造成泵吸空,过高易导致溢流。 低位开关直接切断泵;高位报警可触发旁路或报警值班。
简而言之,只要涉及 液位维持、泵启停、防干抽、报警联锁 的场合,此功能块都能直接套用或稍作参数调整即可满足需求。
3
拓展思考
-
多泵轮切(泵组控制)
目前 FB 仅控制单泵。若要实现 N+1 冗余 或 负载均衡,可以在外部添加一个顺序控制逻辑:根据泵运行时间、故障标志或液位趋势来选择下一台启动的泵。此时 FB 仍可作为每台泵的底层驱动,仅需把pumpOutput映射到对应的物理输出。 -
自适应死区
在某些工艺中,液位的惯性随流量、温度、粘度变化而变化。可以引入一个 自适应算法(如基于最近几分钟的液位斜率),动态调整deadband的大小,以在工况变化时仍保持良好的控制性能。 -
故障诊断与预测性维护
利用startTimer、stopTimer、dryRunTimer等计时器的累计值,可判断泵的启停频率和运行时长。异常升高的启停次数可能暗示传感器噪声或阀门卡滞;长时间的干抽计时器则提示低位开关或液位传感器失效。这些数据可上传至 SCADA 进行趋势分析和维护提醒。 -
与模型预测控制(MPC)结合
对于对动态响应要求极高的系统(如精密实验室配料),可把此 FB 作为 底层安全互锁层,而在其上层运行一个基于模型的预测控制器,由 MPC 给出理想的setpoint和deadband参数,FB 负责确保在任何极端工况下泵不会因为控制器失效而导致设备损坏。 -
跨平台移植
该 FB 采用纯 ST 语言,几乎所有主流 PLC(Siemens S7、Rockwell Automation、Beckhoff、三菱等)均可直接编译。如需迁移到 IEC 61131‑3 以外的环境(如 Arduino、树莓派 + Real‑time Linux),只需把TIME类型换成毫秒计数器,其余逻辑保持不变。
总结
本文通过对 FB_LevelControl 完整代码的逐行解读,展示了一个兼具 死区控制、延时防抖、干抽保护、手自切换及报警复位 的液位调节功能块。它在结构上清晰、参数易调、安全防护全面,能够直接投入到给排水、锅炉、食品饮料、化工等多种液位控制场景中。
文章进一步指出了该 FB 在 多泵轮切、自适应死区、故障诊断、模型预测控制 等方面的扩展潜力,为工程师在实际项目中进行二次开发提供了思路与方向。
掌握此类功能块的设计思想,不仅能提高系统的可靠性和能效,还能为后续更复杂的过程控制奠定坚实的基础。希望本篇文章能成为您在 PLC 编程道路上的得力助手,祝您编码顺利、系统稳定!
你来出题 我来答![]()
![]()
![]()
欢迎大家在评论区提一些标准功能块的需求,如果合适,我们会在以后的文章中与大家分享。
往期回顾
每周一个编程小例子 :Bit 到 Word 转换的两种实现方案对比
每周一个编程小例子:记录设备运行时间
每周一个编程小例子:基于长按检测的启动控制系统
每周一个编程小例子:探秘 PLC 数据记录功能块
每周一个编程小例子:心跳检测与 PLC 应用
每周一个编程小例子:斜坡发生器
每周一个编程小例子:旋转速度计算
每周一个编程小例子:计算 PLC 循环周期|例程需求征集!
每周一个编程小例子:如何优雅的分割字符串
每周一个编程小例子:带反馈的阀门控制程序
每周一个编程小例子:西门子 LGF 库中的脉冲继电器功能块
每周一个编程小例子:曲线加减速的控制应用
每周一个编程小例子:轻松去除字符串前导字符
每周一个编程小例子:根据阈值更新输入
每周一个编程小例子:官方模拟量输入处理模块
每周一个编程小例子:主从电机的时序控制
每周一个编程小例子:基于一阶滞后滤波的优化方案
每周一个编程小例子:16 进制到浮点数的神奇转换
每周一个编程小例子:PLC 长按控制程序
每周一个编程小例子:PLC 程序实现多位整数拆分
每周一个编程小例子:流量累积计算器
每周一个编程小例子:用于连锁的电机标准控制模块
每周一个编程小例子:PID 控制算法在 PLC 系统中的实现与应用
每周一个编程小例子:自定义种子生成随机数
每周一个编程小例子:可调时间的脉冲生成器
每周一个编程小例子:带滤波的标准模拟量输入功能块
每周一个编程小例子:使用 PLC 将字符串转换为日期格式
每周一个编程小例子:PLC 配方管理
每周一个编程小例子:比较两个 DB 块(STL)
每周一个编程小例子:如何使用 PLC 实现数组逆序
每周一个编程小例子:流量累计与批次控制
每周一个编程小例子:自定义循环执行控制程序
每周一个编程小例子:步进控制功能块
每周一个编程小例子:PLC 权重比例分配器
每周一个编程小例子:数字量输入组监控
每周一个编程小例子:实时数据分析
每周一个编程小例子:PLC 多轴同步控制的理解与应用
每周一个编程小例子:PLC 波形生成器 (正弦 方波 三角波)
每周一个编程小例子:模拟量信号报警
每周一个编程小例子:组合数概率的实现
每周一个编程小例子:多传感器信号融合与优化方案
每周一个编程小例子:监控模拟信号的健康状态
每周一个编程小例子:PLC 程序实现模拟信号的线性校准
每周一个编程小例子:智能报警过滤器:优化报警系统的 PLC 程序
每周一个编程小例子:使用 PLC 程序让灯光呼吸
每周一个编程小例子:自适应性滤波器:动态调整以平衡响应与稳定性
每周一个编程小例子:卡尔曼滤波器在自动化中的简单应用
每周一个编程小例子:多模式定时器
每周一个编程小例子:基于 PLC 的编码器速度计算器
每周一个编程小例子:电机顺序启动与停止程序
每周一个编程小例子:电梯控制程序
每周一个编程小例子:自动门控制系统
每周一个编程小例子:智能停车场计数系统
每周一个编程小例子:智能照明控制系统
每周一个编程小例子:变频器控制
每周一个编程小例子:比例阀控制
每周一个编程小例子:脉冲输出的灵活控制
每周一个编程小例子:计算移动平均值
每周一个编程小例子:速率限制器
每周一个编程小例子:线性插值法线性化传感器
每周一个编程小例子:数据转换的魔力
每周一个编程小例子:PLC 安全监控功能块
每周一个编程小例子:「看门狗」功能块
每周一个编程小例子:实现工业数据轻量压缩
每周一个编程小例子:PLC 消抖功能块
每周一个编程小例子:CRC 校验计算器
2026年10月