3. 视觉检测结果的数据结构

视觉系统输出的“结果”并不是一句“合格/不合格”,而是一组结构化数据。PLC 要做的判定、分拣、报警、追溯,全部依赖这组数据能否被稳定、无歧义地读取。因此本节的核心任务是:先把视觉侧的结果字段定义清楚,再把它映射成 PLC 能直接寻址的寄存器格式。

一、视觉结果的标准字段定义

一个可工程化的单次检测结果,通常包含以下字段。字段名可以不同,但语义必须固定:

  • 判定结果 Result:整件产品的总判定,取值 OK / NG。建议用整数 0=OK、1=NG,避免字符串比较。
  • 缺陷类型 DefectType:NG 时的分类编码,如 1=划伤、2=脏污、3=缺料、4=尺寸超差、5=错件。OK 时填 0。
  • 缺陷数量 DefectCount:本件检出的缺陷个数,用于判断是否多缺陷。
  • 坐标 X、Y:缺陷在图像坐标系中的位置,单位像素。需明确原点在左上角、X 向右、Y 向下。
  • 尺寸 Width、Height:缺陷外接矩形宽高,单位像素;也可用面积 Area。
  • 置信度 Score:0~100 的整数,表示模型对该缺陷判定的可信程度。
  • 图像 ID ImageID:本次检测图像的唯一编号,用于追溯原图。
  • 时间戳 Timestamp:检测完成时刻,用于与 PLC 节拍对齐。

这里有一个关键约定:坐标与尺寸统一使用像素整数,不直接传毫米。原因是像素是视觉侧的原生量,转毫米需要标定系数,一旦标定变更,历史数据就不可比。若 PLC 需要毫米值,应在 PLC 侧用标定系数换算,或由视觉侧额外输出一份毫米字段,二者不可混用同一寄存器。

二、从视觉结构体到 PLC 寄存器的映射

PLC 不认 JSON、不认字符串,它只认连续的寄存器区。因此映射的本质是:把结构体按固定偏移量铺平成一维数组。以三菱/西门子常见的 32 位寄存器为例,一个结果块可规划为 16 个字(Word):

偏移字段类型说明
D100ResultINT160=OK,1=NG
D101DefectTypeINT16缺陷分类编码
D102DefectCountINT16缺陷个数
D103ScoreINT160~100
D104XINT32占 D104/D105
D106YINT32占 D106/D107
D108WidthINT32占 D108/D109
D110HeightINT32占 D110/D111
D112ImageIDINT32占 D112/D113
D114DataReadyBOOL数据就绪握手位
D115AckBOOLPLC 应答位

注意 INT32 在 PLC 中占两个字,存在高低字顺序问题。三菱、西门子、欧姆龙对 32 位数据的字序约定不同,必须在通信配置中显式指定,否则会出现“X 坐标变成 65536 倍”这类典型错误。工程上建议:视觉侧发送前先确认目标 PLC 的字序,并在联调时用一个已知值(如 X=1000)验证读回是否正确。

三、握手时序:数据何时有效

寄存器写好了不等于 PLC 能读。必须用握手位保证“读到的是完整的一帧”。典型流程是:视觉侧先写数据区,最后置 DataReady=1;PLC 检测到上升沿后读取全部字段,处理完置 Ack=1;视觉侧收到 Ack 后清 DataReady,准备下一帧。这样可避免 PLC 读到半帧数据。

视觉结果字段 → PLC 寄存器映射与握手 视觉侧结果结构体 Result OK / NG DefectType 分类编码 DefectCount 缺陷数 Score 置信度 0~100 X / Y 像素坐标 Width / Height 像素 ImageID 图像编号 Timestamp 时间戳 按偏移铺平 PLC 寄存器区 D100 Result D101 DefectType D102 DefectCount D103 Score D104~105 X (INT32) D106~107 Y (INT32) D108~111 W / H D112~113 ImageID D114 DataReady 握手时序 ① 视觉写数据区 ② 置 DataReady=1 ③ PLC 读上升沿 ④ 读取全部字段 ⑤ 判定并执行动作 ⑥ 置 Ack=1 ⑦ 视觉清 DataReady ⑧ 准备下一帧 半帧保护:先写数据 后置就绪位 约定:坐标原点在图像左上角,X 向右、Y 向下,单位像素;INT32 高低字序须与 PLC 型号一致

四、字段取值与边界处理

映射中最容易出问题的是边界值。工程上建议明确以下规则:

  • OK 件:Result=0,DefectType=0,DefectCount=0,Score 可填 100 或 0,坐标尺寸填 0。PLC 侧只判 Result,不读坐标。
  • NG 件:Result=1,DefectType 必填,Score 低于阈值时是否仍判 NG,需在视觉侧先决定,PLC 不再二次判断。
  • 多缺陷:若一件有多个缺陷,只上传“最严重”或“面积最大”的一个,其余用 DefectCount 计数。PLC 寄存器区不展开数组,避免长度不定。
  • 无结果:相机未触发或通信超时,Result 保持上一次值会误判,应设一个独立状态位或约定 Result=2 表示“无数据”。
不要把 Score 当作 PLC 的判定依据。PLC 只做“读 Result 执行动作”,置信度阈值判断应在视觉侧完成。否则阈值一改,PLC 程序也要改,维护成本翻倍。

五、一个可用的映射配置示例

下面是一段视觉侧发送前的字段打包伪代码,展示如何把结构体按偏移写入寄存器数组。示例参数为教学假设值,非实测:

// 假设本次检测:NG,划伤,1 个缺陷,Score=87
// X=1240, Y=860, W=36, H=12, ImageID=20240513_0007
regs[0]  = 1;          // D100 Result = NG
regs[1]  = 1;          // D101 DefectType = 划伤
regs[2]  = 1;          // D102 DefectCount
regs[3]  = 87;         // D103 Score
regs[4]  = 1240;       // D104~105 X (INT32)
regs[6]  = 860;        // D106~107 Y
regs[8]  = 36;         // D108~109 Width
regs[10] = 12;         // D110~111 Height
regs[12] = 202405130007; // D112~113 ImageID
// 最后一步:置就绪位
regs[14] = 1;          // D114 DataReady = 1

联调时用一个已知值验证:把 X 写成 1000,在 PLC 侧读 D104/D105 组合值,若读回 1000 则字序正确;若读回 65536000,说明高低字颠倒,需在通信配置中交换字序。这个验证只需做一次,但能避免后续所有坐标类缺陷定位错误。

字段定义一旦冻结,就不要在项目中途改偏移。若必须新增字段,追加在 DataReady 之前,并同步更新 PLC 读取长度,避免旧程序读到错位数据。

总结来说,视觉结果的数据结构设计要抓住三点:字段语义固定、寄存器偏移固定、握手时序固定。做到这三点,PLC 侧的程序就退化成“读固定地址、判 0/1、执行动作”,稳定且易维护;视觉侧也能独立升级算法而不影响 PLC 逻辑。