简介:这是面向加油站信息化管理领域的毕业设计论文资源,主题为加油机数据采集与状态监控系统,适用于机械设计制造及其自动化、自动化、计算机等相关专业学生参考毕业设计、课程设计或工程实训。文档从加油站传统人工记账与人工测罐的痛点切入,系统阐述以数据采集器为纽带的上位机、加油机、液位仪协同架构,重点覆盖数据采集器的软硬件设计、上位机数据采集动态库、监控程序功能以及通信协议设计,并讨论模块化结构增强系统适配多样加油机的思路。完整呈现中英文摘要、目录、正文与参考文献,涵盖选题背景、系统总体设计、硬件选型到上位机软件实现的全过程。资源为单个docx文档,共1个文件,压缩包大小193KB,格式规整可直接阅读与二次修改。目前已有107人学习下载,适合需要从需求分析、总体设计到程序实现完整梳理加油站监控系统开发流程的本科生参考。
1. 加油站数据采集与状态监控系统:一台工控机把罐区、加油机和报警器串成一张能信的网
深夜两点,油罐液位数据对不上账,加油机脉冲计数和收银台流水差了几十升,值班员抄了三次表还是三个数——这不是某个加油站独有的问题,而是站级自动化的常态。加油站数据采集与状态监控系统,本质是一套贴着防爆规范走、规模不大但可靠性要求极高的轻量 SCADA:现场 PLC 和液位仪负责取数,站控工控机做边缘计算与本地监控,再按需把数据上报到区域平台。它要解决的不只是“把数据读出来”,而是让油罐液位、加油机状态、可燃气体报警这些关乎安全经营的信号,在断电、干扰、设备老化的情况下依然准确、连续、可回溯。这套系统的读者,多是做站级集成的自动化工程师、连锁油站的信息化运维,以及准备把传统站点改造成数据资产的能源数字化团队。这篇文章按我实际落地过的路径,从架构选型一直讲到参数调试与踩坑,给你一条能直接照做的实施路线。
2. 站控系统架构与设备选型:PLC、液位仪、边缘网关先各自归位
2.1 三层架构怎么划,数据才不打架
常见做法是把加油站监控系统拆成现场设备层、站级边缘层、中心平台层。现场设备层包含加油机、油罐液位仪、可燃气体探测器、卸油区的静电接地报警器以及负责汇总信号的 PLC 或 RTU;站级边缘层是一台工控机或边缘网关,跑数据采集服务、本地数据库和 HMI 画面;中心平台层则接收上传的汇总数据,负责多站对比分析和远程运维。
我见过不少项目把采集逻辑直接塞进中心平台,站点只做透传,结果网络一抖动整条链路都跟着抖。正确的边界是:站级边缘层必须能在断网时独立完成采集、存储和本地告警,网络恢复后再补传。这样即使运营商线路中断,站内监控也不至于变成瞎子。
2.2 PLC 与站控的通讯方式:串口、以太网和 OPC UA 怎么选
站内设备的通讯协议远比想象中杂。加油机常见的是 RS485 总线的 Modbus RTU,或厂家私有的脉冲信号;液位仪多用串口输出,协议往往是罐厂自定义的 ASCII 帧;而 PLC 这边,既有老站的串口 Modbus,也有新站的以太网 Modbus TCP 或 Profinet。把这些协议统一到站控,最常用的做法是让 PLC 做一级汇聚,站控再通过 Modbus TCP 与 PLC 通讯——这样 PLC 把加油机脉冲、液位仪模拟量、报警器开关量先转换成统一的寄存器地址,站控只面对一个设备,省去逐台设备适配的麻烦。
那什么时候直接用 OPC UA?当站控需要和上层 ERP 或区域 SCADA 平台做标准化对接时,我会在边缘层部署一个轻量 OPC UA 服务器,把本地采集的数据映射为标准节点。它能省掉自定义接口的联调成本,但也要求工控机配置别太低,至少 4 核 CPU、8GB 内存,否则 OPC UA 的会话开销会把采集线程拖慢。如果只是站内自用,Modbus TCP 到平台反而更省事。
2.3 站点硬件清单与防爆选型边界
站级边缘层的选型直接决定系统稳定性。工控机要选无风扇、宽温(-20℃到 60℃)、支持 9~36V 直流供电的型号,硬盘用工业级 SSD,电源加一层 DC-DC 隔离模块,防止加油机启停时的电压跌落把系统打重启。如果站点有 PLC,选型时注意 CPU 的通信口数量至少留一个冗余口做调试,否则以后加设备就得现场拆线。
防爆是加油站绕不开的红线。安装在爆炸危险区域的变送器和仪表必须有对应防爆等级的证书,罐区的液位仪和可燃气体探测器一般要求本安型(Ex ia),现场接线必须经过防爆挠性管或格兰头。站控工控机如果放在营业室或站房内,属于非危险区域,不需要防爆认证,但如果是放在罩棚立柱下的室外机柜,就得按正压型或隔爆型机柜来配置。这部分没有商量余地,验收时检查防爆合格证和安装方式,比检查通讯参数优先得多。
3. 用 Modbus 轮询把采集跑起来:从点表到最小可用代码
3.1 先把点表建明白:加油机、油罐和报警器的采集项
动手写代码之前,必须先把点表定清楚。一份合格的加油站采集点表至少包含三类:加油机数据(每台油枪的累计升数、单价、金额、当前状态字、故障码)、油罐数据(液位、油高、水高、油温、容积、报警状态)、安全数据(可燃气体浓度、静电接地状态、紧急切断阀状态)。点表的每一项要写明寄存器地址、数据类型(16 位无符号、32 位浮点还是开关量)、读写属性和量程。
这里有个关键点:油罐容积不是直接读出来的,而是液位仪给出油高后,由罐容表(静压法或几何法标定)换算出的。液位仪通常直接输出体积值,但如果你用的是只输出液位的罐厂协议,就得在站控里维护一张罐容表并按液位插值。这个换算做错,盘点差异会直接怪到采集系统头上。
3.2 最小轮询代码:pymodbus 实现与超时参数详解
下面是一个用 Python + pymodbus 实现的站控最小轮询脚本,采用同步客户端连接 PLC 的 Modbus TCP 服务,按点表读取保持寄存器。这里给的是 pymodbus 3.x 的常见写法,我在生产环境也是这样组织循环的。
from pymodbus.client import ModbusTcpClient import time # 站控工控机到 PLC 的 Modbus TCP 连接 client = ModbusTcpClient("192.168.1.20", port=502, timeout=1.5) if not client.connect(): raise SystemExit("PLC 连接失败,检查网线和 PLC 侧 IP 配置") # 点表:寄存器起始地址、数量、含义 READ_GROUPS = [ (0x0000, 10, "加油机1累计升数"), # 10 个寄存器:5 台加油机各 2 个寄存器 (0x0100, 8, "罐区液位"), # 4 个油罐的液位与温度 (0x0200, 4, "可燃气体报警状态"), ] def read_block(address, count, name): # pymodbus 3.x 的读取结果放在 response.registers 中 response = client.read_holding_registers(address, count, slave=1) if response.isError(): # 错误时记录日志,不终止进程,交给上层重试逻辑 print(f"[{time.strftime('%H:%M:%S')}] 读取失败: {name} - {response}") return None return response.registers while True: for start, count, name in READ_GROUPS: values = read_block(start, count, name) if values: # 具体解析按点表定义,例如液位 = 原始值 * 0.01 print(f"{name}: {values}") time.sleep(0.2) # 组间间隔 200ms,防止总线占用过高 time.sleep(2) # 整轮轮询间隔 2 秒,可按现场调逻辑说明:脚本用一个死循环按组读取 PLC 保持寄存器,每组间休眠 200ms,整轮间隔 2 秒。这个节奏在站点场景下已经足够,因为加油机累计升数、罐液位都是慢变量,1 秒级的变化没有监控意义;而可燃气体报警虽然需要快,但报警信号一般也由 PLC 的数字量输出直接联动声光报警器,站控轮询只是做记录,不需要毫秒级响应。
参数说明:timeout=1.5是单次 Modbus 请求的超时,站点局域网内这个值设 1~2 秒合适。设太短,PLC 在忙时容易误报离线;设太长(比如 5 秒),一旦某个设备断线,整轮采集周期会被拉长到几十秒,后面告警的实时性就全毁了。slave=1是 PLC 的 Modbus 从站地址,多台 PLC 时分别设 1、2、3 即可。
3.3 数据上云:MQTT 上报与断电续传
很多加油站项目要求站控把数据上报到区域中心,用的较多的是 MQTT 协议,因为轻量、且天然支持断线重连和遗嘱消息。上报线程和采集线程要分开,否则网络抖动会影响本地采集的稳定性。
import paho.mqtt.client as mqtt import json # 上报线程独立使用一个 MQTT 连接,和采集循环解耦 mqtt_client = mqtt.Client(client_id="station-001", protocol=mqtt.MQTTv311) mqtt_client.connect("10.10.0.6", 1883, keepalive=15) def upload(active_events): payload = json.dumps({ "station": "001", "ts": int(time.time()), "data": active_events, }) # 设置 retain=False,只发送当前数据,避免历史数据占用平台存储 mqtt_client.publish("station/001/meter", payload, qos=1)参数说明:keepalive=15是 MQTT 的心跳间隔,小于这个值没有数据包往来时,服务端会断开连接;站点网络不稳定时把它放宽到 20~30 秒更稳妥。qos=1保证消息至少到达一次,配合站控本地的 SQLite 落盘做断电续传——发送前写本地待发送表,收到平台 ACK 后删除记录,平台侧按ts做幂等去重。这样即使断网一小时,恢复后数据也能补齐。
4. 状态监控规则设计:阈值、状态机和告警分级
4.1 加油机状态怎么判断:脉冲计数与故障码映射
加油机采集的核心不是油枪的开关状态,而是脉冲信号累计值。每升油对应固定脉冲数(常见 100~1000 脉冲/升),PLC 高速计数器累加后得到累计升数,站控再按时间差算流速。状态判断要用状态机:待机、正在加油、完成加油、故障。从“待机”到“加油”的跳变条件是脉冲增量大于阈值且持续超过 2 秒,避免电磁干扰造成的单脉冲误触发。
故障码映射则依赖加油机厂家的协议文档。同一厂家的不同型号,故障码定义都未必一致,比如某品牌代码 03 表示电机过载,另一型号 03 却是通讯故障。踩过的坑是把 A 型号的映射表直接套到 B 型号上,导致报警全部乱掉。正确做法是在点表里给每台加油机单独配一张故障码映射表,维护在站控的配置文件里,换机时只改配置不改代码。
4.2 油罐液位与泄漏监控:不是设置上下限那么简单
油罐液位监控如果只做“高报警、低报警”,会在实际运行中产生大量误报。液位仪数据在卸油时快速上升、在加油高峰缓慢下降,单纯按固定上下限判断,卸油刚启动就会触发高液位报警。我常用的做法是做变化率判断和差分逻辑:液位变化率超过阈值(比如每分钟超过 2 厘米)才判定为异常波动;而泄漏检测则专注静态时段——停业后 1 小时液位没有外部因素干扰,此时液位下降速率若持续超过 0.2 毫米/分钟,才提示疑似渗漏。
温度补偿也要做。油品热胀冷缩会导致液位读数在昼夜温差大的地区出现假变化,体积值必须按标准温度(通常 20℃)折算。液位仪一般直接输出温度,站控保存温补系数,否则夏天中午和凌晨的数据对比会得出“罐在漏油”的荒唐结论。
4.3 告警分级与展示:让值班员 5 秒看懂现场
告警不分级,是加油站监控系统最常见的败笔。把所有异常都推到同一张列表,值班员看 10 分钟也不知道先处理哪个。我按紧急程度把告警分成三级:
| 级别 | 示例 | 响应要求 | 通知方式 |
|---|---|---|---|
| 紧急 | 可燃气体浓度超限、油罐液位突变、泄漏疑似 | 立即现场确认并处置 | 声光报警 + 短信/电话推送 |
| 重要 | 加油机故障、通讯中断、液位高/低限 | 2 小时内处理 | 站控弹窗 + 平台消息 |
| 一般 | 单次轮询超时、数据校验不一致 | 当班内关注 | 站控日志记录 |
展示规则有一条红线:紧急告警必须置顶并全屏变色,不能和一般告警混排。我在站控 HMI 上做了“告警聚焦”功能,按下确认键后紧急告警仍在顶部保留 30 分钟,防止值班员确认完就忘。分级规则写在一个配置文件里,每个站点可以独立调整阈值,但分级逻辑本身不开放给站端随意改,否则集团统一管控就成了摆设。
5. 加油站数据采集避坑:通讯干扰、数据错乱与掉线重连排查
这一章我直接按排查记录来写,每一条都是现场真实遇到过、并且会反复出现的坑。
5.1 现象:加油机脉冲在启停瞬间大量丢失
现象:加油结束后,收银台总升数和 PLC 脉冲累计值差出 0.3~0.5 升,多台加油机都有此问题,高峰时段更明显。 原因:加油机内部电机启停瞬间产生浪涌电流,通过信号线耦合进脉冲回路;同时部分站点使用非屏蔽双绞线走脉冲信号,长距离并行于动力线,干扰被成倍放大。 解决:脉冲线全部换成屏蔽双绞线,屏蔽层在 PLC 侧单端接地,信号线走单独的金属线槽,和动力线保持 30cm 以上间距。在 PLC 的高速计数模块上开启数字滤波,滤掉小于 5μs 的窄脉冲。这类问题靠程序过滤很难根治,因为丢的是物理信号,软件看不到。
5.2 现象:液位仪数据偶尔跳变,两个采集端读数不一致
现象:站控显示某罐液位在 1 秒内跳了 5 厘米,随后恢复;且同一台液位仪,PLC 读取和站控直连读取的数据有时差 1 个字节的解析误差。 原因:液位仪是 RS485 串口菊花链,多台设备并挂同一条总线。站控的采集服务和 PLC 同时向液位仪发起读取请求时,没有做到一主多从的时序仲裁,两个主站同时发命令导致从站应答帧冲突,数据帧被截断或被错误解析。 解决:统一由 PLC 作为串口主站读取液位仪,站控不再直连串口。PLC 把解析后的数据放到寄存器,站控只读寄存器。这样从链路层面消除双主站竞争。如果必须保留站控直连,就得在站控采集服务里加串口信号量锁,让两个采集任务排队访问。
5.3 现象:Modbus 轮询偶尔超时,采集周期越拖越长
现象:站控日志里每隔几分钟出现一条 “Timeout” 记录,轮询时间从正常的 2 秒涨到 6 秒以上。 原因:这是慢发问题,不是断线。PLC 的 Modbus 响应慢,但站控的超时设得偏长(比如 5 秒),单次超时直接占用 5 秒,整轮周期自然膨胀。深层原因是 PLC 的通信负载过高——同时被 OPC UA 服务器、HMI 触摸屏和站控脚本轮询,PLC 的通信缓冲区不够用。 解决:把 Modbus 超时调到 1.5 秒以内,超时后立即记录并跳过该组,不阻塞整轮。再在 PLC 侧调大 Modbus 从站通信缓冲区,并降低 HMI 的刷新频率(从 500ms 改到 2 秒)。还有一招:把 READ_GROUPS 里变化慢的罐区数据从轮询改为按需读取,比如每 30 秒读一次,减轻总线负担。
5.4 现象:工控机重启后采集服务没起来,数据缺口一整晚
现象:夜间市电闪断,UPS 撑了 3 分钟,工控机正常关机后重启,但第二天发现从凌晨 2 点到早上 7 点完全没数据。 原因:采集服务依赖数据库服务和网络连通后才开始工作,但服务的自启动方式没有做依赖等待;更常见的是服务配置成 “登录时启动”,但工控机开机后停在登录界面,服务根本没触发。 解决:把采集服务注册成 Windows 服务,设置“自动(延迟启动)”或做成 Linux systemd 服务并配置After=network-online.target和Restart=always。在采集主程序里加启动自检:等数据库端口连通、PLC 网络可达之后再进入主循环,并每 30 秒重试一次。这样断电恢复后,系统能自愈,不需要人员现场点启动。
5.5 现象:告警风暴把消息通道打满,真实的泄漏反被淹没
现象:某次液位仪通讯中断 20 分钟,系统对每个采集点连续发送不通告警,短信平台被刷了几百条,值班员把手机静音了;而当晚恰好有轻微泄漏告警,被淹没在消息列表里没被看见。 原因:告警逻辑没有做“抖动抑制”和“恢复确认”。同一个故障在每次轮询失败时都触发一次新告警,而不是合并为一条持续告警;告警产生次数没有上限控制。 解决:对每个告警源引入状态跟踪——故障发生时生成一条告警,后续轮询仍失败只更新该告警的最后时间,不重复生成新告警;恢复后自动关闭,系统记录故障总时长。再给同一站点设置 5 分钟内同类告警最多 3 条的限流策略,超出后只保留第一条并标记“持续”。这样短信平台安静了,紧急告警才能被真正看见。
6. 数据治理与系统验证:从“能跑”变成“敢信”
采集系统上线只是开始,运行三个月后,数据质量才是核心问题。三个习惯值得坚持。
第一是时钟同步。没有 NTP 的站控,半年后系统时间和手机差出几分钟,告警时间线对不上账,平台排查问题会极其痛苦。在工控机里配ntpdate定时同步,站点离线时至少保证本地时钟不漂移超过 30 秒。
# 每天凌晨 2 点同步一次,站点网络不稳定时足够 0 2 * * * /usr/sbin/ntpdate -u 10.10.0.2 >> /var/log/ntpdate.log 2>&1第二是数据校验。我习惯在采集服务里加一层完整性校验,每轮采集完成时记录总条数和校验值。平台侧做每日核对:如果某站点某时段数据条数少于应采条数 5%,自动生成数据缺口工单,让运维确认是设备问题还是网络问题。这样,盘点差异是采集丢了还是账算错了,一查便知。
第三是故障注入演练。每季度挑一天,人为断一次 PLC 网线、停一次液位仪电源、拔一次工控机电源,观察系统能否自动恢复、数据是否完整。这套方案值不值得做,做完演练后自己会有结论:如果系统在拔电重启后能完整补传数据,那它就是可信的。
我早年在一个高速服务区站点做过一次深夜检修,因为忘记给采集服务配置重启等待,导致整站数据缺口,后来我给自己定了一条规矩——所有站控程序必须能在无人干预的断电重启后自愈。也因为这个教训,之后每个项目上线前,我都坚持做一次完整的断电恢复测试,数据缺失、告警风暴这类坑,就是在这个过程中一个个暴露并填平的。希望这些经验对你有用。
本文还有配套的精品资源,点击获取