4. IEC 61131-3数据建模

在PLCnext的数据采集项目中,真正决定后续云端对接效率的,往往不是通信协议选得多先进,而是变量建模是否清晰。IEC 61131-3不仅规定了编程语言,也提供了变量、数据类型、结构体(STRUCT)和数组(ARRAY)等建模手段。把这些手段用在产线设备上,就能把“现场一堆散点”整理成“可采集、可理解、可维护”的数据字典。

一、从设备对象出发,而不是从地址出发

很多初学者习惯先看PLC地址表:%I0.0是启动按钮,%Q0.1是电机输出,%IW64是温度值。这种按地址罗列的方式在采集端会带来两个问题:一是地址含义靠注释维护,注释一丢就不可读;二是同一台设备的状态量、模拟量、报警量分散在不同区域,云端无法按设备聚合。

更合理的做法是先识别产线中的设备对象。以一条典型装配线为例,可抽象出以下对象:输送电机、气缸、光电传感器、RFID读写器、称重模块、安全门。每个对象都有属性,属性就是需要采集的变量。例如输送电机有:运行状态、故障状态、当前速度、累计运行时间、启停命令。把这些属性用IEC 61131-3的数据类型表达出来,就形成了设备变量。

二、用基本数据类型锁定语义

IEC 61131-3的基本数据类型是建模的最小单元。选择类型时,不只看位数,还要看语义:

  • BOOL:用于开关量,如电机运行、气缸到位、安全门关闭。
  • INT / DINT:用于计数值、状态码、配方号。状态码建议用INT,便于后续映射枚举。
  • REAL:用于速度、温度、压力、重量等模拟量。注意REAL是32位浮点,采集到云端后通常直接映射为float。
  • TIME:用于累计运行时间、节拍时间。PLCnext中TIME通常为64位,单位毫秒或纳秒,采集时需明确单位。
  • STRING:用于设备编号、批次号、RFID标签内容。STRING长度要显式限定,避免不定长带来的内存与通信问题。

一个常见错误是把所有模拟量都定义成REAL,却忽略了量程和工程单位。例如称重模块原始值为INT,量程0~20000对应0~5000g,那么建模时应同时保留原始值变量和工程值变量,并在数据字典中记录换算关系。这样云端既能拿到原始数据做诊断,也能直接使用工程值做展示。

三、结构体:把一台设备的属性打包

结构体(STRUCT)是IEC 61131-3中组织相关变量的核心工具。以输送电机为例,可以定义:

TYPE ST_Motor :
STRUCT
    bRun        : BOOL;      // 运行状态
    bFault      : BOOL;      // 故障状态
    bEnable     : BOOL;      // 使能状态
    rSpeed      : REAL;      // 当前速度,单位mm/s
    nStatus     : INT;       // 状态码:0停止 1运行 2故障
    tRunTime    : TIME;      // 累计运行时间
    sDeviceID   : STRING[16];// 设备编号
END_STRUCT
END_TYPE

定义好结构体后,在全局变量表中声明:stMotor1 : ST_Motor;。这样一台电机的所有采集点就聚合在一个命名空间下。云端采集时,只需按stMotor1.前缀批量读取,既减少通信请求数量,也避免变量名冲突。

结构体还可以嵌套。例如把整条产线定义为ST_Line,内部包含多个ST_Motor、ST_Cylinder和ST_Sensor。这种层级关系与云端设备模型天然对应:产线→设备→属性。

四、数组:处理同类设备的批量采集

当产线上有8个相同的气缸时,逐个定义stCylinder1到stCylinder8会非常冗长。此时用数组更合适:

TYPE ST_Cylinder :
STRUCT
    bExtend     : BOOL;   // 伸出到位
    bRetract    : BOOL;   // 缩回到位
    bAlarm      : BOOL;   // 报警
    nActionCount: DINT;   // 动作次数
END_STRUCT
END_TYPE

VAR_GLOBAL
    aCylinder : ARRAY[1..8] OF ST_Cylinder;
