ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

阿塔拉斯开放协议MID能力矩阵:修订号、部分支持与IO映射

阿塔拉斯开放协议MID能力矩阵:修订号、部分支持与IO映射

简介:面向使用阿特拉斯 PowerFocus 6000 进行远程控制或数据订阅开发的工程师,这份开放协议附录文档聚焦平台独立接口在 PF6000 上的具体实现,帮助读者厘清 MID 支持范围、版本兼容、信号接入与紧固程序调用等对接问题。压缩包仅含 1 个 PDF 文件,大小约 980KB,内容集中,适合在集成调试时随手查阅。文档依次说明 MID 支持表、MID Relay 与数字及模拟输入信号、Revision 支持、MID 64/65 旧结果数据特殊处理,并给出 Pset 选择、Pset 批量大小与 Job 序列选择的使用方式,同时提示 Ethernet 连接及跨 Linux、PLC、打印机和 Windows 平台实现时需注意的产品差异。正文还围绕通信启动、参数集上传与订阅等消息列出支持情况,便于对照设备实际返回逐项排查。已有 195 人学习,可作为自动化产线集成、上位机通信搭建、协议开发和现场排错的接口对照资料。

1. 阿塔拉斯开放协议的门槛,不在通信层,在那张三百行的能力矩阵

阿塔拉斯开放协议(Open Protocol)这套东西最容易让人误判的地方,是它看起来只是一份“接口附录”。协议本身确实平台无关,Linux、PLC、打印机、各类 Windows 平台都能实现,拿以太网连上、把报文拼对,工程好像就已经开了头。

真正让人卡住的是第二周:链路是通的,报文也解析得动,程序依然会在某些控制器上拿到一堆零字段,或者发出命令后没反应、也不报错。通信层没有问题,问题在于这套协议从设计上就没有“统一版本”这回事——能力被拆成一条条 MID(消息标识符)加上各自的修订号,分散声明。

决定这套接口能不能用的,往往不是拼报文的水平,而是有没有把那张 MID 能力矩阵当成代码来读:哪些消息根本不存在,哪些只是“部分支持”,哪些继电器编号会随硬件配置整体平移。这份附录值得逐行看的原因,就在这里。

2. MID 与修订号:为什么协议把“能力声明”拆到每一条消息上

先把最容易读错的一列说清楚。MID 表里 Revision 那一栏填的数字,不是“这一个版本”,而是“从 0 一直到该数字(含)的全部修订都支持”。某条 MID 标 8,意思就是 rev 0 到 rev 8 它都认,客户端按自己实现的最高修订去对,只要不超过这个数字就能用。这一条读法决定了整张表的用法,也决定了客户端要不要为每条消息做版本分叉。

2.1 修订号是区间声明,"-" 和 "p" 是两件完全不同的事

区间声明的好处,在做产线集成时特别明显。控制器固件和上位机程序的升级节奏从来不同步:现场可能先升级了控制器,而上位机程序还停留在两年前的版本。如果协议按“整体版本号”协商,这种情况会直接不兼容;改成按消息声明区间,上位机照旧用它实现的 rev 2 去读写,控制器侧新增的 rev 3、rev 4 只对已经升级的客户端生效。分批升级这件事,就变成了客户端的自由。

表里还有两个符号要分开看。-表示这台控制器完全不支持这条 MID,连最低修订都没有;p表示至少有一个修订被部分支持。这两者混为一谈,代价很大。

举个具体的:MID 0025(下载 Pset)在这一型号上是-。如果客户端按通用协议写了一个“把程序参数下发到控制器”的按钮,在这台机器上按下去就是石沉大海——不是报错,是没有响应。再看 MID 0044(断开工具请求)、0046(设置主工具请求)、0047 到 0049(配对处理、配对状态、配对状态确认),四连-。这一整块是工具与控制器之间的配对管理,这台控制器走的是别的配对路径,开放协议这一侧根本没留口子。客户端如果把这套消息当成通用能力来实现,代码在别的控制器上能跑,在这台上就永远走不通。

2.2 为什么一部分 MID 只能给到 p:新旧结果模型对不上

标p的消息里,最有代表性的是 MID 0061(最后拧紧结果数据,修订 8)和 MID 0065(旧拧紧结果上传应答,修订 8)。两者都在拧紧结果的范围内,一个是现行的结果模型,一个是历史遗留的结果模型。

