首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >采集协议的兼容层:老设备也能接

采集协议的兼容层:老设备也能接

原创
作者头像
节点恒存
发布于 2026-10-28 09:18:26
发布于 2026-10-28 09:18:26
850
举报

2023 年 8 月,我们给一个老车间做设备联网,87 台设备,协议数出来四种。17 台 2008 年前后的老机床只有 RS485 串口,报文是厂家自己定的,手册早丢了;23 台挤压机走 Modbus RTU;31 台新一点的设备走 Modbus TCP;剩下 16 台是近五年买的,支持 OPC UA。

按台数看,三分之二的设备用的是标准协议,接起来不难。麻烦在那 17 台老机床:它们承担了车间四成的工序,产量数据缺了它们,整条线的 OEE 就没意义。厂家的人来了两次,说板卡还能用,但协议文档找不到了,只能抓包看。

结论是:不要为每种协议写一套采集程序,做一个兼容层,把协议差异关在驱动里,上层只认统一的点位模型。这样加一种新协议只改配置和驱动,不动上层。项目从 8 月做到 11 月,87 台全部接上,数据完整率百分之九十六,剩下四个点是老机床本身没有计数信号。

一、老设备不是不能接,是接法不一样

1.1 四种协议的实际差别

Modbus TCP 和 RTU 差别只在传输层,寄存器地址和含义是一套,接一种就懂另一种。OPC UA 自带信息模型,点位有名字有类型,接起来省事,但握手和会话管理要单独处理。

真正难的是私有报文。老机床的板卡每隔两秒往外吐一帧,帧头两个字节固定,后面跟长度、数据区、校验。数据区里哪两个字节是主轴转速,哪一个是运行状态,全靠抓包对着机床面板一条条试。

1.2 抓包反推字段

反推的过程很土但有效:让人在机床上操作,我盯着抓包工具看哪几个字节变了。开机、停机、调转速、按急停,每次操作记一次帧内容,比对差异字节。

主轴转速花了半天。转速从 800 调到 1200,有两个字节从 03 20 变成 04 B0,正好是 800 和 1200 的十六进制,说明是原始值不缩放,大端。报警码花了三天,因为报警只在特定条件下出现,我们守到第三天下午机床才报了一次刀具磨损。

反推还有个小技巧:先找出不变的部分。一帧里的帧头、长度、校验位是固定的,数据区里常年不变的字节多半是配置或型号,剩下会变的才是状态和参数。这样能把二十几个字节缩到七八个候选,再逐个试。

1.3 先定统一点位模型

动手写驱动之前,先定了点位模型。不管什么协议,采上来的数据只有五类:运行状态、产量计数、工艺参数、报警、能耗。

每个点位有固定字段:点位键、设备号、类型、单位、采集频率、有效范围、数据质量。上层应用只认这套,不关心底下是串口还是以太网。这一步要是省了,后面每接一种协议就要改一次上层,改三次之后代码就没法维护了。

二、适配层放在哪

2.1 驱动和映射分开

兼容层分成两半:驱动负责把字节变成数,映射负责把数变成点位。驱动按协议类型写,一共四个;映射按设备型号写,一共十一个型号。

分开的好处是新增设备型号不用写代码。同一个 Modbus 驱动,挤压机和水泵的寄存器地址不同,只是两份映射配置。车间再进同型号设备,复制一份映射改设备号就行。这套配置后来交给设备科自己维护,我们只负责驱动。

映射文件按型号命名,改一次记一次版本。有一台挤压机换了控制板,寄存器地址整体后移了 8 个,如果没有版本记录,采上来的数据会整体错位而没人发现。现在每次改映射都留一句说明,谁改的、为什么改,出问题能倒查。

2.2 字节序和缩放是主要错误源

采上来的数不对,九成出在三个地方:字节序、字序、缩放系数。字节序是高低字节的顺序,字序是 32 位数据里两个 16 位字的顺序,缩放是原始值乘的系数。

这三样在配置里必须显式写,不能靠猜。我们的规矩是每个点位都写 endian,32 位数据再加 word_order,浮点或小数量级加 scale。写全了啰嗦,但排错快——数不对的时候先看这三项,比翻手册快。

2.3 一台老机床的配置

下面这段是一台老机床和一台挤压机的适配配置,点位映射、字节序、缩放、数据质量都在里面。

代码语言:yaml
复制
devices:
  - dev_id: CNC-014
    driver: serial_frame
    link: {port: ttyS2, baud: 9600, databits: 8, parity: none, stopbits: 1}
    poll_ms: 2000
    frame:
      head: "AA55"
      len_field: 1
      tail: "0D0A"
      checksum: sum8
    points:
      - {key: run_state,   offset: 3, type: uint8,  map: {0: 停机, 1: 运行, 2: 报警}}
      - {key: spindle_rpm, offset: 4, type: uint16, endian: big, scale: 1}
      - {key: feed_rate,   offset: 6, type: uint16, endian: big, scale: 0.1}
      - {key: alarm_code,  offset: 8, type: uint8,  quality: bitmask}

  - dev_id: PRESS-003
    driver: modbus_rtu
    link: {port: ttyS4, baud: 19200, databits: 8, parity: even, stopbits: 1}
    poll_ms: 1000
    points:
      - {key: run_state,    unit_id: 1, func: 1, addr: 0,  type: bool}
      - {key: stroke_count, unit_id: 1, func: 3, addr: 12, type: uint32, word_order: low_first}
      - {key: oil_temp,     unit_id: 1, func: 3, addr: 20, type: int16, scale: 0.1}

