3. 数据采集实战:PLC数据采集、OPC UA协议、Modbus TCP/RTU通信、边缘网关配置
数据采集这件事,说白了就是让设备开口说话。我在工厂里见过太多设备,明明跑得好好的,但就是没人知道它内部发生了什么。今天我们就来聊聊,怎么把这些铁疙瘩的数据给「掏」出来。
3.1 工业通信协议的三驾马车
做数据采集,绕不开三种协议:Modbus、OPC UA,以及各家PLC的私有协议。我个人习惯把它们分成两类——能直接读的和需要中间人翻译的。
| 协议 | 传输层 | 典型场景 | 我的评价 |
|---|---|---|---|
| Modbus RTU | RS-232/485 | 老旧仪表、变频器 | 稳定但慢,适合小数据量 |
| Modbus TCP | 以太网 | 新装设备、PLC从站 | 速度快,接线简单 |
| OPC UA | TCP/IP | 跨平台、安全要求高 | 现代工厂的首选 |
| PLC私有协议 | 串口/以太网 | 西门子、三菱、欧姆龙 | 性能好,但需要SDK |
核心原则:能走OPC UA就别走Modbus,能走Modbus TCP就别走RTU。但现实往往是——你手里只有一台20年前的温控器,只支持Modbus RTU。
3.2 Modbus RTU:老当益壮的串行通信
Modbus RTU是我最早接触的工业协议。记得2015年在一个水处理项目中,我需要采集32台水泵的电流和振动数据。现场只有一条RS-485总线,所有设备都挂在这根线上。
它的工作原理其实很简单:主站问,从站答。主站(通常是PLC或工控机)发送一个请求帧,从站(设备)回复数据帧。帧结构如下:
请求帧格式:
[地址码 1字节] [功能码 1字节] [起始地址 2字节] [寄存器数量 2字节] [CRC校验 2字节]
响应帧格式:
[地址码 1字节] [功能码 1字节] [数据长度 1字节] [数据 N字节] [CRC校验 2字节]
避坑指南:我曾经在一个项目中,CRC校验算错了三天。后来发现是字节序搞反了——Modbus RTU用的是低位在前、高位在后。你写代码时一定要确认字节序,否则设备永远不会理你。
常用的功能码就几个:
- 0x03:读取保持寄存器(最常用)
- 0x04:读取输入寄存器
- 0x06:写单个寄存器
- 0x10:写多个寄存器
举个例子,读取地址为1的从站,从寄存器0x0000开始读2个寄存器:
请求:01 03 00 00 00 02 C4 0B
响应:01 03 04 00 01 00 02 79 CB
解析:寄存器0x0000 = 0x0001,寄存器0x0001 = 0x0002
3.3 Modbus TCP:把串口搬到以太网上
Modbus TCP其实就是Modbus RTU的以太网版本。它去掉了CRC校验(因为TCP/IP本身有校验),加了一个MBAP报文头。嗯,这里要注意:Modbus TCP的端口号是502,很多IT防火墙默认会封这个端口,你得提前跟网络管理员打招呼。
帧结构对比:
| 字段 | Modbus RTU | Modbus TCP |
|---|---|---|
| 地址 | 1字节设备地址 | MBAP中的单元标识符 |
| 校验 | 2字节CRC | 无(依赖TCP) |
| 报文头 | 无 | 7字节MBAP |
| 最大数据 | 253字节 | 260字节 |
注意:Modbus TCP虽然方便,但它是明文传输的。如果你采集的数据涉及工艺参数或质量指标,建议用OPC UA或者加一层VPN。我在一个汽车零部件工厂就遇到过,有人通过抓包直接拿到了产线的配方数据。
3.4 OPC UA:现代工业的通用语言
OPC UA(统一架构)是我现在最推荐的协议。它解决了传统OPC DA的两个痛点:依赖COM/DCOM和安全性差。OPC UA是跨平台的,Linux、Windows、嵌入式设备都能跑。
它的核心概念是地址空间——所有数据都组织成节点,节点之间有层次关系。比如一个电机,它的电流、转速、温度都是子节点。你想想看,这比Modbus那种「寄存器地址表」的方式直观多了。
一个典型的OPC UA连接流程:
- 客户端发现服务器(通过mDNS或手动配置)
- 建立安全通道(证书交换)
- 创建会话(Session)
- 浏览地址空间(找到你要的节点)
- 订阅数据变化(实时推送)
// Python示例:使用opcua库连接
from opcua import Client
client = Client("opc.tcp://192.168.1.100:4840")
try:
client.connect()
# 浏览根节点
root = client.get_root_node()
print("根节点:", root)
# 获取变量值
temp = client.get_node("ns=2;i=1001")
print("温度值:", temp.get_value())
# 订阅变化
def data_change_notification(node, val, data):
print(f"{node}: {val}")
sub = client.create_subscription(100, data_change_notification)
sub.subscribe_data_change(temp)
# 保持连接
while True:
time.sleep(1)
except Exception as e:
print("连接失败:", e)
finally:
client.disconnect()
我的经验:OPC UA的证书管理是个坑。开发环境可以用「无安全模式」,但生产环境一定要启用签名和加密。我见过一个工厂,OPC UA服务器裸奔了两年,直到被勒索软件加密了所有PLC程序……
3.5 边缘网关:数据采集的桥头堡
边缘网关是什么?说白了就是一个放在现场的小型计算机。它负责把各种协议的数据收上来,然后统一转发到上层系统。我参与过的一个钢铁厂项目,现场有西门子S7-1200、三菱FX5U、还有一堆Modbus仪表,全靠一台边缘网关搞定。
边缘网关的核心功能:
- 协议转换:Modbus → OPC UA,或者PLC私有协议 → MQTT
- 数据预处理:滤波、去重、聚合
- 本地缓存:网络断了也不丢数据
- 远程管理:通过云平台配置和监控
下面是我常用的边缘网关配置流程:
- 硬件选型:根据现场设备数量选CPU和内存。一般建议4核CPU、4GB内存起步。
- 操作系统:我习惯用Ubuntu Server或Debian,稳定且驱动全。
- 安装驱动:各家PLC的驱动库(如Snap7、libplctag)
- 配置采集任务:定义采集周期、数据点映射
- 配置上行通道:MQTT、OPC UA、或HTTP API
- 测试与调优:检查数据完整性,调整采集频率
小技巧:边缘网关的采集周期不要设得太短。我见过有人把100个数据点都设成100ms采集一次,结果网关CPU直接跑满。一般工艺数据1秒一次就够了,振动数据可以设到10ms,但要做好数据压缩。
3.6 实战案例:从PLC到数据库的全链路
我们来看一个完整的例子。假设现场有一台西门子S7-1200 PLC,需要采集它的温度、压力和流量数据,存到云端数据库。
第一步:确定通信方式
S7-1200支持多种协议:Profinet、Modbus TCP、以及西门子私有协议。我建议用西门子私有协议,因为它效率最高。用Snap7库可以轻松读写:
import snap7
plc = snap7.client.Client()
plc.connect('192.168.0.1', 0, 1)
# 读取DB1.DBW0(温度)
temp = plc.db_read(1, 0, 2)
temp_value = struct.unpack('>h', temp)[0] / 10.0
# 读取DB1.DBW2(压力)
pressure = plc.db_read(1, 2, 2)
pressure_value = struct.unpack('>h', pressure)[0] / 100.0
print(f"温度: {temp_value}°C, 压力: {pressure_value}MPa")
第二步:边缘网关中转
在边缘网关上运行一个Python脚本,把数据转成JSON格式,通过MQTT发送:
import paho.mqtt.client as mqtt
import json
client = mqtt.Client()
client.connect("mqtt.cloud.com", 1883, 60)
while True:
data = {
"timestamp": time.time(),
"temperature": temp_value,
"pressure": pressure_value
}
client.publish("factory/line1/data", json.dumps(data))
time.sleep(1)
第三步:云端接收与存储
云端的MQTT Broker收到数据后,写入时序数据库(如InfluxDB)。这样你就可以在仪表盘上实时看到数据了。
重要提醒:数据采集的可靠性比实时性更重要。我曾经因为网络抖动丢了一天的数据,后来在边缘网关上加了本地SQLite缓存,网络恢复后自动补传。这个设计现在成了我所有项目的标配。
3.7 数据采集架构总览
下面这张图展示了从现场设备到云端的完整数据流。你可以看到,边缘网关是整个架构的核心枢纽。
3.8 常见问题与解决方案
做数据采集这么多年,我踩过的坑可以写一本书。这里列几个最常见的:
| 问题 | 现象 | 解决方案 |
|---|---|---|
| 通信超时 | 设备偶尔不响应 | 增加重试机制,设置超时时间3-5秒 |
| 数据错位 | 读到的值明显不对 | 检查字节序(大端/小端)和数据类型 |
| 网络风暴 | 网关CPU 100% | 限制采集频率,使用异步IO |
| 证书过期 | OPC UA连接失败 | 设置证书自动续期,提前30天告警 |
| 数据丢失 | 历史数据有空洞 | 边缘网关加本地缓存,断网自动补传 |
最后说一句:数据采集不是一锤子买卖。设备会老化、网络会波动、协议会升级。你设计采集系统时,一定要考虑可维护性和可扩展性。我见过太多项目,采集系统上线后没人管,半年后数据全断了。记住,好的采集系统是「无人值守,但随时可查」的。