4. AOI功能块的逻辑主体编写

AOI 的定义参数和本地标签只是“外壳”,真正决定它行为的,是逻辑主体(Logic Body)。在 Studio 5000 Logix Designer 中,一个 AOI 的逻辑主体只能选择一种语言:梯形图(RLL)、功能块图(FBD)、结构化文本(ST),或顺序功能图(SFC)。语言一旦选定,AOI 内部就按该语言的执行语义运行,因此选型不是审美问题,而是与算法结构、可读性、可维护性直接相关。本节围绕“如何把核心算法写进逻辑主体”展开,重点讲三种语言的适用边界、条件分支与循环的实现方式,以及 AOI 内部特有的执行约束。

一、先判断算法形态,再选语言

选语言前先问三个问题:算法是位逻辑与联锁为主,还是连续量运算与信号流为主,还是带索引、数组、迭代为主?

  • 梯形图:适合布尔联锁、启停保持、故障锁存、设备顺序动作。它的“能流”模型与电气图一致,现场排查直观。缺点是大量数学运算和数组遍历会变得臃肿。
  • 功能块图:适合模拟量处理链,如滤波、标定、PID、限幅、报警阈值比较。信号从左到右流动,参数在块引脚上直接可见,调参方便。缺点是复杂条件分支表达不如 ST 紧凑。
  • 结构化文本:适合带公式、查表、状态机、循环、数组处理的算法。表达力最强,但可读性依赖命名和注释,现场电工不一定能直接读。

一个实用原则:能用梯形图清楚表达的联锁,不要硬写成 ST;能用 ST 三行写完的数组遍历,不要硬拉成二十个梯级。如果算法内部既有联锁又有运算,可以在 AOI 内用所选语言统一实现,但要把“联锁段”和“运算段”在结构上分开,便于阅读。

二、条件分支:三种语言的写法差异

条件分支是逻辑主体的核心。以“根据模式选择输出”为例,假设 AOI 有输入 Mode(INT,0=手动、1=自动、2=维护)和 ManualCmd、AutoCmd,输出 CmdOut。

梯形图用并联分支和比较指令实现:先 EQU Mode 0 串 ManualCmd,再 EQU Mode 1 串 AutoCmd,两路并联后驱动 CmdOut。分支互斥靠模式值保证,若模式值可能越界,需补一路默认处理。

功能块图用 SEL 或 MUX 块:Mode 接选择端,ManualCmd 与 AutoCmd 接数据端,输出接 CmdOut。多路选择可用级联 SEL,或直接用 MUX 的多输入形式。FBD 的优势是分支关系一眼可见,不需要读梯级。

结构化文本用 CASE 最清晰:

CASE Mode OF
    0: CmdOut := ManualCmd;
    1: CmdOut := AutoCmd;
    2: CmdOut := FALSE;   // 维护模式禁止输出
ELSE
    CmdOut := FALSE;      // 越界保护
END_CASE;

注意 CASE 的 ELSE 分支不是可选项,而是安全兜底。AOI 被多处调用时,输入可能来自不同程序,越界值必须被显式处理,否则输出会保持上一次扫描值,形成隐蔽故障。

三、循环:AOI 内必须谨慎使用

AOI 的逻辑主体在每个扫描周期被调用一次,循环会直接增加该周期的执行时间。因此循环的使用要满足两个条件:迭代次数有明确上界,且单次迭代工作量小。

典型场景是数组遍历,例如对 8 个模拟量通道求最大值和平均值。ST 写法:

Sum := 0.0;
MaxVal := Ch[0];
FOR i := 0 TO 7 DO
    Sum := Sum + Ch[i];
    IF Ch[i] > MaxVal THEN
        MaxVal := Ch[i];
    END_IF;
END_FOR;
Avg := Sum / 8.0;

这里 i 必须是 AOI 本地标签中的 DINT,不能是全局标签,否则多个 AOI 实例会互相干扰。循环上界 8 是常量,扫描时间可预估。若通道数可变,应把上界做成输入参数并加限幅,例如 IF N > 32 THEN N := 32;,防止误设大值拖垮扫描。

梯形图实现循环较笨拙,通常用 FOR 指令或索引递增配合跳转,可读性差;FBD 更不适合循环。因此含循环的算法优先用 ST 写逻辑主体,这是语言选型的重要依据。

