跳到正文
Learn-LAD
PLC AI 实战/用 AI 审一套 PLC 程序:投运前找出会停机的缺陷

用 AI 审一套 PLC 程序:投运前找出会停机的缺陷

只读审查一套 18 网络的 LAD+SCL 程序:按 7 类清单找缺陷,分 P0/P1/P2,每条带块/网络证据和复现方法;工程零改动。

进阶 第 5 课 35 分钟 TiaLink

学完你能:能只读审查一套 LAD+SCL 程序,产出带证据、分严重级别、可复现的《程序审查报告》,并分清编译能查出、仿真能验证、只能人工确认的三类问题。

概述

前面几课把「敢改」拆开了:读懂老工程(L1)→ 知道改动会波及谁(L2)→ 写块到编译 0/0(L3)→ 让程序在虚拟 PLC 里跑起来(L4)。这一课补上投运前最后一道:这套程序哪里会出事,先修哪条。

程序审查(code review)不是让 AI 说「代码写得怎么样」,而是让它在只读前提下,按一张固定清单找出有失败场景的缺陷,并产出能复核的《程序审查报告》。风格偏好、命名习惯、个人写法,不进入「发现」;没有失败场景的候选,只能进「误报/已排除」或「待确认」。

本课用示例库里的 分拣箱(Factory IO) 当靶子:Main 的 18 个网络 + 1 个 SCL 通信 FC(1 个网络),31 个标签,5 个系统实例 DB。这套开源示例保留了原工程的真实缺陷,正好用来练审查。本次实测找到:

  • P1:右分拣不按箱型工作,左箱型时左右链条可能同时动作;
  • P1:Feed Conveyor 被 3 个网络同时驱动,没箱子也在转,停止不保持;
  • P2:Emitter 只有一个扫描周期(10ms)的脉冲,执行器可能来不及动作;
  • P2:编译警告「使用了硬件中不存在的 I/O」——不是逻辑错误,但不能忽略;
  • P3/无法确认:程序内没有急停/安全逻辑,需要电气图纸和安全评审;
  • 误报 1 条:导出文本看起来像 SCL 编译失败,实际 TIA 编译 0 错误。

最后一条尤其重要:AI 审查最大的风险不是漏看,而是把「看起来像问题」当成「已确认的缺陷」。 本课会专门做一遍反证,把误报挡在报告外面。

先别看示例页的「常见问题」。本课是盲审:先按接线审一遍,再对照示例页。审完你会发现,示例页原来的右分支描述也不准确——这正是审查要解决的问题(本课审完后已修正示例页,下面保留原来的错误说法作对照)。

口径:AI 是辅助审查,结论必须人工复核;本课不是安全认证,急停/安全功能必须由有资质的人确认。审查阶段工程零改动。

你将学会

  • 写一份可执行的审查任务书:范围、7 类清单、严重级别、证据要求、输出格式、只读约束;
  • 让 agent 建证据包:块/网络清单、调用关系、输出 → 写点 表、逐块编译消息、硬件地址;
  • 抓跨网络缺陷:多驱动、置位/复位配对、扫描顺序、单扫描脉冲、边沿存储、地址与硬件不匹配;
  • 把发现分成 P0/P1/P2,并标注「确认 / 推断 / 无法确认」;
  • 做反证:对每条发现追问「有没有别的网络、外部写入或工艺要求让它不成立」,过滤 AI 误报;
  • 产出《程序审查报告》:每条带块/网络证据、失败场景、影响、修复建议、验证方法;
  • 分清编译能查出、仿真能验证、只能人工确认三类问题,不用其中一种替代另一种。

前置条件

  • Windows 机器,已安装 TIA Portal V19(TiaLink 当前基于 V19 与 Openness 构建);
  • TiaLink:在 TiaLink 页面 下载并启动,打开一个空白/临时工程;
  • 一个支持 Streamable HTTP MCP 的客户端(Claude Code、Cursor、VS Code 等),MCP 端点为 http://localhost:8080/mcp;
  • 练习对象:把示例库的 分拣箱(Factory IO) 导入临时工程。不要在生产工程上做:导入会覆盖同名 Main,并新增系统实例 DB;
  • 记录导入前的 dirty 状态当基线;允许逐块编译,但不保存;
  • 可选:S7-PLCSIM Advanced 复现行为类发现;不装也能做静态审查(本课的行为证据来自离线逐扫描推演);
  • 一条安全边界:本课不覆盖硬件/HMI/总线/安全程序,安全相关结论一律标「需人工确认」。

步骤

准备:配好 TiaLink 与 MCP

在博途那台机器上启动 TiaLink、打开空白工程。页首状态条会自动检测;然后在客户端里加一个 Streamable HTTP MCP 服务:

先在本页顶部点「设置」填一次地址(存在本机,示例库页面也用同一个地址),下面的 URL 会跟着更新,点「复制」贴进客户端配置:

MCP
{
  "mcpServers": {
    "tialink": {
      "type": "http",
      "url": "http://localhost:8080/mcp",
      "headers": { "Authorization": "Bearer <你的 TiaLink API Token>" }
    }
  }
}

看到什么:客户端列出 TiaLink 的工具(名字以 tialink_ 开头,覆盖健康检查、读工程、导出、编译、保存等)。工具数量随版本变化,不必对数字。

第一步:准备靶子与基线

在一个空工程里新建 CPU(本课实测用 CPU 1215C DC/DC/DC,S7-1200),按示例的导入顺序导入。没有 1215C 也可以用你现有的 S7-1200/1500 沙盒;本课的逻辑结论与 CPU 型号无关,硬件 I/O 警告会随配置不同。

  1. 点表 Default tag table(31 个标签);
  2. SCL FC MHJ-PLC-Lab-Function-S71200;
  3. 5 个系统实例 DB(2 个计数器 + 3 个定时器);
  4. Main(OB1,18 个网络)。

导入方式:在示例页点「导入到 TIA」(推荐),或用 TiaLink 的 tialink_import 按上面的顺序逐个导入。推荐用示例页按钮:agent 不需要自己找 XML,也不会去猜文件路径。

导入完成后,把下面这段发给 agent,让它做基线盘点,先不要开始审查:

只做基线盘点,不要审查、不要修改任何逻辑、不要保存工程;可以逐块编译以获取编译结果。
对象:当前工程里的 sorting-boxes 示例(Main + MHJ-PLC-Lab-Function-S71200 + 5 个系统实例 DB + Default tag table)。

请报告:
1. 工程名、设备名、CPU 型号/订货号、软件名;
2. 块清单(块名/类型/编号/语言)、Main 的网络数、点表标签数、系统实例 DB 数;
3. 逐块编译结果:每个对象的错误数/警告数 + 消息原文;
4. 导入前/后的 dirty 状态(如果知道;不知道就写“无法确认”);
5. 与预期不符的地方:缺块、同名覆盖、导入失败、编译错误、硬件 I/O 警告。

不要猜;没有的信息标“无法确认”。不要保存工程。

用自己的工程时:把对象和预期规模换掉,基线项(块/点表/编译/dirty)不变。

看到什么:agent 报告的规模应该对得上:2 个块 + 5 个系统 DB + 1 张点表;Main 18 个网络;逐块编译 0 错误 / 1 警告。基线表如下:

对象 错误 警告 说明
MHJ-PLC-Lab-Function-S71200(FC9000) 0 1 硬件 I/O 警告
Main(OB1) 0 1 同一条硬件 I/O 警告
整个 PLC 软件 0 1 5 个系统 DB 均编译成功

注意:编译警告「Inputs or outputs are used that do not exist in the configured hardware」先不要修,也不要忽略——它是审查的候选之一。本课用的 1215C 集成 I/O 不包含示例里的 Q1.2、Q1.3、QW30、QW34,这条警告是真实的硬件配置差异。

同时记下:审查前 dirty 是什么。本课实测从 dirty=false 开始,导入/编译后变 dirty=true,但没有保存。这份基线就是后面审查报告的「范围与基线」段;如果这里已经发现缺块/导入失败,先解决,不要进入审查。

第二步:写审查任务书(审查阶段只需要这一段)

反例:只发一句「帮我 review 一下这段 PLC 程序」。agent 大概率会给你一堆风格建议:命名、注释、网络拆分、变量表规范——听起来都对,但没有一条能证明「会停机」。

正例:把「审什么、怎么算问题、怎么给证据、怎么排除误报」一次说清。下面这段可以直接复制,靶子换成你的工程:

只读审查,不要修改任何对象,也不要保存工程。对象是当前工程的全部 PLC 软件(块、点表、DB)。

目标:找出会导致误动作、停机、无法投运、数据损坏或难以维护的缺陷;不要给纯风格建议。

按 7 类逐项审查:
1) 结构与调用:空网络、未调用块、重复驱动、调用关系、实例 DB;
2) 状态与保持:置位/复位配对、自锁、首扫描、保持性、断电恢复;
3) 时序与扫描:扫描顺序、双线圈、边沿存储、定时器类型(TON/TOF/TP)、单扫描脉冲;
4) 互锁与安全:启停/急停/联锁、冲突输出、故障失效方向;
5) 数据与地址:类型/范围/数组边界、INT/REAL、计数器溢出、I/O 地址与硬件通道;
6) 可维护性:巨型网络、空接口、全局变量、魔法数、命名与注释;
7) 可测试性:手动/仿真模式、场景可注入、诊断与报警。

