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连接流程:

  1. 客户端发现服务器(通过mDNS或手动配置)
  2. 建立安全通道(证书交换)
  3. 创建会话(Session)
  4. 浏览地址空间(找到你要的节点)
  5. 订阅数据变化(实时推送)
// 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
  • 数据预处理:滤波、去重、聚合
  • 本地缓存:网络断了也不丢数据
  • 远程管理:通过云平台配置和监控

下面是我常用的边缘网关配置流程:

  1. 硬件选型:根据现场设备数量选CPU和内存。一般建议4核CPU、4GB内存起步。
  2. 操作系统:我习惯用Ubuntu Server或Debian,稳定且驱动全。
  3. 安装驱动:各家PLC的驱动库(如Snap7、libplctag)
  4. 配置采集任务:定义采集周期、数据点映射
  5. 配置上行通道:MQTT、OPC UA、或HTTP API
  6. 测试与调优:检查数据完整性,调整采集频率

小技巧:边缘网关的采集周期不要设得太短。我见过有人把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 数据采集架构总览

下面这张图展示了从现场设备到云端的完整数据流。你可以看到,边缘网关是整个架构的核心枢纽。

数据采集架构图 数据采集架构总览 PLC(西门子/三菱) Modbus TCP / 私有协议 仪表/传感器 Modbus RTU / 4-20mA 变频器/驱动器 Modbus / Profinet 边缘网关 协议转换 · 数据缓存 · 本地处理 云平台 / MES / 数据库 MQTT · OPC UA · HTTP API 说明:边缘网关支持断网续传,本地缓存至少保存7天数据 推荐使用MQTT + TLS加密传输,确保数据安全

3.8 常见问题与解决方案

做数据采集这么多年,我踩过的坑可以写一本书。这里列几个最常见的:

问题 现象 解决方案
通信超时 设备偶尔不响应 增加重试机制,设置超时时间3-5秒
数据错位 读到的值明显不对 检查字节序(大端/小端)和数据类型
网络风暴 网关CPU 100% 限制采集频率,使用异步IO
证书过期 OPC UA连接失败 设置证书自动续期,提前30天告警
数据丢失 历史数据有空洞 边缘网关加本地缓存,断网自动补传

最后说一句:数据采集不是一锤子买卖。设备会老化、网络会波动、协议会升级。你设计采集系统时,一定要考虑可维护性和可扩展性。我见过太多项目,采集系统上线后没人管,半年后数据全断了。记住,好的采集系统是「无人值守,但随时可查」的。