END_VAR

采集端可以用循环遍历aCylinder[i],把8个气缸的数据一次性打包上传。数组下标建议从1开始,符合IEC 61131-3习惯,也便于与现场编号对应。如果设备数量可能扩展,可以在数据字典中预留数组上限,例如ARRAY[1..16],实际使用前8个。

五、建立可采集的数据字典

变量定义完成后,还需要一份数据字典,把“PLC内部变量”翻译成“云端可理解的数据点”。数据字典至少应包含:变量路径、数据类型、工程单位、量程、采集周期、读写权限、业务含义。下面是一个示例片段:

变量路径类型单位量程周期权限含义
stMotor1.bRunBOOL—0/1100ms只读1号电机运行状态
stMotor1.rSpeedREALmm/s0~1500100ms只读1号电机当前速度
stMotor1.nStatusINT—0/1/2100ms只读0停止 1运行 2故障
aCylinder[1].bExtendBOOL—0/1200ms只读1号气缸伸出到位
aCylinder[1].nActionCountDINT次0~9999991s只读1号气缸动作次数
stScale.rWeightREALg0~500050ms只读称重工程值

数据字典不是一次性文档,而是采集配置的来源。OPC UA服务器、MQTT主题、REST接口都可以从这份字典自动生成。例如MQTT主题可设计为line1/motor1/speed,与stMotor1.rSpeed一一对应。

产线设备数据建模:从物理对象到可采集数据字典 物理设备层 输送电机 ×1 运行/故障/速度/时间 气缸 ×8 伸出/缩回/报警/次数 光电传感器 ×4 检测/遮挡/信号强度 称重模块 ×1 原始值/工程值/稳定 RFID读写器 ×1 标签号/读取状态 安全门 ×1 抽象 IEC 61131-3 建模层 基本数据类型 BOOL · INT · DINT · REAL · TIME · STRING 语义明确,量程与单位在字典中记录 结构体 STRUCT ST_Motor:bRun / bFault / rSpeed / nStatus / tRunTime ST_Cylinder:bExtend / bRetract / bAlarm / nActionCount ST_Scale:rRaw / rWeight / bStable 嵌套:ST_Line 包含多个设备结构体 数组 ARRAY aCylinder : ARRAY[1..8] OF ST_Cylinder 循环遍历,批量打包上传 全局变量声明 stMotor1 : ST_Motor; aCylinder : ARRAY[1..8] OF ST_Cylinder; 映射 可采集数据字典 变量路径 stMotor1.rSpeed aCylinder[1].bExtend 类型 / 单位 / 量程 REAL / mm/s / 0~1500 BOOL / — / 0/1 采集周期 / 权限 100ms / 只读 1s / 只读 业务含义 1号电机当前速度 1号气缸伸出到位 MQTT主题 / OPC UA节点 line1/motor1/speed 建模原则:先对象后地址 · 类型语义明确 · 结构体聚合设备 · 数组批量管理 · 字典驱动采集

六、建模时的几个实用判断

第一,状态量用BOOL还是INT?如果只有“是/否”,用BOOL;如果有多个状态(停止、运行、故障、维护),用INT状态码,并在数据字典中列出枚举映射。第二,模拟量是否保留原始值?建议保留。原始值可用于诊断传感器断线或量程溢出,工程值用于展示。第三,时间量用什么单位?PLCnext中TIME类型精度高,但云端通常只需要秒级。可以在采集端统一转换为DINT秒数,减少数据量。

第四,字符串长度要克制。RFID标签号如果固定为8字节,就定义STRING[8],不要用STRING[255]。第五,数组下标与设备编号的对应关系要写进字典。例如aCylinder[1]对应现场1号气缸,避免调试时靠猜。

数据字典建议用CSV或YAML维护,字段包括:变量路径、数据类型、单位、量程下限、量程上限、采集周期、读写权限、业务含义、枚举映射。这份文件可以直接作为OPC UA节点配置和MQTT主题生成的输入,减少手工重复。