defaults:
  stale_after_ms: 15000
  retry: {times: 2, backoff_ms: 300}
  clock: device

stale_after_ms 是这份配置里要紧的一项。超过十五秒没采到新值,这条数据就标成过期,不参与 OEE 计算。没有这一项,断线之后界面还显示着上一次的数,看上去一切正常,实际已经停了半小时。这块的补数任务放在搭贝里定时跑,按设备补近一小时的空档。

三、上线踩的坑

3.1 波特率和轮询时序

23 台 Modbus RTU 设备挂在同一条 485 总线上,波特率必须一致。有一台挤压机出厂设的是 9600,其余是 19200,接上去之后整条总线时不时丢包,查了两天才发现是它。

轮询时序也踩过。一开始给每台设备都配 200 毫秒轮询,23 台挤在一起,总线上全是请求,响应超时率百分之十七。改成按设备分组轮询,每组间隔 50 毫秒,超时率降到百分之一以下。

总线空闲时间也要算进去。485 是半双工,转换器收发切换有延迟,我拿示波器量过,从发完一帧到能收下一帧要 8 毫秒左右。轮询间隔如果压到 10 毫秒,请求会叠在一起,表现是偶发校验错。所以 50 毫秒这个数不是拍出来的,是响应时间加切换延迟再加一点余量。

3.2 断线重连要有退避

老机床的串口转换器不稳定,一天要断两三次。一开始的重连逻辑是断了立刻重连,结果转换器还没恢复就又被连上,反复几次之后驱动直接卡死。

后来加了退避:失败一次等 300 毫秒,连续三次失败等 5 秒,十次以上等 30 秒并报警。重连期间该设备的所有点位标成无数据,不保留旧值。这个改动之后,驱动连续跑了四个月没重启过。

3.3 时钟是隐藏的坑

老设备没有时钟。采上来的数据带不了时间,只能落库时补采集时间。补时间听着简单,但有两处要注意:一是采集端和数据库的时钟要同步,二是补的时间要标明来源。

我们定了个规矩,时间戳带来源字段,device 表示设备自带,collector 表示采集端补的,server 表示服务端补的。报表按采集时间统计时,只用 device 和 collector 两种,server 那种延迟大,会把数据挪到错误的班次里。

四、新旧并存

4.1 采集频率分级

87 台设备如果都按一秒采,数据量一天两千多万条,存不下也用不上。按用途分三级:状态和报警两秒一次,工艺参数五秒一次,能耗十五秒一次。

分级之后一天四百万条左右。老机床的私有报文本身两秒一帧,就按两秒采,不额外加快——加快也拿不到新数据,只是把同一帧重复存。

4.2 数据质量要标出来

兼容层的一个作用是把"这台设备的数据可不可信"标出来。质量标记有四档:正常、过期、越界、缺失。越界是指数值超出配置的有效范围,比如油温采到 900 度,明显是传感器坏了。

标出来之后,看板上灰色的就是不可信的点。以前的做法是采到什么都往上报,报表里混着错数,分析的人先花半小时判断哪条是真的。现在至少在界面上不骗人。

4.3 老设备的退役问题

17 台老机床里,有 5 台的状态信号是从继电器上取的,只能判断"通"和"断",判断不了是运行还是待机。这 5 台的 OEE 只能算可用率,算不了性能开动率。

这件事没有技术解。设备科的计划是三年内换掉 3 台,剩下 2 台作为备用机保留。兼容层的好处是换设备的时候不用改上层:新设备接 OPC UA,加一份映射,点位键沿用老的,历史曲线能接上。

常见问题

问:私有报文没有文档,反推出来的映射可靠吗?

答:靠抽样验证。反推完字段,让设备在已知状态下跑一段,把采上来的值跟面板显示逐项比。我们对转速比了 40 组,误差都在正负 2 转以内;报警码只验证了 6 种,其余标成"未验证",界面上不显示含义只显示原始码。

问:一条 485 总线上挂多少台设备合适?

答:看轮询周期和响应时间。我们的经验是 19200 波特率下挂 20 台左右,每台轮询间隔不低于 50 毫秒,一轮下来两秒内能转完。再多就要么加总线,要么放慢轮询,硬堆会丢包。

问:采集频率调高是不是数据更准?

答:不一定。设备本身的刷新周期决定了数据上限,采得比它快只是重复存同一个值。另外频率高会挤占总线,影响其他设备。判断方法是先看设备手册的刷新率,按它的一半到一倍设,再根据报表需要往下调。

问:老设备断线时,界面应该显示什么?

答:显示"无数据"加断线时间,不显示上一次的值。这个决定当初争论过,生产那边希望显示旧值,看起来连续。实际运行下来,显示旧值会让人误判设备在运行,宁可留空。真要画曲线,用虚线断开表示缺数据,不用直线连过去。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、老设备不是不能接,是接法不一样
    • 1.1 四种协议的实际差别
    • 1.2 抓包反推字段
    • 1.3 先定统一点位模型
  • 二、适配层放在哪
    • 2.1 驱动和映射分开
    • 2.2 字节序和缩放是主要错误源
    • 2.3 一台老机床的配置
  • 三、上线踩的坑
    • 3.1 波特率和轮询时序
    • 3.2 断线重连要有退避
    • 3.3 时钟是隐藏的坑
  • 四、新旧并存
    • 4.1 采集频率分级
    • 4.2 数据质量要标出来
    • 4.3 老设备的退役问题
  • 常见问题
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档