我接触PLC污水处理这个方向,最早是因为一个关于小型污水处理站的自动化改造项目。当时客户提的需求很明确:工艺上要能自动运行,监控上位机要用组态王做动画界面,交付物要包含PLC源代码、组态王源代码、电气图纸和完整的IO地址分配表。这几乎就是把一套可落地的方案摊开在你面前。后来这个项目做下来,我最大的感受是:技术难点其实不集中在某一个环节,而在整条链条——从工艺逻辑拆解,到IO点表设计,再到程序结构和组态画面的联动,每一环都容易踩坑。
今天这篇文章,我打算把自己做这套系统的完整思路复盘一遍,包括工艺流程怎么拆、PLC选型怎么定、IO地址怎么分配才能方便后续维护、程序逻辑里哪些联锁必须做、组态王画面怎么设计才有“仿真感”,以及在调试阶段遇到的几个真实问题和排查过程。无论你是做污水自控项目刚起步的工程师,还是准备拿类似课题做毕业设计或竞赛作品的学生,这篇内容应该都能直接用得上。
1. 污水处理工艺与控制需求拆解
做任何一套控制系统,第一件事不是打开编程软件,而是先把工艺吃透。组态王和PLC都只是工具,真正决定程序怎么写的,是这套污水系统到底怎么运转、哪些设备需要联动、哪些参数需要参与闭环控制。
1.1 这套系统的工艺主干
我们当时做的是一个小规模的市政污水提升与生化处理单元,工艺路线大致是:集水井提升泵 → 格栅渠(粗格栅) → 调节池 → A/O生化池 → 二沉池 → 消毒接触池 → 达标排放。此外还有污泥回流和剩余污泥排放两条辅助管路。设备清单包括:提升泵、粗格栅除污机、潜水搅拌器、鼓风机(给好氧池供氧)、污泥回流泵、剩余污泥泵、加药计量泵(用于除磷或消毒)、电动阀门若干,以及液位计、pH计、溶解氧(DO)探头、电磁流量计等仪表设备。
这套流程放在PLC控制里,可以简化成几个控制单元:
1.2 控制任务清单
- 集水井泵站控制:根据集水井液位自动启停提升泵,高液位启动、低液位停止,防止泵空转或溢流;
- 格栅控制:根据格栅前后液位差或定时时间自动运行除污机,无人值守时以时间为准是更省心的方式;
- 生化池供氧控制:根据好氧区溶解氧浓度对鼓风机进行启停或台数控制,如果要求再高一些可以做变频调速,但这里用异步电机+多台启停控制就够了;
- 污泥回流控制:回流泵按运行时间和设定的启停周期循环切换,防止污泥沉积;
- 加药控制:按流量比例或定时定量投加药剂,涉及流量计读数参与计算;
- 消毒控制:紫外线消毒设备随系统出水阀联动投入。
我习惯在动手设计PLC程序之前,先画一张表把设备和对应的控制条件列清楚。比如提升泵:
| 控制条件 | 动作 | 说明 |
|---|---|---|
| 集水井液位 ≥ 高液位 2.5m | 启动1#提升泵 | 液位信号来自静压式液位计 |
| 集水井液位 ≤ 低液位 0.8m | 停止1#提升泵 | 带低位保护,防止空转 |
| 1#泵故障 | 自动投入2#泵 | 两台泵互为备用 |
| 2#泵故障且1#泵未投 | 报警并停止进水 | 防止集水井溢流 |
这种控制表写清楚之后,后面写PLC程序、做组态王变量、画电气图纸就都有依据了。不要嫌这一步麻烦,我在调试时见过太多项目因为前期逻辑没理清,程序写了两版甚至三版,返工成本远高于前期梳理成本。
1.3 手自动三种模式怎么设计才实用
很多初学PLC的朋友喜欢把程序直接写成纯自动逻辑,但实际项目里运维人员非常依赖手动模式。我们的系统在每个设备上设置了“本地/远程”硬切换,在PLC内部还做了“手动/自动”软切换:
- 本地模式:设备由现场控制箱按钮直接控制,PLC不做任何干预,电气检修时用;
- 远程手动模式:设备由中控室组态王画面点按钮操作,PLC只负责执行命令并反馈状态,适合调试阶段或异常工况下人工干预;
- 远程自动模式:设备完全由程序依据液位、时间等条件自动控制,运行稳定后交给这个模式。
这个设计的核心原则是:设备的启停控制权限在同一时刻只能掌握在一处,必须通过硬编码的互锁逻辑来保证,而不是只靠组态王脚本。这是安全底线。
2. 硬件选型与IO地址分配
硬件选型听起来好像很简单——按点数估一个PLC就行。但实际做下来,IO地址分配才是影响后面所有工作(程序、组态、图纸、接线)的核心。地址分配得合理,程序写起来顺手,查线也轻松;分配得乱,调试时能从上午找到晚上。
2.1 PLC选型背后的逻辑
我当时的选型思路是这样的:先列IO需求表,再反推CPU和模块配置。
从工艺清单来看:
- 开关量输入DI:液位开关(高/低报警)、各设备的运行反馈、故障反馈、手自动切换信号、远程就地切换信号、电动阀开到位/关到位反馈等,粗算约20点;
- 开关量输出DO:各电机启停接触器、电动阀开门/关门指令、指示灯/蜂鸣器输出等,约16点;
- 模拟量输入AI:集水井液位、调节池液位、pH、溶解氧DO、进水流量、出水流量、消毒池余氯等,约6路;
- 模拟量输出AO:加药泵频率给定、鼓风机变频给定等,按需求预留2路。
核心计算原则是:CPU的I/O能力要预留20%-30%的余量,模拟量模块要按实际通道数选型并预留备用通道。综合下来,选用了一款中小型PLC搭配两块DI模块、一块DO模块、一块8通道AI模块,再选一个通信扩展接口用于连接组态王。
提示:确定PLC型号时,多问自己一个问题——后期要扩展的IO多不多?如果大概率要加设备,就选CPU本体扩展槽位多一些的型号,别在这个地方省成本。
2.2 IO地址表格怎么排才算“会排”
IO地址分配这门手艺,说实话很多文章都不细讲,但实际项目里它是让大家最头疼的。我分享一个自己的习惯:按“信号类型+工艺单元”两个维度来分组。
常见的错误做法是拿到点表就从I0.0按序列下去,设备之间毫无逻辑可言。这样的结果是:到现场查故障时,你得对着图纸翻半天才能定位一个中间继电器。而我推荐的方式是:
- 同一工艺单元的设备连续编组,例如集水井的提升泵1#、2#放在一组,格栅除污机单成一组,鼓风机这两台放一起;
- 泵类设备的DO运行指令对应的DI运行反馈尽量放在相邻地址,程序阅读时一目了然;
- 模拟量通道按仪表所在工艺位置顺序分配,例如AI0.0接集水井液位,AI0.1接调节池液位,AI0.2接pH计……每个通道在下线槽里挂标签明示,避免接线错误。
以提升泵为例,我们实际的分配片段:
| 地址 | 名称 | 信号类型 | 接线图端子 | 说明 |
|---|---|---|---|---|
| I0.0 | 集水井液位高位开关 | DI | X1-01 | 高液位报警输入 |
| I0.1 | 集水井液位低位开关 | DI | X1-02 | 低液位停泵保护 |
| I0.2 | 1#提升泵运行反馈 | DI | X1-03 | 接触器辅助触点 |
| I0.3 | 1#提升泵故障反馈 | DI | X1-04 | 热继电器信号 |
| I0.4 | 2#提升泵运行反馈 | DI | X1-05 | 接触器辅助触点 |
| Q0.0 | 1#提升泵启动指令 | DO | Y0-01 | 中间继电器→接触器 |
| Q0.1 | 2#提升泵启动指令 | DO | Y0-02 | 中间继电器→接触器 |
| AIW0 | 集水井液位4-20mA | AI | 模拟量输入卡0通道 | 量程0-5m |
注意,DI反馈类型要区分是“运行反馈”还是“故障反馈”,这两者在PLC程序中的处理方式完全不同。运行反馈用于状态显示和设备保护,故障反馈则是硬报警信息,通常还要在组态王画面里做闪烁和声光提示。
2.3 出图时容易忽略的三个细节
电气图纸是整个交付包里的另一条腿。这边的图纸通常包含三部分:主回路图(电机的电源回路、接触器、热继电器)、控制回路图(PLC输出点→中间继电器→接触器线圈)、端子接线图(PLC模块端子与现场设备的对应关系)。
画图时有三个细节非常值得留意:
- 每个PLC数字量输出点都要经过中间继电器中转,绝不能直接用PLC输出点驱动接触器线圈,因为接触器线圈的浪涌电流容易冲击PLC输出晶体管或继电器触点,缩短模块寿命;
- 模拟量信号必须注明信号类型和量程范围(如4-20mA对应0-5m),这样不仅接线的师傅不会接错,组态王里变量的原始值范围也有据可依;
- 接地端子的标注不能省,模拟量仪表电缆的屏蔽层必须单端接地,图纸上要能体现。
这三条看着不起眼,却是实际调试中排查问题的关键线索。我在现场见过不少项目因为忽略中间继电器导致PLC输出模块反复烧坏的情况,排查到最后发现是端子排上少画了一个续流二极管。
3. PLC程序核心逻辑设计(附源程序思路)
PLC程序是整套系统的大脑。下面我把程序结构从上往下拆开讲,这也基本就是源代码的架构骨架。有PLC基础的朋友可以直接照这个思路搭出第一版程序。
3.1 程序整体框架
我把程序划分为三个主程序段加若干子程序:
- 初始化程序:上电后复位所有输出状态、把组态王远程指令标志位清零、装载初始设定参数(定时器时间、液位联锁门限);
- 模式切换与手自动控制程序:处理远程/本地切换、手动指令的执行与锁定;
- 自动联锁程序:处理液位、溶解氧、时间相关的判断逻辑,输出到设备启停变量;
- 报警处理与通信数据区刷新程序:把各类报警汇总输出到组态王可读的数据区,同时周期刷新设备状态。
实际上很多工程师习惯把所有逻辑写在一个主程序里,程序短的时候没问题,但系统一复杂就会变得难以维护。结构化编程的好处是故障定位快——假如风机不启动,你先去查“自动联锁程序”中风机那一段的条件,再去查“模式切换”中是不是处于自动状态,很快就能定位。
3.2 自动联锁逻辑的核心写法
以提升泵两台自动切换为例,源代码的核心逻辑可以这样描述:
// 提升泵自动控制逻辑 IF 集水井液位 >= 高液位 THEN 当无泵运行且无故障时,启动当前工作泵 END_IF IF 集水井液位 <= 低液位 THEN 停止所有在运行的提升泵 END_IF IF 当前泵故障 THEN 停止该泵,启动备用泵 END_IF这里有一个很多初写程序的人容易犯的错误:直接用一个通电延时定时器做泵的轮换,而没有考虑“故障在泵启动瞬间是否已经存在”这种边界条件。由于电机启动电流大,接触器冲击,如果反馈信号取的是接触器辅助触点,那么启动瞬间会出现短暂的“运行反馈为0”状态,程序必须加一个“启动延时确认”的扫描窗口,而不是一看到反馈为0就立刻判故障。这个窗口通常设置3-5秒。
另外,高液位和低液位的判断建议用模拟量加比较指令,而不要只依赖液位开关数字量。原因在于:模拟量可以做中间死区处理,避免液位波动导致泵频繁启停;而液位开关只有ON/OFF两种状态,在临界点附近可能会反复抖动。
3.3 模拟量工程量转换公式
模拟量通道采集到的原始值是一个数字量(例如S7-200 SMART系列的AIW是0-27648),组态王能直接读取变量,但要想显示真实液位,还是要做一次工程量转换。
转换公式是:
- 工程量 = (原始值 - 偏移量) ÷ 量程数字量跨度 × 物理量程范围 + 物理下限
以4-20mA对应0-5m液位为例,假设原始值范围0-27648对应4-20mA:
液位 = (AIW原始值 - 5530) / (27648 - 5530) × 5.0为什么要强调5530这个数?因为很多模拟量模块在4mA时读到的原始值并不是0,而是在满量程的约20%处。如果直接用“原始值÷27648×5”,零点就会偏很多,显示值虚高。
这段转换我倾向于放在PLC程序里做一次,然后把运算结果(真实工程值)放到组态王变量的连接区,而不是让组态王去做二次计算。这样组的变量更直观,调试时也能在PLC侧监控判断仪表本身准不准。
3.4 设备互锁与保护逻辑
设备互锁是最能体现工程经验的地方。比如:鼓风机启动前,必须确认对应好氧池的潜水搅拌器已在运行,避免局部曝气不均;加药泵只有在其对应的进水调节阀打开后、且有流量信号的情况下才允许启动,防止药剂投加到干管道里。
还有一条关于电动阀的逻辑:开阀和关阀两个输出必须做互锁,严禁在程序逻辑中同时输出开和关两个指令。我在接线图上为每个阀加了单独的中间继电器,在PLC程序里再写了一道软互锁,双重保护。这属于“用不到的时候感觉多余、一旦误操作就救命”的设计。
4. 组态王动画仿真画面开发
组态王(KingView)这部分,可能是很多人觉得“最难”的地方——因为画图容易,画“会动”的画面才是核心难点。这里我按数据词典、画面组织、动画连接、命令语言四个层次来拆。
4.1 数据词典是画面的“变量中枢”
组态王的数据词典里需要定义两类变量:
- IO变量:与PLC通信交换数据,变量名要和PLC侧一致。比如在PLC程序中设定VW100为提升泵运行状态字,那么在组态王数据词典中就要新建一个整数变量“提升泵状态字”,对应设备地址VW100。组态王会通过通信驱动周期性读写这个地址;
- 内存变量:仅保存在组态王内部,不参与PLC通信。这类变量多用作画面内部的切换标志位、变量颜色变化中间量等。
有一点必须提醒:数据词典变量的寄存器地址一旦确定,不要随意改动。因为PLC程序、组态画面、报警设置、趋势曲线全都依赖这个变量名。当然,如果非要改,最稳妥的方式是在PLC程序里用“传输变量区”做二次映射,这样上位机变量地址可以保持稳定,而PLC内部逻辑调整时不会影响组态画面。
4.2 几个核心动画效果怎么做
组态王画面里最常用到的几种动画效果,我逐一说明实现方式:
- 水池液位动态变化:画一个水池轮廓,用矩形填充,动画连接选择“模拟值”(对应液位变量),设置好数值范围和填充方向(从底部向上填充)。难点在于:填充量的百分比要与液位量程对齐,否则画面显示比例和实际液位不符。我的做法是专门在数据词典里建一个“液位百分比”内存整数变量,由单片机逻辑或组态脚本计算好百分比后再填到动画连接里;
- 管道液体流动效果:组态王支持线条的颜色或可见性动画。你可以在管道线上绘制一系列小线段,通过一个0-100的“流动偏移量”变量来控制这些小线段的可见性顺序变化,视觉上就像水在流动。这个效果不复杂,但很出彩;
- 泵/风机旋转动画:用一个圆形齿轮图片,动画连接“旋转角度”。如果PLC或脚本每周期给角度变量叠加一个固定增量,画面里的齿轮就会转起来。要控制转速,只需要调控增量和画面刷新周期;
- 报警闪烁:用“可见性”连接报警变量,同时配合一个周期变化的内存变量控制颜色闪烁。报警发生时红色亮起,变量在0/1间周期性切换,画面就会一闪一闪的,非常醒目。
我在搭这套画面时发现一个细节:组态王画面分辨率和运行时的桌面分辨率如果不匹配,动画位置会整体偏移。所以工程里可以给画面底图设置固定大小并开启“画面缩放”功能,或者干脆按目标显示器分辨率去设计底图尺寸。
4.3 命令语言脚本与仿真演示
组态王的命令语言(脚本)是实现交互的关键。比如在画面中添加“自动/手动”切换按钮:
// 切换按钮的命令语言(左键按下时触发) 自动模式标志 = 1 - 自动模式标志; // 置反标志位当画面处于仿真演示模式(没有连接真实PLC)时,还可以写一个“模拟液位源”脚本,用随机数或正弦函数模拟液位缓慢上升和泵抽水下降的过程。这样整个画面就“活”起来了。但这里要强调:仿真脚本只用于演示完整状态,不要影响真实IO变量的写操作。具体做法是把模拟状态和真实状态通过一个“仿真使能”内部变量分开,互不干扰。
4.4 画面之间跳转与变量传递
一套完整的组态王画面通常不止一页。我会把它们组织成:
- 总览画面(全厂工艺概览,一眼看见所有设备状态)
- 泵站细览画面(集水井、提升泵机组、液位曲线)
- 生化单元画面(曝气池DO值、风机运行组态)
- 报警历史画面与实时趋势曲线窗口
画面之间的跳转用“画面切换”按钮实现,按钮的命令语言是:
ShowPicture("泵站细览");变量名和画面名要保持规范,否则画面调用时找不到对象。另一个常见问题是:画面从A跳到B再跳回A时,A上的一些动画不见了——这是因为画面画面被关闭再打开后,变量重新初始化,连接关系没有完美恢复。解决办法是尽量避免频繁切换画面,多使用“窗口叠加显示”的功能,或者在每个画面打开命令中重新初始化需要的变量。
5. 调试现场记录的四个真实坑点
这一部分是我最想在文章里分享的内容。调试过程是项目中最耗时也最涨经验的环节,遇到的所有问题基本都在通信、干扰、逻辑边界和画面连接这几个类别里。
5.1 组态王与PLC通信不上,先从这里查
刚做完画面打算连PLC时,组态王显示“通信失败”,这是我们第一次调试遇到的第一个挡路石。我的排查顺序是:
- 检查PLC通信端口参数(波特率、数据位、停止位、校验位)是否与组态王设备配置完全一致,组态王默认是9600,8,1,无校验,PLC侧如果默认是19200或者偶校验,必然连不上;
- 检查COM口号是否被其他程序占用(组态王和老版PLC编程软件同时开着,COM口冲突是常见问题);
- 检查PLC驱动选择是否正确——组态王里有专门的PLC驱动列表,选择“Modbus TCP”和选择“某品牌专用驱动”虽然最终可能都能通信,但数据地址的偏移规则可能不同,地址对不上也会通信失败。
这里建议:上位机与PLC的通信参数做成一张表,挂在项目文件夹里,避免三个月后再看项目时忘了当初设的是什么。
5.2 液位波动导致泵频繁启停,加了死区才解决
这个问题的现象是:调试期间提升泵在几分钟内频繁启停,接触器不断吸放。原因是集水井液位信号在临界点附近小幅抖动,导致液位值反复跨过高/低阈值。
解决办法是典型的“死区控制”思路:
- 和原来的单一启泵阈值不同,改为启泵“高液位”阈值设为2.5m,停泵“低液位”阈值设为0.8m,两个阈值之间保持1.7m的死区带;
- 液位只要不超过高阈值,即使在这个区间内波动,也不会触发启动;
- 类比来说,这就像空调温度控制器的“±1℃温差”,没有死区控制,系统就会一直抖。
有条件的还可以在程序里做模拟量滤波(取多次采样平均或采用一阶惯性滤波),但这里提醒一下:滤波时间常数不能太大,否则液位快速上升时泵启动会严重延迟,可能造成溢流风险。我们在现场最终采用“滑动平均滤波,取样周期1秒、取5次平均”,效果最稳。
5.3 组态王变量类型不匹配造成的显示异常
组态王画面连好变量后,液位显示是负数、设备状态怎么都不亮,这类问题多半是变量的数据类型或标准格式没对齐。
比如:PLC里用VW存储的液位是带小数点两位的浮点值(用两个字表示32位浮点数),而组态王数据词典里定义的却是一个16位整数变量,结果必然错乱。又比如PLC输出的是16位二进制位串(设备状态包),组态王却把它当成整数显示,是无法直接判断设备是否运行的。
我的建议是:建立上位机变量表时,明确标注每个变量的类型(Bool/Byte/Int/Real)、读写属性(只读/只写/读写)、数据长度和量程范围。组态侧的每个IO变量都要和这张表一一对应。
5.4 模拟量信号受干扰,屏蔽接地解决
还有一次在调试中发现pH读数周期性跳变,怀疑是仪表故障,但就地pH变送器显示正常。后来用万用表测PLC模拟量输入端的信号,发现在2mA左右的波动,才确定是信号传输环节的干扰。
排查下来原因有两处:
- 现场信号电缆的屏蔽层在PLC端和设备端都接了地,造成“两端接地”,反而形成地环路;
- 仪表电缆和动力电缆在同一根线槽内并行走线,干扰直接从动力侧耦合过来。
处理方式是:屏蔽层改为PLC侧单端接地,仪表侧屏蔽层悬空;同时把仪表信号电缆尽量移出动力电缆槽,或者加装金属隔离板。干扰问题处理完以后,pH信号稳定在了0.1以内。这类问题在污水处理现场非常常见,因为现场的变频器、电机启停对模拟量回路干扰很大。
6. 把这一整套交付物变成可复用的项目经验
这套系统做完之后,交付物包括了PLC源程序、组态王源程序、电气图纸、IO地址分配表和多版调试记录。回头复盘,最大的收获不是哪一个函数写得漂亮,而是整个项目形成了一个可以复用的“模板”。后续再做同类项目时,我从工艺拆解到地址分配再到画面开发,可以直接沿用这套框架,省掉大量重复沟通和设计的时间。
6.1 文档比代码更值钱
项目交付时,我最花心思整理的反而不是程序本身,而是三份文档:
- IO地址分配总表:把地址、设备名称、信号类型、线号、仪表量程、组态变量名全部列在一张Excel里,这是现场查线和后续维护的唯一“地图”;
- 控制逻辑说明:每一条联锁条件、定时时间、模拟量转换公式都写成文字,不依赖代码注释;
- 调试记录:把每一次异常现象、排查步骤、修改措施按时间记录成表,既是对业主的交代,也是自己下次做项目的参考。
这组文档里能看出工程师的做事习惯。很多项目最终程序能跑通,但半年后运维人员想改一个定时时间,根本无从下手,这才是项目失败的一半。
6.2 后续可以往哪些方向扩展
这套系统如果后面要做功能升级,优先考虑的方向有三个:一是增加变频器控制,鼓风机从“启停控制”升级为“按DO浓度自动调节转速”,节能效果立竿见影;二是把模拟量点位扩展为多因子自动加药闭环,靠pH和流量信号实时调整加药泵频率;三是做远程监控,把PLC通过网关接入物联网平台,在中控室之外用手机App查看实时运行状态和报警信息。
无论往哪个方向扩展,底层的IO分配、程序框架和组态变量结构都不用推翻重来,这就是前期设计阶段花时间把地基打牢的回报。
最后分享一个小技巧:整个项目做完,我习惯把组态王工程每人一个备份压缩包放在项目文件夹里,命名为“日期_版本号”。调试过程中每改一次画面或程序,就另存一个版本。这个习惯救了我很多次——有一次画面联动怎么都调不好,翻回三天前的版本一对比,立刻发现是一处脚本变量被后来加的功能误改了。版本控制对单人开发也同样重要,因为你的记忆永远没有磁盘记录可靠。