AOI 内不要使用 JMP/LBL 做跨段跳转,也不要写无界 WHILE。AOI 被调用在哪个任务、哪个周期,调用者不一定清楚,无界循环会导致任务看门狗超时,且故障现象与 AOI 本身难以关联。

四、执行顺序与“先算后用”

逻辑主体内部按从上到下、从左到右执行。AOI 的输入参数在本次调用开始时已就绪,输出参数在本次调用结束时写回。因此同一次调用内,不要假设输出参数已被更新后再读回;需要中间结果时,用本地标签暂存,最后统一赋给输出。

下面这张图给出一个“模式选择 + 数组统计”AOI 的逻辑主体数据流:输入参数进入后,先做模式分支,再进入循环统计,中间结果存本地标签,最后写回输出参数。

AOI 逻辑主体:模式分支 + 数组统计的数据流 输入参数 Mode : INT ManualCmd : BOOL AutoCmd : BOOL Ch[0..7] : REAL N : DINT 条件分支(CASE) 0 → ManualCmd 1 → AutoCmd 2 → FALSE ELSE → FALSE 越界兜底不可省 循环统计(FOR) Sum += Ch[i] MaxVal = max(...) i : DINT(本地) 上界 N ≤ 32 迭代有界,扫描可控 本地标签(暂存) Sum : REAL MaxVal : REAL i : DINT 输出参数 CmdOut : BOOL Avg : REAL MaxOut : REAL 执行顺序:输入就绪 → 模式分支 → 循环统计 → 本地标签暂存 → 输出写回(同一扫描内不读回输出参数) 语言选型:联锁用 RLL,模拟量链用 FBD,含分支/循环/数组的算法用 ST 安全约束:CASE 必须有 ELSE;FOR 上界必须限幅;禁止无界 WHILE 与跨段 JMP

五、一个可复用的逻辑主体骨架

把上面的要点整理成 ST 逻辑主体的骨架,可直接作为编写模板:

// 1) 输入合法性检查
IF N < 0 THEN N := 0; END_IF;
IF N > 32 THEN N := 32; END_IF;

// 2) 条件分支:模式选择
CASE Mode OF
    0: CmdOut := ManualCmd;
    1: CmdOut := AutoCmd;
    2: CmdOut := FALSE;
ELSE
    CmdOut := FALSE;
END_CASE;

// 3) 循环统计:有界迭代
Sum := 0.0;
MaxVal := Ch[0];
FOR i := 0 TO N-1 DO
    Sum := Sum + Ch[i];
    IF Ch[i] > MaxVal THEN MaxVal := Ch[i]; END_IF;
END_FOR;

// 4) 输出写回
IF N > 0 THEN Avg := Sum / INT_TO_REAL(N); ELSE Avg := 0.0; END_IF;
MaxOut := MaxVal;

这段骨架体现了三个工程习惯:先限幅再运算、分支必有兜底、除零前先判断。AOI 一旦被多处调用,任何未处理的边界值都会在某个调用点暴露,而排查时往往先怀疑调用方,浪费大量时间。

六、验证逻辑主体的最小方法

AOI 不能像普通程序那样单独下载运行,验证要靠调用它的测试程序。建议建一个专用测试例程,只调用该 AOI 一次,用强制表或测试标签给定输入,观察输出。重点验证四类用例:

  • 正常分支:Mode=0/1/2 时 CmdOut 是否符合预期。
  • 越界分支:Mode=5 时 CmdOut 是否为 FALSE,而不是保持旧值。
  • 边界循环:N=0、N=1、N=32 时 Avg 与 MaxOut 是否正确,N=0 时是否避免除零。
  • 扫描影响:把 N 临时设为 1000,观察任务扫描时间是否明显上升,确认限幅生效。

观察手段上,梯形图可直接看能流和标签值;FBD 可在线看各块引脚数值;ST 可在例程中把中间变量映射到测试标签,用趋势或监视表查看。判断依据不是“程序能下载”,而是每个分支和边界都有确定的、可解释的输出。

逻辑主体写完后,先自问三句:所有 CASE 都有 ELSE 吗?所有循环上界都限幅了吗?所有除法都防了零吗?这三问能挡掉 AOI 现场故障的大多数来源。