对每个候选问题输出:
- 证据:块名 + 网络号 + 标签/指令;跨网络问题列出所有写点;
- 失败场景:什么输入/时序/硬件状态下出错,后果是什么;
- 严重级别:P0 停机/安全/数据损坏;P1 功能错误/难恢复;P2 维护/可读性;P3 待确认;
- 置信度:确认(程序内可证)/ 推断(需工艺或硬件确认)/ 无法确认;
- 修复建议:最小改动 + 风险;
- 验证方法:读图/逐块编译/PLCSIM/云仿真/人工;
- 反证:有没有其他网络、外部写入或工艺约束使它不成立。

最后输出《程序审查报告》,按 P0→P1→P2 排序,并单列「误报/已排除」和「无法确认」。
不要编造行号;没有失败场景的候选不要写进报告。

这段任务书有四个关键点:

  1. 7 类清单:防止 agent 只挑自己熟悉的看;
  2. 证据 + 失败场景:把「我觉得」变成「什么条件下会错」;
  3. 反证:强制 agent 自己找反例,降低误报;
  4. 只读 + 输出格式:审查不是改代码,报告要能交接。

审查的 7 个面与一条证据链
先定审查面,再定证据链:没有失败场景的候选不进报告

看到什么:agent 不会立刻给你一份“感觉”,而是先回一个审查计划/范围,例如(示意,实际措辞会变):

收到。只读审查,不修改、不保存。
范围:Main (OB1, LAD, 18 networks) + MHJ-PLC-Lab-Function-S71200 (FC9000, SCL, 1 network)
基线:编译 0 错误 / 1 警告;dirty=true
计划:1) 导出块/点表 2) 建 输出→写点 表 3) 按 7 类扫描 4) 反证/分级 5) 出报告
先扫全;候选会按 P0/P1/P2 + 证据列出,没有失败场景的不进报告。

如果它只回一句“好的”然后开始讲命名/注释,说明任务书没生效:把 7 类清单、证据要求和“没有失败场景不进报告”再发一遍。真正的发现和报告在第四步到第七步;这一步只要确认它按清单扫全、按证据说话。

第三步:agent 建证据包

这一步不需要新的提示词。 第二步的任务书已经包含「证据」「跨网络列出所有写点」「逐块编译」的要求;agent 会自己继续。正常使用不需要你一步步指挥。它会做四件事:

  1. 盘点:块清单、网络数、语言、点表、系统实例 DB;
  2. 编译:先逐块编译,再整体编译;把错误/警告按对象归位;
  3. 建 输出 → 写点 表:对每个输出/标志,列出所有写它的网络和指令;
  4. 对硬件:把 I/Q 地址和 CPU/模块的通道对照,标出「程序用了但硬件没有」的点。

看到什么:agent 会先摆出规模(2 个块、18 个网络、31 个标签、5 个系统 DB、编译 0 错误 / 1 警告),再给出 输出 → 写点 表。这张表是审查的核心工具;本课实测得到的关键行:

输出 / 标签 写它的网络 指令 备注
Feed Conveyor N4 / N6 / N7 普通线圈 / 置位 / 复位 三个驱动,扫描顺序敏感
Chain_Transfer_Right N11 / N12 / N13 普通线圈 / 置位 / 复位 N11 与 N12 条件互斥;N11 在 Tag_5=0 时恒真
Tag_5 N13 复位 程序内没有置位
Tag_9 N16 普通线圈 由 TON 自复位

表里只要出现同一输出多个写点,或某个标志只有复位,就进入候选;单看一个网络是看不出来的。

如果 agent 停下来:只回一句「继续,先把 输出 → 写点 表建出来,再按 7 类扫描」,不要重新发整段任务书。

这里有一个容易踩的坑:导出的 SCL 文本里可能出现 511Ret_Val、空 GOTO ; 这种拼接。先不要把它写成 P0——它是文本反编译的伪影,不是 TIA 编译器的结论。下一步会专门处理。

第四步:审跨网络逻辑——两条真实发现

这一步不需要新的提示词。 第二步的任务书已经要求「跨网络列出所有写点」和「失败场景」;agent 应该从证据包直接进入候选分析。如果它停下来,只回一句「继续,按 7 类给候选,先不要写报告」。

你可能需要回答的:agent 可能会问 Load 是保持信号还是短脉冲、右分拣应该由哪个箱型触发。知道就回答;不知道就说「标推断/待确认」,不要让它猜。