控制器内部只维护一套统一的结果对象,它带着多阶段、同步信息、策略标签这些维度。而 0065 对应的旧消息结构是按“一次拧紧、几个扁平字段”的年代设计的,里面没有地方放这些新维度。所谓部分支持,落到实际表现上就是:字段位还在,但填的是默认值;或者某几类结果根本不会从这条通道出来。

同样的道理,MID 0012、0013(参数集数据上传请求与应答)标p,意味着想把这台控制器的程序通过开放协议读出来做备份,拿到的是裁剪版。MID 0041(工具数据上传应答)标p,意味着工具属性里有一部分读不到。MID 0015(参数集已选通知)也标p,这条更隐蔽——它是订阅链路上最关键的一条通知。

看到p的正确反应不是“跳过”,而是“给这条 MID 准备两套解析路径”:一套处理字段齐全的情况,一套处理字段缺失的情况。常见的实现思路是给每个字段挂一个 valid 标记,而不是拿 0 当“没有值”的哨兵。0 在扭矩、角度这些量上都是合法值,用 0 当哨兵,问题只会推迟到某个特定拧紧策略上才爆发,那时候排起来就是纯玄学。

2.3 MID 编号的分层:功能域加操作类型的二维排布

把编号按段摊开看,会发现它不是随机编号,而是先按功能域切块,块内再用个位区分“请求 / 应答 / 订阅 / 取消订阅”这几种操作类型:

编号段功能域本型号的支持情况
0001–0005通信生命周期与通用应答全部支持
0010–0025参数集(Pset)0012、0013、0015 部分支持
0030–0039Job0033、0035 部分支持
0040–0049工具0044、0046–0049 不支持
0060–0065拧紧结果0061、0065 部分支持
0070–0078报警全部支持
0090–0109多主轴与旧系统结果整段不支持
0200–0225外部 IO0200 部分支持
0250–0254选择器插槽0250–0253 部分支持
9999保活支持,修订 0

这种排布带来的直接好处是,客户端可以按段做能力降级。0090 到 0109 整段标-,多主轴功能就可以整体关掉,不用一条条判断。0200 段里只有 0200 一条标p,外部继电器控制和读取监控输入这条路是通的,只是要按部分支持处理。

至于为什么不用 JSON 或者文本格式——在 PLC 这种场景里,一条报文要在很小的扫描周期内解出来,整数操作码让分发退化成一个查表跳转,长度固定、没有歧义。代价是协议本身不能自我描述:客户端没法从报文里问出“你支持什么”,必须依赖一份事先出版、静态的能力表。

这也是这份附录单独成册的根本原因。主协议是所有实现方共享的公共部分,需要稳定;而“这一型号具体实现到哪一步”是产品级的差异,改一次就可能要重新出版一次。把差异从主协议里拆出去,主协议才能几年不动。

3. 继电器与数字输入:把物理 IO 压成一张会平移的功能编号表

这张表看着最枯燥,实际是整份附录里信息密度最高的部分。三百多条继电器功能编号,编号方式同时编码了两件事:这个功能是什么,以及这个功能值不值得被推送。前者决定了你怎么接线,后者决定了你的客户端是等通知还是轮询。

3.1 表 22 的编号结构:固定功能段与随硬件平移的段

从编号分布能看出明显的分段意图。00 到 31 是基本状态段:OK、NOK、低扭矩、高扭矩、低角度、高角度、周期完成、报警、批次状态、Job 运行状态、控制器就绪、工具就绪、工具启动开关、旋向。这一段是任何一台设备都有的,编号固定。32 到 39 是位选段,Pset 位 0 到 3 加 Job 位 0 到 3。再往后是同步段(67 到 88,涵盖同步总状态和同步主轴 1 到 10)、逻辑继电器段、批次位段、PLUS 相关段。

真正需要留意的是表底下那两行换算。附录在继电器表之后给出了两个基准点:

def relay_bases(relay_count: int, digin_count: int) -> tuple[int, int]: """ 表 22 底部给出的两个基准点换算。 relay_count: 实际装配的继电器数量 digin_count: 实际装配的数字输入数量 返回 (X, Y),用于核对落在平移区间里的功能编号 """ x = 31 + 4 * relay_count y = x + 8 + 4 * digin_count return x, y for n in (4, 8, 16): print(n, relay_bases(n, 4)) # 4 -> (47, 71) # 8 -> (63, 87) # 16 -> (95, 119)

这两行不是装饰。它说明继电器编号不是一张全局常量表,其中有区间是随实际装配的 IO 数量整体平移的相对地址。翻译成工程语言就是:别把供应商样例工程里的继电器号直接烧到另一台配置不同的控制器上。血泪经验是,两台机器功能配置完全一样,一台动作、一台不动,查半天线,最后发现是装配的 IO 模块数量不同,编号基准差了十几个位置。

