AI驱动的 PLC 程序开发 (WorkBuddy+TiaLink)

我们让 WorkBuddy 通过 TiaLink 操作本机的博途 V19,实现一条 S7-1500 输送线分拣控制程序。

AI驱动的 PLC 程序开发 (WorkBuddy+TiaLink)
博途PLC工程智能体 | AI智能体博途网关 | 博途PLC程序知识图谱 | 梯形图转SCL | 自然语言生成梯形图 | 自然语言生成SCL | 逆向生成程序块文档 | 梯形图在线查看 | 博途编程文档MCP | AI模型价格对比 | AI工具导航 | ONNX模型库 | Vibe Coding教程 | PLC在线仿真器 | Tripo 3D | Meshy AI

给智能体一份分拣控制需求,先加个 CPU 验证仿真,再把状态机、FB、测试用例一起写出来。

硬件组态把设备插齐了,网络组态把子网、IP、PN 设备名建好了,但控制器里还是一片空白——它不知道输送线怎么起、工件怎么分、故障了怎么办。

程序开发这一步,是前面两步的"下游":组态决定"有哪些设备",程序决定"这些设备怎么协同"。它比组态更接近工程的本质:

  • 状态机漏了一个状态,设备可能在某一步卡死,而编译照样通过;
  • 输出依赖上周期残留值,冷启动第一次可能对,第二次就不对;
  • 急停被写成普通逻辑,现场没人发现,直到真出事。

但程序开发同样是高度规则化的活:给定需求和状态定义,一个好的实现是可推导、可验证、可测试的。越是这种活,越适合交给智能体。

我们做了一次实测:让 WorkBuddy 通过 TiaLink 操作本机的博途 V19,先添加一个 CPU 并验证仿真器,然后实现一条 S7-1500 输送线分拣控制程序——SCL 状态机、可复用 FB、独立实例 DB,以及配套的状态说明、测试用例和竞态分析。

1、环境搭建

分工和前两篇一样:

  • WorkBuddy:读懂需求,做决策、排步骤,写代码和测试用例;官网下载
  • TiaLink:把每一步真正落到博途上——加设备、建块、写 SCL、编译、下载到仿真器、读回核对;官网下载
  • 博途:还是那个博途,装好 Openness 的 V19;这次额外用到随博途安装的 S7-PLCSIM Advanced仿真器。

TiaLink 需要和博途安装在同一台机器上,例如你的工控机;WorkBuddy 可以在另一台机器上,例如你的笔记本,但需要能访问 TiaLink 所在的主机。

启动博途和 TiaLink,然后在 WorkBuddy 中切换到【专家-技能-连接器】中的【连接器】页面,点击右上角的【自定义连接器】:

在弹出的对话框中点击【添加 MCP】添加 TiaLink,例如假设 TiaLink 所在主机的 IP 地址是 192.168.1.78:

{
  "mcpServers": {
    "tialink": {
      "type": "http",
      "url": "http://192.168.1.78:8080/mcp"
    }
  }
}

注意:在 WorkBuddy 中添加一个新的 MCP,需要明确地【启用】:

和组态任务不同,程序开发必须"能跑"。所以这次的第一件事不是写代码,而是:先添加一个 CPU,测试仿真器有没有问题。仿真器跑不通,后面写的所有代码都无从验证。

2、提示词

这是实际使用的提示词,前置条件是:项目里已经完成硬件和网络组态,现在要在当前项目中实现一个 S7-1500 输送线分拣控制程序:

在当前的tia portal项目中实现一个 Siemens S7-1500 输送线分拣控制 PLC 程序。

技术要求
1. 使用 SCL 实现状态机,状态编号与任务定义一致。
2. 将控制逻辑封装为一个可重复调用的 FB,使用独立实例 DB。
3. 定义清晰的输入、输出和内部状态变量。
4. 使用 IEC 定时器实现分拣超时与推料时间控制。
5. 实现入口工件去重、质量结果锁存、双气缸互锁、故障锁存、手动复位和正常停止。
6. 每个扫描周期必须保证输出具有确定值,不允许依赖残留的上周期值。
7. 急停仅作为安全回路状态输入;不得将普通 PLC 程序视为安全急停的替代方案。

交付物
- FB 的 SCL 源码
- 所需 UDT(如果使用)
- 状态转换说明
- 至少 10 个自动化测试用例
- 对边界条件和潜在竞态的分析

先添加CPU,测试仿真器有没有问题。

这段提示词为什么这么写?

