Skip to main content

 

引言

在工业生产、给排水、食品饮料等众多领域,液位的精准控制直接关系到产品质量、设备安全以及能源消耗。传统的开关量控制往往存在频繁启停、 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

   

逐段解读

代码块

功能

输入输出声明

定义了所有可外部连接的变量。level、setpoint 为百分比液位;deadband 决定死区大小;pumpStartDelay/StopDelay 提供启停防抖;dryRunProtection 与 lowLevelSwitch 配合实现干抽保护;manualMode 允许现场调试。输出包括泵开关量、三类报警以及控制模式字符串,便于 HMI 显示。

报警复位

一旦 resetAlarms 为 TRUE,三路报警全部清零,避免误报累积。

手动模式

当 manualMode = TRUE 时,直接把 manualPumpCommand 传递到泵输出,并进入保护检测:若低位开关闭合且泵被命令启动,则启动干抽计时器,超过 5 s 则报警并强制关泵。手动模式下不参与自动液位适配,便于调试和维护。

自动模式标记

若非手动,则把 controlMode 设为 'AUTO',后续报警与保护均在此基础上进行。

液位报警

简单比较:超过高报警阀位 → highAlarm=TRUE;低于低报警阀位 → lowAlarm=TRUE。

干抽保护

当使能开关、低位开关闭合且泵处于运行状态时,累计 10 ms 周期,累计超过 5 s 触发 dryRunAlarm 并立即切断泵。若低位开关断开(说明有液),则计时器清零并复位报警,防止误报。

液位控制逻辑(死区+延时)

- 低于下限:level < setpoint - deadband/2 → 启动计时器 startTimer,达到 pumpStartDelay 后才真正置位 pumpState(防止因噪声或短暂波动造成误启)。

- 高于上限:level > setpoint + deadband/2 → 同理使用 stopTimer 防止频繁停泵。

- 死区内:两个计时器清零,保持现有泵状态,实现 hysteresis(滞后)特性。

低位开关硬保护

即使液位仍在死区内,若低位开关意外闭合(例如液位传感器失效),直接强制 pumpState := FALSE,确保泵不会在无液情况下运行。

输出与状态更新

将内部 pumpState 映射到 pumpOutput;同时把本次低位开关状态保存到 lastLowLevel,供后续诊断或事件记录使用。

通过上述结构,该 FB 集成了 死区控制、延时防抖、干抽保护、手/自切换、报警复位 五大核心功能,能够在多数液位调节场景下提供安全、平稳的控制表现。

2

   

应用场景

给排水泵站  水位波动大,泵易频繁启停导致电机过热。  死区 + 启停延时抑制频繁动作;低位开关干抽保护防止泵空转。

锅炉給水系统  需要严格维持锅炉内水位在安全范围,否则可能造成干烧或过压。  高/低报警阀值可直接对应锅炉安全限值;干抽保护再增加一层防护。

食品饮料罐体配料 配料罐液位必须保持在目标范围,过高会导致溢出,过低影响配料比例。死区确保液位在目标附近稳定;手动模式便于调试配方;报警可联锁后道工序。

化工反应釜 反应物加料液位波动会影响反应速率和产物质量。 可根据反应釜的惯性时间调节 pumpStartDelay/StopDelay,使液位变化更平缓。

废水处理污泥浓缩 污泥浓缩罐液位过低易造成泵吸空,过高易导致溢流。  低位开关直接切断泵;高位报警可触发旁路或报警值班。

简而言之,只要涉及 液位维持、泵启停、防干抽、报警联锁 的场合,此功能块都能直接套用或稍作参数调整即可满足需求。

3

   

拓展思考

  1. 多泵轮切(泵组控制)
    目前 FB 仅控制单泵。若要实现 N+1 冗余 或 负载均衡,可以在外部添加一个顺序控制逻辑:根据泵运行时间、故障标志或液位趋势来选择下一台启动的泵。此时 FB 仍可作为每台泵的底层驱动,仅需把 pumpOutput 映射到对应的物理输出。

  2. 自适应死区
    在某些工艺中,液位的惯性随流量、温度、粘度变化而变化。可以引入一个 自适应算法(如基于最近几分钟的液位斜率),动态调整 deadband 的大小,以在工况变化时仍保持良好的控制性能。

  3. 故障诊断与预测性维护
    利用 startTimer、stopTimer、dryRunTimer 等计时器的累计值,可判断泵的启停频率和运行时长。异常升高的启停次数可能暗示传感器噪声或阀门卡滞;长时间的干抽计时器则提示低位开关或液位传感器失效。这些数据可上传至 SCADA 进行趋势分析和维护提醒。

  4. 与模型预测控制(MPC)结合
    对于对动态响应要求极高的系统(如精密实验室配料),可把此 FB 作为 底层安全互锁层,而在其上层运行一个基于模型的预测控制器,由 MPC 给出理想的 setpoint 和 deadband 参数,FB 负责确保在任何极端工况下泵不会因为控制器失效而导致设备损坏。

  5. 跨平台移植
    该 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月

 

 

 

Tags