TiaLink
把 TIA Portal 接到你的智能体:导入、编译、读回核对、PLCSIM 仿真。本地运行,工程数据不出厂。
打开 TiaLink一段输送带分拣需求:让智能体通过 TiaLink 在你的 TIA Portal 工程里写 SCL,导入、编译到 0 错误 0 警告,再读回核对。
学完你能:独立走完「读工程 → 写需求 → 生成 SCL → 导入编译 → 读回核对」,并说清哪些环节不能交给 AI。
本课用一段「输送带分拣」需求,完整走一遍:智能体读工程 → 生成 SCL 功能块 → 通过 TiaLink 导入博途 → 编译到 0 错误 0 警告 → 读回核对 → 保存。
本课流程已在 TiaLink 1.1.0.0 + TIA Portal V19 + S7-1200(CPU 1214C,V4.6) 上实测跑通:最终编译 0 错误 0 警告,读回接口与需求一致。实测中撞到的两个真实坑(计时器调用漏 PT、输出未初始化)都写进了下面的实际过程和「常见坑」——这恰好是本课最想教的东西:AI 写的代码能不能用,由编译器和读回核对说了算,不由 AI 自称。
本课按一次真实运行来讲:你只输入一段需求,其余都是 agent 的工作。下面会告诉你它中间做了什么、哪里可能需要找你、最后你得到什么。
口径:AI 是辅助,改动必须人工复核。安全功能、联锁与急停逻辑不交给 AI。
PT、输出未初始化;SorterDemo),不要在正在用的工程上练。空项目里没有设备也没关系——本课过程会建一台 CPU;没有带 PLC 软件的设备时,导入会直接失败(实测报错:No device with PLC software was found in the project.);http://localhost:8080/mcp。真实使用只有一次输入:你把需求说清楚。之后读工程、建 CPU、写 SCL、导入、编译修错、读回核对、保存,都是 agent 自己做的。需要你的地方基本只有两处:它先报告后改动时你点个头,以及最后抽查看结果。
动手写需求之前,只做两件一次性的事(之后每次用都不再需要):
/mcp 端点。地址填你实际的 TiaLink 网关地址:TiaLink 与博途同机部署;MCP 客户端在另一台机器时,填博途那台机器的局域网地址,端口以 TiaLink 启动配置为准。先在本页顶部点「设置」填一次(存在本机,示例库页面也用同一个地址),下面的 URL 会跟着更新,点「复制」直接贴进客户端配置:
{
"mcpServers": {
"tialink": {
"type": "http",
"url": "http://localhost:8080/mcp",
"headers": { "Authorization": "Bearer <你的 TiaLink API Token>" }
}
}
}看到什么:客户端列出 TiaLink 的工具(名字以 tialink_ 开头,覆盖健康检查、读工程、导入、编译、导出、保存等)。工具数量随 TiaLink 版本变化,不必对数字,能看到这组前缀就对了。
把下面这段发给 agent(需求部分可以换成你自己的):
帮我在当前博途工程里实现一个功能块,并直接做到可交付:
需求:写一个 FB
FB_Sorter(SCL),输入:Start(Bool)、SensorA(Bool)、SensorB(Bool)、Reset(Bool);输出:DiverterA(Bool)、DiverterB(Bool)、Running(Bool)。Start上升沿后Running置位;SensorA触发后DiverterA输出 2s;SensorB触发后DiverterB输出 2s;两路互锁;Reset复位所有输出。定时器用命名的 IEC 定时器实例(TON_TIME,声明在 Static 区)。要求:
- 先只读工程,告诉我你看到了什么;如果工程里没有 PLC 设备,先查订货号建一台(先 dry-run 再创建);
- 实现这个块并导入工程;自己编译并读取编译结果,报错就修,重复到 0 错误 0 警告,不要让我手工粘贴输出;
- 读回块核对需求(接口、时序、互锁、复位),输出「需求 → 实现 → 结论」对照表;
- 清理导入留下的多余外部源文件,最后保存工程并确认没有未保存修改;
- 全程只动这个块和必要的新建设备,不要修改工程里的其他对象;涉及安全、联锁与急停的部分提醒我人工复核。
发完这一条,你等着看结果就行。下面是它实际会做的事(本次实测过程)。
它先确认 TiaLink 已连接、项目名和写入权限,然后只读工程。新建空项目的回报是「没有 PLC 设备 / 设备树是空的」——这是预期,不是失败。
它自己查订货号、挑最新固件版本,先 dry-run 报告将要创建的设备,再创建。
这里可能会找你确认一次:如果 agent 严格按「先报告后改动」的习惯办事,它会问你要不要建这台 CPU;回复「建」即可。想省这一步,可以在需求里预先授权(上面的提示词已经写了「先查订货号建一台」)。
创建后工程里出现 PLC_1 和 Main (OB1),它会重新读一遍确认,再继续。
它从需求生成块接口和逻辑——接口与需求逐条对应,定时器是 Static 区的命名实例:
1FUNCTION_BLOCK "FB_Sorter"2VAR_INPUT3 Start : Bool;4 SensorA : Bool;5 SensorB : Bool;6 Reset : Bool;7END_VAR8VAR_OUTPUT9 DiverterA : Bool;10 DiverterB : Bool;11 Running : Bool;12END_VAR13VAR14 PulseA : TON_TIME;15 PulseB : TON_TIME;16END_VAR17BEGIN18 IF #Start AND NOT #Reset THEN19 #Running := TRUE;20 END_IF;2122 #PulseA(IN := #Running AND #SensorA AND NOT #PulseB.Q,23 PT := T#2s);24 #DiverterA := #PulseA.Q;2526 #PulseB(IN := #Running AND #SensorB AND NOT #DiverterA,27 PT := T#2s);28 #DiverterB := #PulseB.Q;2930 IF #Reset THEN31 #Running := FALSE;32 #PulseA(IN := FALSE);33 #PulseB(IN := FALSE);34 #DiverterA := FALSE;35 #DiverterB := FALSE;36 END_IF;37END_FUNCTION_BLOCK看起来完全符合需求,也能生成块——但编译不过。下面才是它真正花时间的地方。
它把块导入工程并编译。第一轮:2 错误 2 警告。然后它自己读取编译输出、定位原因、修改、重新导入,重复这个过程,直到 0/0。你不需要粘贴任何报错。
这两个报错就是本课最值得记住的地方:
[Error] Parameter 'PT' has to be used. —— 计时器每次调用都必须带 PT,包括复位分支里那句 #PulseA(IN := FALSE);。正确做法是每扫描周期只调用一次计时器,把复位条件并进 IN:#PulseA(IN := #RunningState AND #SensorA AND NOT #PulseB.Q AND NOT #Reset, PT := T#2s);,输出再用 #PulseA.Q AND NOT #Reset 兜底。[Warning] The parameter '#Running' might not be initialized. —— 输出在读取前没有被确定赋值。用一个 Static 状态变量(RunningState : Bool := FALSE;)承载状态,最后 #Running := #RunningState; 无条件赋值,警告消失。修复后的完整 SCL(实测,编译 0 错误 0 警告):
1FUNCTION_BLOCK "FB_Sorter"2VAR_INPUT3 Start : Bool;4 SensorA : Bool;5 SensorB : Bool;6 Reset : Bool;7END_VAR8VAR_OUTPUT9 DiverterA : Bool;10 DiverterB : Bool;11 Running : Bool;12END_VAR13VAR14 PulseA : TON_TIME;15 PulseB : TON_TIME;16 StartEdge : R_TRIG;17 RunningState : Bool := FALSE;18END_VAR19BEGIN20 #StartEdge(CLK := #Start);21 IF #Reset THEN22 #RunningState := FALSE;23 ELSIF #StartEdge.Q THEN24 #RunningState := TRUE;25 END_IF;2627 #PulseA(IN := #RunningState AND #SensorA AND NOT #PulseB.Q AND NOT #Reset, PT := T#2s);28 #DiverterA := #PulseA.Q AND NOT #Reset;2930 #PulseB(IN := #RunningState AND #SensorB AND NOT #DiverterA AND NOT #Reset, PT := T#2s);31 #DiverterB := #PulseB.Q AND NOT #Reset;3233 #Running := #RunningState;34END_FUNCTION_BLOCK
最后它把块从工程里读回,逐项核对需求并输出「需求 → 实现 → 结论」对照表;顺手清掉中间迭代留下的外部源文件;然后保存工程,确认没有未保存修改。
FB_Sorter(以及为了装下它而建的 CPU),编译 0 错误 0 警告,且已保存;正常使用不需要;如果你想在每一步停下来看,可以用这些指令:
| 想介入的点 | 发给 agent 的话 |
|---|---|
| 先只读 | 只读,不要修改。告诉我设备清单、块清单、变量表和现有逻辑。 |
| 建 CPU | 工程里没有 PLC 设备。先查订货号,先 dry-run 报告,再建一台。 |
| 只写需求 | 把上面的需求先只给我 SCL 源码和接口说明,不要导入。 |
| 导入编译 | 把 FB_Sorter 导入并编译,自己读取结果修到 0 错误 0 警告,不要让我贴输出。 |
| 读回保存 | 读回 FB_Sorter 核对需求并输出对照表,清理多余外部源文件后保存。 |
PT;No device with PLC software was found in the project. 先补一台 CPU(agent 可以代劳)。prerequisites 里白名单不通过时,第一次写入会让 TIA 弹授权窗,只能人工确认;先跑一次 TiaLink.Helper.exe 可以免掉。PT:Parameter 'PT' has to be used.——每次调用都要给 PT,复位分支别写 #PulseA(IN := FALSE);,改成把复位条件并进 IN。The parameter '...' might not be initialized.——状态用带初值的 Static 变量,输出最后无条件赋值。把 TIA Portal 接到你的智能体:导入、编译、读回核对、PLCSIM 仿真。本地运行,工程数据不出厂。
打开 TiaLink