七条技术要求,其实对应七类"程序开发里最容易埋雷的地方":

  • 状态机 + 状态编号一致:编号不是装饰,是追溯锚点。HMI 显示、报警文本、测试用例、现场排故都引用同一套编号,才能对得上。要求"与任务定义一致",就是不允许智能体自己另起一套编号。
  • FB + 独立实例 DB:输送线不止一条。写成 FC 或塞在主程序里,第二条线只能复制粘贴;写成 FB,第二条线就是第二个背景 DB。这是可复用性的分水岭。
  • 输入/输出/内部状态分离:i_ 输入、q_ 输出、stat_ 内部状态,边界一目了然。输出是谁写的、状态是谁维护的,不用读完整段代码。
  • IEC 定时器:用标准 TON_TIME,不自己用扫描周期累加计时。自己写的计时器在扫描周期抖动时误差累积,而且换 CPU 就可能不准。
  • 六类典型语义:入口去重(防抖动/粘连)、质量锁存(决策稳定)、双气缸互锁(防打架)、故障锁存(不自己消失)、手动复位(人来确认)、正常停止(可恢复)。这六条是分拣控制几乎绕不开的骨架。
  • 每周期确定值:输出要么在开头赋默认值、要么在每个分支显式赋值,绝不能"上次是 TRUE 这次不写就还是 TRUE"。这是程序从"能跑"到"能交付"的关键区别。
  • 急停是安全回路状态输入:这一条是责任边界。急停必须由硬件安全回路(安全继电器、安全 PLC)实现,普通 PLC 程序只读取"安全回路是否闭合"这个状态。把普通程序当安全功能,是把人命的赌注压在扫描周期上。

为什么第一步是"加 CPU、测仿真"?

因为这决定了这次交付的性质。组态任务交付的是"配置",看一眼截图就能判断对错;程序任务交付的是"行为",只有跑起来才知道对不对。先把 CPU 加上、把 S7-PLCSIM 跑通,等于先把"验证能力"建好,再开始写代码——这也是我们想观察的一件事:智能体会不会先搭好验证环境,而不是先写一堆代码。

3、执行过程复盘

经过大约1个小时15分钟,WorkBuddy 返回了结果:

首先是"加 CPU + 测试仿真"这一步,WorkBuddy根据要求选了CPU 1513-1 PN v2.9,然后验证仿真链路成功。

上图可以看到,WorkBuddy用一个封装分拣逻辑的函数块(FB_SorterCtrl)实现了分拣控制的主要逻辑,定义了一个UDT和OB1,逐条落实了需求。

在验证方面,WorkBuddy设计了16个测试用例,全部通过。这个环节也是用时最多的环节,16个用例大约跑了50分钟。

4、交付成果

本次测试的完整交付成果包含Tia Portal项目文件和交付说明,可以从Github下载。本章部分内容来自 交付说明.md。

WorkBuddy按要求提供了交付说明文件。

4.1 硬件组态

在Tia Portal中,最终完成的项目文件,包含一个设备:

4.2 程序实现

数据类型定义和程序块如下:

对象 类型 说明
typeSorterStatus UDT (PLC 数据类型) HMI 状态视图:状态/故障/计数/锁存镜像
FB_SorterCtrl FB1 (SCL, 优化访问) 分拣控制状态机,可重复调用
FB_SorterCtrl_DB DB1 (独立实例 DB) FB 的单独实例
Main OB1 (SCL) 周期调用,信号映射到 %M 区

FB_SorterCtrl(scl源文件):

4.3 信号映射

WorkBuddy用了%M 区,仿真与后续对接实际 I/O 均可直接替换。

输入:

地址 信号 说明
M0.0 CMD_START 启动(上升沿)
M0.1 CMD_STOP 正常停止(上升沿)
M0.2 CMD_RESET 手动复位(上升沿,仅故障态且急停恢复后有效)
M0.3 ENTRY_SENSE 入口工件传感器
M0.4 DETECT_SENSE 检测点传感器(工件到位)
M0.5 EXIT_SENSE 出口传感器(良品通过确认)
M0.6 QUAL_OK 质量结果:TRUE=良品
M0.7 QUAL_VALID 质量结果有效(与 QUAL_OK 须稳定 ≥1 扫描周期)
M1.0 PUSHER_SELECT 推料缸选择:FALSE=1#,TRUE=2#
M1.1 ESTOP_OK 安全回路状态输入(TRUE=回路正常),仅作状态,不替代安全功能
M1.2~M1.5 PUSHERx_OUT/IN_FB 两缸伸出/缩回到位反馈

输出:

地址 信号
M2.0 CONV_RUN(输送运行)
M2.1 / M2.2 PUSHER1_CMD / PUSHER2_CMD(伸出指令)
M2.3 READY(待机就绪)
MW4 / MW6 STATE(0~6)/ FAULT_CODE
MD10 / MD14 OK_COUNT / NG_COUNT

