3. PLCnext运行时与IEC 61131-3编程基础
PLCnext Control 的实时运行时并不是一个“黑盒”,它把 IEC 61131-3 的软件模型映射到 Linux 之上的实时执行环境中。理解这套映射关系,是后续把机器视觉结果安全、准时地送进 PLC 逻辑的前提。本节围绕任务类型、程序组织单元(POU)、变量作用域、周期任务与事件任务,以及协同控制中的实时性概念展开。
一、IEC 61131-3 软件模型在 PLCnext 上的落地
IEC 61131-3 定义了配置(Configuration)、资源(Resource)、任务(Task)、程序(Program)四级结构。在 PLCnext Engineer 中,一个项目通常对应一个配置,一个控制器对应一个资源,资源下挂若干任务,任务再调用程序组织单元。POU 分为三类:程序(PROGRAM)、功能块(FUNCTION_BLOCK,FB)和函数(FUNCTION)。程序是任务的入口,拥有自己的实例数据;功能块有内部状态,必须实例化后调用;函数无内部状态,同一输入必得同一输出,适合做纯计算,例如视觉坐标的仿射变换。
变量作用域决定了数据在哪里可见。VAR 是 POU 内部局部变量,每次调用重新初始化(FB 的 VAR 在实例中保持);VAR_INPUT / VAR_OUTPUT 是接口变量;VAR_IN_OUT 传递引用,适合大数组避免拷贝;VAR_GLOBAL 在资源内全局可见,常用于跨任务共享的视觉结果;VAR_GLOBAL RETAIN 掉电保持,适合标定参数。一个常见错误是把视觉结果直接写进全局变量而不加保护,导致任务间读写撕裂。
二、任务类型:周期任务与事件任务
PLCnext 支持周期任务和事件任务。周期任务按固定间隔触发,例如 1 ms、4 ms、10 ms;事件任务由外部事件触发,例如硬件中断、EtherCAT 同步信号、或用户自定义事件。周期任务保证确定性,事件任务保证响应性。在视觉协同中,相机曝光完成信号可作为事件源,触发一个事件任务去读取结果,避免主任务空转轮询。
任务优先级决定抢占关系。高优先级任务可打断低优先级任务,因此视觉通信这类对时延敏感的任务应放在较高优先级,而人机界面刷新、日志记录放在低优先级。PLCnext 的任务配置界面中可设置优先级、看门狗时间和任务类型,看门狗超时会触发故障,必须根据最坏执行时间留出余量。
三、周期任务与事件任务的协同
视觉处理通常耗时较长,不适合放在 1 ms 周期任务里。合理的做法是:相机通过 GigE Vision 或 USB3 把图像交给视觉程序,视觉程序在独立进程中完成检测,把结果写入共享内存或通过 OPC UA / 共享变量交给 PLC。PLC 侧用一个事件任务监听“结果就绪”标志,一旦置位就读取结果并触发运动控制。这样视觉的耗时不会拖累 PLC 的周期扫描。
如果视觉结果需要与运动轴严格同步,则应把结果读取放在与 EtherCAT 同步的周期任务中,并确保该任务的周期与总线周期一致。此时视觉结果必须在上一个总线周期结束前就绪,否则会出现“用旧数据控制新周期”的问题。工程上常用双缓冲或序列号机制:视觉侧写完缓冲区后递增序号,PLC 侧读取时比较序号,若序号未变则跳过本次控制,避免重复使用同一帧结果。
四、实时性概念与协同控制中的判断依据
实时性不等于“快”,而是“在截止时间前完成”。对协同控制而言,关键指标是端到端时延:从相机曝光开始,到 PLC 输出新的控制量为止。这个时延由曝光时间、图像传输、视觉算法、结果通信、PLC 任务调度、输出刷新共同构成。假设某示例系统中曝光 2 ms、传输 3 ms、算法 8 ms、通信 1 ms、任务等待 2 ms、输出 1 ms,则端到端约 17 ms。若产线节拍要求 20 ms 内完成,则余量只有 3 ms,任何一项抖动都可能超时。
判断实时性是否达标,不能只看平均时延,要看最坏情况执行时间(WCET)和抖动。PLCnext 的任务看门狗、任务负载监控和 Trace 功能可以记录任务执行时间。若发现某任务偶尔超时,应优先检查是否有低优先级任务长时间占用 CPU、是否有动态内存分配、是否有阻塞式文件或网络操作。视觉通信建议使用非阻塞方式,或把通信放在独立任务中。
五、一个可参考的任务与变量规划示例
下面给出一个示例性的任务与变量规划,用于说明如何把上述概念落到工程配置中。参数为教学假设,实际项目需根据硬件和节拍调整。
| 任务名称 | 类型 | 周期/触发 | 优先级 | 主要 POU | 职责 |
|---|---|---|---|---|---|
| VisionEvent | 事件任务 | 相机曝光完成 | 8 | FB_VisionResultHandler | 读取视觉结果,校验后写全局变量 |
| FastTask | 周期任务 | 4 ms | 5 | FB_MotionControl | 读取视觉结果,计算并输出控制量 |
| SlowTask | 周期任务 | 20 ms | 2 | PRG_HMI_Logger | 状态显示、日志、非实时通信 |
VAR_GLOBAL
stVisionResult : ST_VisionResult; // X, Y, Angle, Timestamp, Valid, SeqNo
bVisionNew : BOOL; // 事件任务置位,FastTask 复位
END_VAR
// FB_VisionResultHandler 中(事件任务调用)
IF stRawResult.Valid THEN
stVisionResult := stRawResult;
stVisionResult.SeqNo := stVisionResult.SeqNo + 1;
bVisionNew := TRUE;
END_IF
// FB_MotionControl 中(FastTask 调用)
IF bVisionNew THEN
IF stVisionResult.SeqNo <> nLastSeq THEN
nLastSeq := stVisionResult.SeqNo;
// 使用 stVisionResult 计算目标位置
bVisionNew := FALSE;
END_IF
END_IF
这段示例体现了三个要点:事件任务负责“接住”视觉结果,周期任务负责“消费”结果,序列号负责判断结果是否为新。若 FastTask 发现序列号未变,说明视觉尚未产出新结果,本次控制可沿用上一次目标或保持等待,避免用同一帧结果重复触发运动。
变量作用域方面,stVisionResult 和 bVisionNew 放在 VAR_GLOBAL,因为跨任务访问;nLastSeq 放在 FB_MotionControl 的实例数据中,因为只属于该功能块。若把 nLastSeq 误写成全局变量,多个调用实例会互相干扰。若把 stVisionResult 放在某个程序的 VAR 中,其他任务无法访问。这些细节在编译时不一定报错,但会在运行时表现为数据不更新或控制异常。
六、实时性检查的实践要点
在协同控制中,建议按以下顺序检查实时性:第一,确认视觉结果写入和读取使用同一数据定义,避免结构体对齐差异;第二,确认事件任务不会因为视觉通信阻塞而长时间占用 CPU;第三,确认周期任务的 WCET 小于周期时间的 50%~70%,留出抖动余量;第四,确认看门狗时间大于 WCET 且小于工艺允许的最大故障响应时间;第五,用 Trace 或任务负载监控观察长时间运行下的最坏情况,而不是只看启动阶段。
当视觉算法耗时波动较大时,可把视觉结果分为“快速粗略结果”和“精确结果”两级:粗略结果在短周期内可用,精确结果稍后到达并修正。PLC 侧根据时间戳和有效标志决定使用哪一级结果。这种分级策略在抓取、定位、检测等场景中比单纯提高任务频率更有效,也更符合实时性“按截止时间交付”的本质。