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 的任务配置界面中可设置优先级、看门狗时间和任务类型,看门狗超时会触发故障,必须根据最坏执行时间留出余量。

PLCnext 任务调度与视觉协同数据流 相机曝光完成 硬件事件 / 中断 EtherCAT 同步 分布式时钟信号 系统周期时钟 1 ms / 4 ms / 10 ms 事件任务 VisionEvent 优先级 8 · 触发即执行 周期任务 FastTask 优先级 5 · 4 ms 周期任务 SlowTask 优先级 2 · 20 ms FB_VisionResultHandler 解析坐标 · 校验 · 写全局变量 FB_MotionControl 读取视觉结果 · 轨迹规划 PRG_HMI_Logger 状态显示 · 日志记录 共享数据区(VAR_GLOBAL) stVisionResult : 坐标 X/Y/角度 · 时间戳 · 有效标志 写者:VisionEvent 任务 · 读者:FastTask / SlowTask 优先级抢占关系 高优先级任务可打断低优先级 共享数据需原子保护

三、周期任务与事件任务的协同

视觉处理通常耗时较长,不适合放在 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、是否有动态内存分配、是否有阻塞式文件或网络操作。视觉通信建议使用非阻塞方式,或把通信放在独立任务中。

在 PLCnext Engineer 中,任务配置界面可查看每个任务的周期、优先级和看门狗时间。建议把视觉结果处理任务设为事件触发,把运动控制任务设为与总线同步的周期任务,两者通过全局变量或共享内存交换数据,并用序列号防止数据撕裂。

五、一个可参考的任务与变量规划示例

下面给出一个示例性的任务与变量规划,用于说明如何把上述概念落到工程配置中。参数为教学假设,实际项目需根据硬件和节拍调整。

任务名称 类型 周期/触发 优先级 主要 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 侧根据时间戳和有效标志决定使用哪一级结果。这种分级策略在抓取、定位、检测等场景中比单纯提高任务频率更有效,也更符合实时性“按截止时间交付”的本质。