4.4 状态机与转换说明

这是WorkBuddy设计的状态机:

状态编号 状态名称 中文说明
0 IDLE 空闲状态
1 RUN 运行状态
2 WAIT_RESULT 等待质量检测结果
3 PASS_GOOD 良品处理状态
4 PUSH_NG 不良品推料状态
5 STOPPING 停止处理中
6 FAULT 故障状态

其中:

  • 状态 2(等待分拣结果):输送停止、工件保持。结果到达优先于超时(同周期两者齐发时不算超时)。
  • 状态 4(NG 推料):输送停止;选定气缸伸出 → IEC TON tPushHold 保持 PT_PUSH_TIME → 撤销指令 → 等缩回到位(必须先见过伸出反馈 bExtConfirmed)→ NG 计数。全程由 tPushGuard(伸出+保持+缩回)监督。
  • IEC 定时器(TON 多重实例,每周期无条件调用):tSortTimeout、tPassTimeout、tPushHold、tPushGuard、tStopTimeout。
  • 故障代码:1=分拣结果超时;2=良品放行超时;3=推料/停止反馈超时;4=双缸互锁冲突(反馈);10=急停回路断开;99=非法状态保护。首个故障优先锁存。

4.5 测试用例

# 用例 步骤概要 预期 结果
TC-01 上电急停状态 下载后 ESTOP_OK=0 STATE=6, FAULT_CODE=10, 输出全 0 ✅
TC-02 恢复+手动复位 ESTOP_OK=1, 复位沿 STATE=0, READY=1, 故障清零 ✅
TC-03 启动 START 沿 STATE=1, CONV_RUN=1 ✅
TC-04 良品全流程 入口→检测→结果良品→出口 回 RUN, OK_COUNT=1 ✅
TC-05 入口去重 连续 2 个入口脉冲再走良品流程 锁存恒 TRUE, OK_COUNT 仅 +1 ✅
TC-06 NG 推料 1# 缸 入口→NG 结果→P1_CMD=1→伸出反馈→保持→缩回反馈 NG_COUNT=1, 回 RUN ✅
TC-07 NG 推料 2# 缸 PUSHER_SELECT=1 重复 PUSHER2_CMD=1(P1_CMD=0), NG_COUNT+1 ✅
TC-08 分拣结果超时 检测后不给结果,超过 PT_SORT_TIMEOUT FAULT_CODE=1 锁存 ✅
TC-09 放行超时 良品后无出口信号 FAULT_CODE=2 锁存 ✅
TC-10 双缸互锁冲突 推料中同时置两缸伸出反馈 FAULT_CODE=4 锁存 ✅
TC-11a 推料全程超时 推料中不给任何反馈超过 PT_PUSH_TIMEOUT FAULT_CODE=3 锁存 ✅
TC-11b 缩回反馈滞后竞态 只给缩回反馈、从未给伸出反馈 不判完成(仍 PUSH_NG、计数不变);补伸出确认后正常完成 ✅
TC-12 运行中急停断开 RUN 中 ESTOP_OK=0 输出立即全 0, FAULT_CODE=10 ✅
TC-13 急停未恢复复位被拒 ESTOP_OK=0 时复位沿,再恢复后复位 前者保持故障,后者回 IDLE ✅
TC-14 处理中正常停止 RUN/处理中 STOP 沿 放弃工件(计数不变)→ STOPPING → IDLE ✅
TC-15 停止过程超时 停止中缩回反馈丢失超 PT_STOP_TIMEOUT FAULT_CODE=3 锁存 ✅
仿真参数说明:OB1 中传入宽松定时(保持 15s、结果/放行 60s、推料监督 90s、停止 30s)以适配测试链路延迟;FB 默认值(500ms/5s/5s/3s/5s)适用于生产整定。

5、结束语

程序开发和前两步一样,是整个 PLC 项目的关键环节:规则明确、结果可验证、错了后果严重,而且后果的暴露时间更晚——组态错了在线才会报,程序错了可能要等到某个特定工况才复现。

把这件事交给 WorkBuddy + TiaLink,我们想验证的还是那三件事,外加一条程序开发特有的:

会不会先查再建?会不会逐条验证?会不会在该停下来的时候停下来?会不会先搭好仿真环境,再开始写代码?

这次的结果依然是:会。

它先加 CPU、跑通仿真,再写 FB;写完编译、下载、按测试用例验证;最后把安全边界、硬互锁和现场整定明确标出来——而这恰好也说明,它清楚哪些事是代码能做的,哪些事是代码不能替代的。


汇智网原创,转载请标明出处