下面两条发现先用离线逐扫描推演确认;你在自己的工程里可以用 PLCSIM 按同一张场景表复现(见 L4)。

发现 A:右分拣不按箱型,左右可能同时动作

先看右分支的接线:

  • N11:NOT Tag_5 AND Load → Chain_Transfer_Right(普通线圈);
  • N12:Tag_5 AND Load → Chain_Transfer_Right(置位),同时 Tag_5 AND Load → TOF 8s → Right_Conveyor;
  • N13:FALLING(Right Entry) → 复位 Chain_Transfer_Right 和 Tag_5。

这是 Main 的实际梯形图(N11/N12/N13 三个网络写同一个 Chain_Transfer_Right):

Main 的实际梯形图:N11/N12/N13 同一输出三个驱动
N11 普通线圈、N12 置位+TOF、N13 复位;三个网络写同一个 Chain_Transfer_Right

把三个写点放在一起看,才能发现 N11 的 NOT Tag_5 恒为 1;单看 N12 会以为“Tag_5 置位后才动作”。

Tag_5 在整个程序里只有复位、没有置位(除非 HMI/通信从外部写入,本课未发现)。所以:

  • NOT Tag_5 恒为 1;
  • 只要 Load=1,N11 就把右链条打开,不区分箱型;
  • 在程序内没有外部写入的前提下,N12 的 Tag_5 AND Load 不会成立,Right_Conveyor 也不会转;
  • 如果此时 Tag_2=1(左箱型),N9 也会置位左链条——左右链条同时动作。

右分拣与左分拣的接线:Tag_5 没有置位,N11 每次 Load 都开右链条
N11 用 NOT Tag_5 AND Load 驱动右链条;Tag_2=1 时左右同时动作

逐扫描推演(Load=1):

Tag_2 Tag_5 左链条 右链条 右输送机
0 0 0 1 0
1 0 1 1 0

级别:P1(功能错误,可能造成机构干涉)。 置信度:确认(静态接线 + 离线逐扫描仿真)。 修复建议:补 Tag_5 的置位条件(另一种箱型),并让 N11/N12 统一用一种驱动方式;或者删掉 N11,只保留按箱型的 N12。 验证:场景表断言「左箱型只允许左链条」「右箱型只允许右链条」。

发现 B:Feed Conveyor 多驱动,没箱子也进料

再看进料输送机:

  • N4:Tag_1 → Feed Conveyor(普通线圈,每个扫描都写);
  • N6:Tag_1 AND Height_sensor_1 AND NOT Load → Feed Conveyor(置位);
  • N7:Load OR Reset_Button_1 → Feed Conveyor(复位)。

这是 Main 的实际梯形图(N4/N6/N7 三个网络写同一个 Feed Conveyor):

Main 的实际梯形图:N4/N6/N7 同一输出三个驱动
N4 普通线圈、N6 置位、N7 复位;N4 每扫描写 1,覆盖 N6/N7

注意 N4 同时驱动 Start Light、Remover 1、Remover 2;Feed Conveyor 只是其中一个输出。

OB1 每个扫描按 N4 → N6 → N7 执行。于是:

  • Tag_1=1、Height_sensor_1=0、Load=0:N4 写 1,N6 不成立,N7 不动作 → 1。没有箱子时进料输送机也在转;N6 的 Height_sensor_1 条件被 N4 完全覆盖。
  • Tag_1=1、Height_sensor_1=1、Load=0:N4 写 1,N6 也写 1,N7 不动 → 1;
  • Load=1:N4 先写 1,N7 再复位 0 → 本扫描结束为 0;
  • Load 变回 0:N4 又写 1,N7 不动作 → 1(重新启动)。

也就是说,N7 的「停止」只在 Load=1 的扫描有效,不是保持;而「有箱才进料」的 N6 条件也被 N4 覆盖。如果 Load 是短脉冲,停止只持续一个扫描;如果 Load 是保持信号,输送机在箱子到位时停、箱子一离开又自动重启——这不一定符合工艺意图。

Feed Conveyor 的扫描顺序:N4 先写 1,N6/N7 再置位/复位
同一个扫描里 N4 先写 1;N6 的置位被覆盖,N7 的复位只在 Load=1 时有效

级别:P1(功能错误:没有箱子也进料;且停止不保持)。 置信度:确认(程序内 + 离线逐扫描仿真);工艺意图仍需确认。 修复建议:只保留一个驱动源;若要「有箱才进料、停止并保持」,用置位/复位或自锁,不要让普通线圈每扫描覆盖;或者把 N4 的 Feed Conveyor 拆成独立输出。 验证:Tag_1=1, Height_sensor_1=0, Load=0 → 1(没箱子也转);Height_sensor_1=1, Load=0 → 1;Load=1 → 0;Load=0 → 1(重启)。若要求停止保持,最后一步应为 0。