工程上最稳的做法不是背数字,而是上电之后用 MID 0215 把每个物理通道点一遍,把实际映射录成一份配置项,跟着设备走。这比查表可靠得多。

至于为什么用这种扁平编号而不是树形寻址,道理在 PLC 那一侧:继电器最终要接到输出模块的物理通道上,编号必须能一对一映射到端子位置。任何抽象层都会在接线这一步被拆掉。

3.2 “跟踪事件”这一列决定了你是被推送还是只能轮询

表 22 有一列 Tracking event,取值 Yes 或 No。它回答的是一个非常实际的问题:这个继电器功能的状态变化,会不会主动触发 MID 0215 上报。

分布是有规律的。有跟踪的集中在这些位置:01 OK、02 NOK、05 低扭矩、06 高扭矩、07 低角度、08 高角度、12 Job OK、13 Job NOK、14 Job 运行、18 控制器就绪、19 工具就绪、20 工具启动开关、21/22 旋向、90 使能扫描枪、91 产线控制启动、93 到 102 外部控制 1 到 10、277 有效松开、293 功能按钮、295/296 拧紧禁用与松开禁用、302 PLUS 自动模式。

没有跟踪的则集中在另一类:09 周期完成、10 报警、11 批次 NxOK、15/16 载具完成状态、26 工具运转、32 到 39 的位选、67 到 88 的同步状态、139 到 142 逻辑继电器 1 到 4、144 批次完成、284 批次完成时锁定。

这个划分不是随手定的。有跟踪的,是那种“状态会持续存在、而且客户端没法从别的消息推出来”的信号——控制器就绪、工具就绪、外部控制线、拧紧禁用开关。没有跟踪的,是“脉冲式”的,或者已经被专门的消息承载了:周期完成有 MID 0061 结果消息,报警有 MID 0071,批次状态有 MID 0022,重复推送没有意义。

对客户端的直接影响是订阅策略不能一刀切。订阅 MID 0216 之后,只对 Tracking = Yes 的功能能等到 0217 推送;对 Tracking = No 的功能,要么轮询 0215,要么从结果消息里反推。很多程序在开发环境跑得好好的,上产线之后发现某些状态永远不更新,根子就在这儿。

3.3 表 94 DigIn:n.o./n.c. 的差异与位选编号

数字输入那张表结构上和继电器表对称:00 关、01 复位批次、02 解锁工具、03 工具禁用 n.o.、04 工具禁用 n.c.、05 工具拧紧禁用、06 工具松开禁用、07 远程启动脉冲、08 远程启动持续、09 工具启动松开、10 批次递增、11 绕过 Pset、12 中止 Job、13 Job 关闭、14 参数集切换、15 复位继电器、16 到 19 参数集选择位 0 到 3,再往后是 Job 相关。

03 和 04 这对并存的功能值得单独说。n.o.(常开)和 n.c.(常闭)在功能语义上是同一个“禁用工具”,区别在接线方式和失效方向。常闭接法在断线或失电时,输入默认为“禁用”,是往安全方向倒;常开接法断线时默认变成“允许”,方向是反的。附录把两种都给出来,把选择权交给集成方,这个设计本身就是一种安全边界的表达——协议不替你做安全判断,但把两种接线语义都定义了,让上层能明确表达意图。

07 和 08 这对也是同样的思路:脉冲启动和持续启动是两种完全不同的操作手感,前者按一下就触发一次,后者要一直保持。把两者做成两个独立功能号,而不是靠一个参数去切换,好处是接线上就能区分,不需要额外的配置同步。

位选这部分则要看解码逻辑。参数集选择位 0 到 3 是四个独立的数字输入,被选中的程序号是这四个位的二进制组合:

SEL_BITS = {16: 0, 17: 1, 18: 2, 19: 3} # DigIn 功能号 -> 对应的选择位 def decode_pset(active_funcs: set[int]) -> int | None: """从当前生效的 DigIn 功能集合里还原被选中的参数集号""" value, hit = 0, False for func, bit in SEL_BITS.items(): if func in active_funcs: value |= (1 << bit) hit = True return value if hit else None print(decode_pset({16, 18})) # 0b0101 -> 5

用位而不是用“直接给一个数值”,原因还是回到 PLC 那边:现场能拿到的就是几个输出点,把程序号编码成几根线的组合,接线就能选程序,连以太

本文还有配套的精品资源,点击获取

返回列表