第五步:审时序与硬件——单扫描脉冲与编译警告

这一步不需要新的提示词。 第二步的任务书已经覆盖「时序/扫描」和「数据/地址」;agent 会从那套清单继续扫。如果它停下来,只回一句「继续,把时序和地址两类扫完,再对硬件」。

你可能需要回答的:原机 CPU 实际插了哪些 DQ/AQ 模块、Q1.2/Q1.3/QW30/QW34 对应哪些通道;Emitter 是电磁阀还是接触器、10ms 脉冲够不够。知道就回答;不知道就说「标待确认」,不要让它猜。

P2:Emitter 只有一个扫描周期的脉冲

N16 是 TON(IN = Tag_1 AND NOT Tag_9, PT = T#10s) → Tag_9,N17 是 Tag_9 → Emitter。Tag_9 自己又是 TON 的「非」条件,所以计时到 10s 后:

  • 第 1000 个扫描(10ms 周期):Tag_9=1;
  • 第 1001 个扫描:Tag_9=0,TON 重新计时。

这是 Main 的实际梯形图(N16/N17):

Main 的实际梯形图:N16/N17 Emitter 单扫描脉冲
N16 的 TON 计时 10s,Q 驱动 Tag_9;Tag_9 又作为 NOT 条件,到点后下一扫描自复位

Emitter 只得到一个扫描(10ms)的脉冲。如果它是电磁阀/接触器,10ms 可能来不及动作——现场表现就是「出料偶尔不动作」。级别 P2;修复用 TP 保持一个固定脉宽,或用置位/复位 + 定时器复位。

P2:编译警告「硬件中不存在使用的 I/O」

编译 0 错误 / 1 警告。本课沙盒是 CPU 1215C DC/DC/DC,集成 DI14/DQ10 + AI2/AQ2;示例使用 Q1.2、Q1.3、QW30、QW34,不在集成 I/O 范围内。原始工程可能另有 DQ/AQ 模块。

这不是逻辑错误,但不能忽略:TIA 编译不检查「地址有没有物理通道」,下载后这些点可能根本没有接线。审查报告里把它列为 P2「硬件配置待确认」,修复方式是补模块或改地址,验证方式是硬件组态 + 下载后 I/O 检查。

P3:程序内没有急停/安全逻辑

31 个标签里没有 E-stop,程序只有 Start/Reset。这不一定是缺陷:原机可能有硬接线安全回路或安全继电器。审查报告把它列为 P3「无法确认」,需要电气图纸和安全评审;AI 不能做安全认证,也不能用「程序里没有」推出「机器不安全」。

第六步:反证与分级——把「看起来像问题」变成「能证实的发现」

这一步是整节课最值钱的地方。AI 审查最常见的失败不是漏看,而是把可疑当成确认。对每条候选,追问三个问题:

  1. 有没有别的网络/外部写入,让结论反转?
  2. 信号是保持还是脉冲?失败场景还成立吗?
  3. 有没有工艺/硬件要求,说明这是故意的?

本课实测排除了三条「看起来很吓人」的候选:

候选 为什么看起来像问题 反证结果 处理
SCL 里的 511Ret_Val、空 GOTO ; 像两处语法错误,AI 很容易报 P0 真实 TIA 逐块编译 0 错误 / 1 警告,块 consistent=true;重新导出 XML 是结构化的 PEEK/POKE/GOTO token 误报,排除;修正示例页的「SCL 编译失败」说法
SCL FC 每扫描 120×10 次系统时间读写 循环很大,像会拖垮扫描周期 没有扫描时间实测;不能从代码结构直接推结论 标 P2/P3「推断/需实测」,不进 P1
N2 复位在 N3 置位之前,两个按钮同按 像启停竞争 两个按钮同时按下时 Start 优先;没有工艺要求证明这是缺陷 标 P3「待确认」,不算已确认缺陷

重点看第一条。导出文本里确实有:

SCL
1#Value:=PEEK(area := 16#82,2     dbNumber := 0,3     byteOffset := 511Ret_Val);4...5       GOTO ;

但 tialink_compile 对 MHJ-PLC-Lab-Function-S71200 的真实结果是 0 错误 / 1 警告,tialink_meta 显示 consistent=true。重新 tialink_export 这个 FC,XML 里是结构化的 PEEK / POKE / GOTO token,不是上面那段拼接文本。

结论:511Ret_Val 和空 GOTO ; 是文本反编译/导出拼接伪影,不是程序缺陷。审查时不能用「读导出文本」代替「让 TIA 编译」。 这条误报已经回写修正到示例页:原来写「SCL 编译失败」,现在写「导出文本有拼接伪影,TIA 实际编译 0 错误」。

反证之后,报告里只留下能证实的:

ID 级别 发现 置信度
P1-01 P1 右分拣不按箱型;左箱型时左右同时动作;N12 不触发 确认(静态 + 仿真)
P1-02 P1 Feed Conveyor 多驱动:没箱子也进料,停止不保持 确认(静态 + 仿真);工艺意图待确认
P2-01 P2 Emitter 单扫描脉冲(10ms / 10s) 确认(仿真)
P2-02 P2 编译警告:硬件中不存在使用的 I/O 确认(编译 + 硬件对照)
P3-01 P3 程序内无急停/安全逻辑 无法确认(需图纸/安全评审)

第七步:出报告与零改动确认

报告不需要很长,但每一段都要能复核。先看报告的结构和分级口径:

《程序审查报告》的结构与分级
P0 阻塞 / P1 功能错误 / P2 维护风险 / P3 待确认;每条都要有证据和验证方法

用这个模板:

# 程序审查报告

### 1. 范围与基线
工程 / CPU / 块 / 网络 / 语言 / 点表 / 系统 DB / 审查前 dirty

### 2. 结论摘要
P0/P1/P2 数量;能不能投运;最危险的 1-2 条

### 3. 发现
#### P1-01 <标题>
- 证据:块名 + 网络号 + 标签/指令(跨网络列出所有写点)
- 失败场景:什么输入/时序/硬件状态下出错,后果是什么
- 影响:停机 / 误动作 / 数据损坏 / 维护风险
- 级别:P0 / P1 / P2
- 置信度:确认 / 推断 / 无法确认
- 修复建议:最小改动 + 风险
- 验证方法:读图 / 逐块编译 / PLCSIM / 云仿真 / 人工

### 4. 误报与排除
候选 → 为什么看起来像问题 → 反证结果 → 处理

### 5. 无法确认
需要工艺 / 硬件 / 安全资料才能判断的项

### 6. 修复顺序与回归计划
P0 → P1 → P2;每条怎么验证;谁确认

### 7. 只读声明
改没改、保存没保存;结束 dirty 状态

完整产物如下(本次运行生成;展示时只做了排版,内容未改):

展开《程序审查报告》全文(发现、误报、无法确认、修复顺序)

程序审查报告:Sorting Boxes(Factory IO)

只读生成 · 2026-10-21 · TiaLink 1.1.0.0 + TIA Portal V19 · L7_Station(CPU 1215C DC/DC/DC)

1. 范围与基线

  • 工程:sorting-boxes(开源示例,MIT)
  • 程序:Main(OB1,LAD,18 个网络)+ MHJ-PLC-Lab-Function-S71200(FC9000,SCL,1 个网络)
  • 点表:Default tag table,31 个标签;系统实例 DB 5 个
  • 编译:0 错误 / 1 警告(硬件 I/O 不存在)
  • 审查前 dirty=false;审查过程未修改被审查的程序对象,未保存工程

2. 结论摘要

  • P1:2 条(右分拣不按箱型/左右同时动作;Feed Conveyor 多驱动,没箱子也进料,停止不保持)
  • P2:2 条(Emitter 单扫描脉冲;硬件 I/O 配置警告)
  • P3:1 条(无急停/安全逻辑,需人工确认)
  • 误报:1 条(SCL「编译失败」不成立)
  • 投运建议:先修 P1,再确认 P2/P3;不要因为编译 0 错误就放行。

3. 发现

P1-01 右分拣不按箱型,且可能与左分拣同时动作
  • 证据:N11 NOT Tag_5 AND Load → Chain_Transfer_Right(普通线圈);N12 Tag_5 AND Load → Chain_Transfer_Right(置位);N13 复位 Chain_Transfer_Right 和 Tag_5,但程序内没有任何 Tag_5 置位。
  • 失败场景:任意箱型 Load=1 且 Tag_5=0 → N11 开右链条;Tag_2=1 时 N9 同时开左链条,左右同时动作。右输送机(N12 的 TOF)不运行,因为程序内 Tag_5 不置位。
  • 影响:分拣方向错误 / 机构干涉;右路输送缺失。
  • 级别:P1。
  • 置信度:确认(程序内静态 + 逐扫描仿真)。
  • 修复建议:补 Tag_5 的置位条件(另一种箱型),N11/N12 统一用一种驱动方式;或删除 N11,只保留按箱型的 N12。
  • 验证:场景表 Tag_2=1, Tag_5=0, Load=1 → 只允许左链条;Tag_2=0, Tag_5=1, Load=1 → 只允许右链条。
P1-02 Feed Conveyor 多驱动,没箱子也进料,停止不保持
  • 证据:N4 Tag_1 → Feed Conveyor(普通线圈);N6 Tag_1 AND Height_sensor_1 AND NOT Load → Feed Conveyor(置位);N7 Load OR Reset_Button_1 → Feed Conveyor(复位)。
  • 失败场景:Tag_1=1、Height_sensor_1=0、Load=0 时,N4 仍把 Feed Conveyor 写成 1——没有箱子也进料;N6 的 Height_sensor_1 条件被完全覆盖。Load=1 时 N7 复位为 0,但 Load 一消失,下一扫描 N4 又写 1,停止不保持。
  • 影响:进料输送机在无箱时运行;停止不可靠;N6/N7 的置位/复位意图被 N4 覆盖。
  • 级别:P1(功能错误:没有箱子也进料;停止不保持)。
  • 置信度:确认(程序内 + 逐扫描仿真);工艺意图仍需确认。
  • 修复建议:只保留一个驱动源;若要「有箱才进料、停止并保持」,用置位/复位或自锁,不要让普通线圈每扫描覆盖;或者把 N4 的 Feed Conveyor 拆成独立输出。
  • 验证:Tag_1=1, Height_sensor_1=0, Load=0 → 1(没箱子也转);Height_sensor_1=1, Load=0 → 1;Load=1 → 0;Load=0 → 1(重启);若要求停止保持,最后一步应为 0。
P2-01 Emitter 是单扫描脉冲
  • 证据:N16 TON(IN=Tag_1 AND NOT Tag_9, PT=10s).Q → Tag_9;N17 Tag_9 → Emitter。
  • 失败场景:Tag_9 在第 1000 个扫描(10ms 周期)为 1,第 1001 个扫描为 0;Emitter 只得到一个扫描的脉冲。
  • 影响:电磁阀/接触器可能来不及动作;出料看起来「偶尔不动作」。
  • 级别:P2。
  • 置信度:确认(逐扫描仿真)。
  • 修复建议:用 TP 保持固定脉宽,或用置位/复位 + 定时器复位。
  • 验证:PLCSIM 跟踪 Tag_9 的脉宽。
P2-02 编译警告:硬件中不存在使用的 I/O
  • 证据:编译报告 0 错误 / 1 警告;CPU 1215C 集成 DI14/DQ10、AI2/AQ2;程序使用 Q1.2、Q1.3、QW30、QW34。
  • 失败场景:如果目标 CPU 没有对应模块,下载后这些点没有物理通道;编译只给警告,不阻止下载。
  • 影响:现场点位不动作;需要核对硬件配置/订货号。
  • 级别:P2(配置问题,不是逻辑错误)。
  • 置信度:确认(编译警告 + 硬件对照);具体是哪些点需在 TIA 硬件组态里逐项确认。
  • 修复建议:补 DQ/AQ 模块或改地址;不要忽略这条警告。
  • 验证:硬件组态 + 下载后 I/O 检查。
P3-01 无急停/安全逻辑
  • 证据:31 个标签中没有 E-stop;程序只有 Start/Reset。
  • 失败场景:如果急停只依赖软件,程序内没有失效方向;但原机可能有硬接线安全回路。
  • 影响:安全功能不能由本程序证明。
  • 级别:P3(待确认,不是已确认缺陷)。
  • 置信度:无法确认(需要电气图纸/安全评审)。
  • 修复建议:由有资质人员确认安全回路;本报告不作为安全认证。

4. 误报与排除

  • SCL「编译错误」:导出文本/反编译结果里出现 511Ret_Val、空 GOTO ;,看起来像语法错误;真实 TIA 逐块编译 MHJ-PLC-Lab-Function-S71200 为 0 错误 / 1 警告,块 consistent=true。结论:文本导出拼接伪影,不是缺陷;不要用文本导出代替编译器。
  • SCL 扫描时间:120×10 次系统时间读写看起来有风险,但没有扫描时间实测;标「推断/需实测」,不进 P1。
  • Start/Reset 同扫描:N2 复位在 N3 置位之前,两个按钮同时按下时 Start 优先;没有工艺要求证明这是缺陷,标 P3/待确认。

5. 无法确认(需人工/硬件/工艺)

  • 急停/安全回路(电气图纸、安全评审)
  • Load 传感器是保持信号还是短脉冲(影响停止的持续时间;不改变「没箱子也进料」的结论)
  • 原始 CPU 的 I/O 模块配置(决定 P2-02 的修复方式)
  • 右分拣的工艺意图(Tag_5 应该由哪个箱型置位)

6. 修复顺序与回归

  1. P1-01 右分拣:补 Tag_5 置位/统一驱动 → 编译 0/0 → 场景表验证左右互斥;
  2. P1-02 Feed Conveyor:单一驱动/保持停止 → 场景表验证「无箱不进料」+「Load 消失后不重启」;
  3. P2-01 Emitter:TP/锁存 → 脉宽测量;
  4. P2-02 硬件:补模块/改地址 → 编译警告清零;
  5. P3-01 安全:人工评审,不在本程序里「修」。

7. 只读声明

审查过程未修改被审查的程序对象,未调用 save;导入/编译只改内存状态;结束 dirty=true,由工程主人关闭不保存。

你得到什么

  • 一份《程序审查报告》:范围/基线、P0/P1/P2 发现、误报、无法确认、修复顺序;
  • 一张 输出 → 写点 表:多驱动、置位/复位配对、扫描顺序问题一眼可见;
  • 一组可复现的验证方法:静态推演、逐块编译、PLCSIM/云仿真、人工确认;
  • 工程零改动:审查前记的 dirty,审查后应当没有保存(本课实测 false → true,但从未 save)。

需要你动手的地方(很少)

  • 工艺确认:Load 是保持还是脉冲、右分拣应该由哪个箱型触发、Feed Conveyor 的停止要不要保持;
  • 硬件确认:Q1.2/Q1.3/QW30/QW34 在原机上有哪些模块/通道;
  • 安全评审:急停/安全回路必须由有资质的人确认,不能采信 AI 的结论;
  • 决定修不修:审查阶段只出报告;修 P1 时按 L2 的影响分析 → 小步修改 → L4/L6 验证 → L5 回归的顺序走;
  • 不要保存:如果你只是练习,关闭工程时选「不保存」,把临时设备留在内存里即可。

验证清单

  • 审查前后工程状态一致:没有修改、没有保存;dirty 有记录;
  • 报告覆盖 7 类清单,至少 4 条有证据的发现;
  • 每条发现含:块/网络/标签、失败场景、影响、级别、置信度、修复建议、验证方法;
  • 至少 1 条被反证/降级,证明误报过滤生效;
  • 编译类与行为类分开;编译 0/0 不作为行为正确的证据;
  • 安全相关项单列,标注「需有资质人员确认」;
  • 报告可交接:别人能按证据复现每条结论;
  • 没有把风格偏好写进「发现」;
  • 没有用导出文本代替 TIA 编译(特别是 SCL 拼接伪影)。

常见坑

  • 把「看起来像」当「确认」:511Ret_Val、空 GOTO ; 就是典型;真实 TIA 编译 0 错误。编译结论只信编译器。
  • 只看单个网络:多驱动、扫描顺序、置位/复位配对,必须按输出标签做全局写点表。
  • 被讲解/注释带偏:示例页讲解、变量注释、网络标题都可能错;先看接线和编译结果,再决定要不要信文字。
  • 把风格当缺陷:命名、注释、网络拆分可以建议,但没有失败场景就不进「发现」。
  • 忽略编译警告:「硬件中不存在使用的 I/O」不是噪音;它可能意味着下载后点位不动作。
  • 用仿真代替硬件/安全:仿真能证明逻辑行为,不能证明接线、通道、安全回路。
  • 让 AI 做安全认证:安全结论必须由有资质的人确认;AI 只能标「无法确认」。
  • 审查阶段改代码:一改就失去「只读基线」,后面所有证据都不可信;先出报告,再按 L2/L5 的流程改。
  • 只审 AI 写的代码:老工程、别人写的代码、自己写的代码,都值得用同一张清单审一遍。

下一步

  • 修 P1:先用 L2《改一个 IO 地址,会影响谁?》 的方式做影响分析,再小步修改;每步用 L4《投运前先仿真》 或 L6《不装博途先跑一遍》 验证行为;结构改动后用 L5《重构不改行为》 做回归。
  • 把清单固化成团队模板:7 类 + 证据 + 反证 + 严重级别,可以直接当 MR/评审模板;每次都先跑一遍,再人工评审。
  • 第二阶段:用 TIA-CONTEXT 的图谱做跨块引用/影响查询,用 BLOCK-SIM 自动生成场景报告;本课的「只读审查 + 证据链」结构不变,只是把人工查引用换成图谱查。
  • 练习建议:拿你自己的一个老工程,按本课的任务书审一遍;先只出报告,不改代码。审完再决定哪条值得修。

本课工具

TiaLink

把 TIA Portal 接到你的智能体:导入、编译、读回核对、PLCSIM 仿真。本地运行,工程数据不出厂。

打开 TiaLink