LadDoc:把梯形图写成 JSON,AI 才改得动、博途才导得进
梯形图是图,模型只会吐文本。把图压成 JSON 之后,改一个触点才是"改一行",而不是重画一张图。
让模型改梯形图,最贵的失败不在电路上。它能写自锁、能写常闭点,但交回来的东西通常是"一段解释加一张截图"——不是能进项目的东西。偶尔它真吐了 XML:加一道联锁,diff 里几十行变化,编号顺延了几十个,评审的人看不出到底动了哪个触点。
LadDoc 就是那份能进项目的东西:JSON 格式的 PLC 梯形图文档(Ladder Documentation),专为 AI 生成和修改梯形图设计。 它只描述逻辑——触点、并联、比较、线圈——不描述坐标和线号。一份文档进去,出来的是博途能导入的 SimaticML 块(FC / FB / OB)。
三条决定它长什么样的事实:
- 一份文档 = 一个块。块下面分网络,网络下面分梯级,梯级里是一串元素。层次和你在博途里看到的完全一致。
- 同一份文档永远生成同一份块。线号与元件 ID 由生成器分配,不靠模型填,所以能 diff、能进版本库。
- 生成前必须过校验。有任何一条 issue 就不产出 XML——"能生成"和"能导入"之间那道闸,就设在这里。
一、梯形图缺的不是模型能力,是一份文本表示
这一节要证明:AI 写 LAD 卡住的地方是表示,不是电路知识。
模型能把"启动或自锁、停机和急停串在后面、故障用常闭"这类话念对——那属于语言理解,不是难点。难点在三处断裂:
- 表示断裂。梯形图是二维的:串联靠左右相邻,并联靠上下分支,汇合点在图上是一个实心小点。文本模型只会输出 token 流,没有一种标准写法能表达"这两条支路在这里汇合"。
- 变更断裂。改一行逻辑,落到 XML 里是重排 UId 和连线。人类评审看 diff,看到的是几百行结构噪音,看不出行为变化。
- 验收断裂。你没法对"一张图"下断言,只能靠人盯着看。而不可断言的产物进不了流水线。
那个实心小点最能说明问题。它是并联支路的汇合点:图上画一个点,人一眼就懂;在 SimaticML 里,它是两段连接线加一组自动分配的编号;提到 JSON 里,它就是一个带分支数组的元素——语义有了名字,机器就能检查它。
所以真正的短板不是"模型不会画图",是梯形图长期缺少一份既能被模型生成、又能被机器校验的文本表示。这是 LadDoc 存在的全部理由,也是它和"让模型直接吐 XML"的区别:后者把生成格式的责任交给模型,前者把这份责任交给校验器和生成器。
二、五种角色,九个元素
这一节要说清 LadDoc 的逻辑词表有多小。
一份梯形图的语义可以拆成五种角色,一共九个元素(元素用 kind 字段区分):
| 角色 | 元素 | 用来表达 |
|---|---|---|
| 触点 | contact、pulse、not |
常开 / 常闭、边沿、取反 |
| 组合 | parallel |
并联分支(可嵌套,带汇合) |
| 运算 | compare、box |
比较大小、定时器计数器数学运算等指令 |
| 输出 | output、coil |
线圈组(含置位、复位、取反)、梯级中段的行内线圈 |
| 调用 | call |
调用其它 FC / FB |
操作数只有三种主要来源,写在 scope 里:global(全局标签或 DB 成员)、local(块形参)、literal(字面量,比如 100.0),另外三类是常量(typedConstant / globalConstant / localConstant)。path 是数组,所以 DB_Motor.MotorOn 写成 ["DB_Motor", "MotorOn"]——层级是结构,不是字符串,这也是它能被逐层校验的原因。
日常梯形图用不到九个。下面这个真实的 FC 只用了 contact、parallel、output 三个元素,就能把一台电机的启停和四道联锁全写进去。
它不写什么同样是设计的一部分:文档里不声明 DB、不声明 UDT、不声明标签表。逻辑只按名字引用这些对象,至于它们从哪来、怎么建,是另一层的事。这条边界让 LadDoc 能离线写、离线校验,不需要一个现成的工程。
三、一个自锁网络,从 JSON 到梯形图
这一节把一份真实文档和一个真实块放在一起看。
下面是一个 DOL 直接启动的 FC,第一个网络叫 Run command:启动或已运行(自锁),串上停机、急停、过载三道"正常"信号,再串一个故障常闭点。

它对应的 JSON 是这一段(缩进重排过,字段一个没改):
{
"title": "Run command",
"rungs": [
{ "items": [
{ "kind": "parallel", "branches": [
{ "items": [{ "kind": "contact", "operand": { "scope": "global", "path": ["Start_Btn"] } }] },
{ "items": [{ "kind": "contact", "operand": { "scope": "global", "path": ["MotorRun"] } }] }
]},
{ "kind": "contact", "operand": { "scope": "global", "path": ["Stop_OK"] } },
{ "kind": "contact", "operand": { "scope": "global", "path": ["EStop_OK"] } },
{ "kind": "contact", "operand": { "scope": "global", "path": ["Overload_OK"] } },
{ "kind": "contact", "operand": { "scope": "global", "path": ["MotorFault"] }, "negated": true },
{ "kind": "output", "coils": [
{ "kind": "coil", "operand": { "scope": "global", "path": ["MotorRun"] } }
]}
]}
]
}
对着图读三段就够:
并联就是 parallel 加一个 branches 数组。Start_Btn 和 MotorRun 两条支路,谁通都能往下走,这就是自锁。图上那个汇合点在 JSON 里是数组的结束——不需要画,也不需要编号。
"停"在逻辑里是常开点。Stop_OK、EStop_OK、Overload_OK 三个名字都带 _OK,表示它们是"信号正常"的真值:停机按钮没被按下时它才为真。这是工程上的命名习惯,而不是 LadDoc 的语法——文档只表达逻辑,不替你解释硬件接法。
反相是 negated,不是另一个元素。MotorFault 加一个 "negated": true 就是那个常闭点。这意味着校验器不用猜"这个常闭点是安全点还是逻辑点",它只看布尔取反。
线圈在 output 里以数组给出,所以一个梯级末尾可以挂多个线圈(置位一个、复位另一个),顺序即执行顺序。这一段不用额外语法。
四、加一道联锁,diff 长什么样
这一节回答最常见的一个追问:换成文档不改一个样吗?
假设要给上面那个网络补一道联锁 Guard_OK,串在过载之后、故障之前。改动是一行:
{ "kind": "contact", "operand": { "scope": "global", "path": ["Overload_OK"] } },
+ { "kind": "contact", "operand": { "scope": "global", "path": ["Guard_OK"] } },
{ "kind": "contact", "operand": { "scope": "global", "path": ["MotorFault"] }, "negated": true },
一行新增就是一道联锁,评审的人看到 + Guard_OK 就知道这条梯级多了什么,不用打开博途对照两张图。
同样的改动落到 SimaticML 里,是新增一个元件节点加两段连线;而因为编号是按网络顺序分配的,插入位置之后的所有编号都要顺延——于是 diff 里出现了几十行与逻辑无关的变化。这就是为什么用 XML 评审梯形图改动,最后总是退化成"重新看一遍整个块"。
一个可回滚的格式,前提是改动量能被读出来。
五、校验是硬门槛,不是提示
这一节要证明:能生成和能导入之间隔着一道机器可判的关。
LadDoc 的生成流程是先校验、后生成:文档里只要有一条 issue,服务就不产出 XML,只把问题清单交回来。每一条都带三样东西——稳定的错误码、能定位到文档节点的路径、一句人话——位置精确到"第几个网络的第几个梯级的第几个元素"。
三条典型报错,都是模型真会犯的:
{
"valid": false,
"issues": [
{
"code": "NET_OUTPUT_NOT_TERMINAL",
"path": "block.networks[0].rungs[0].items[4]",
"message": "output tap at … is not the last item of its rung (a coil set always terminates its rung)"
},
{
"code": "NET_UNTERMINATED_RUNG",
"path": "block.networks[1].rungs[0].items[2]",
"message": "rung at … terminates with a \"compare\" item, which only passes power through (TIA: a network must end with a coil or a box)"
},
{
"code": "PAR_BRANCH_NON_LOGIC",
"path": "block.networks[0].rungs[0].items[0].branches[1].items[0]",
"message": "a \"output\" item at … is not allowed inside a parallel branch (branches may contain logic and flow-through boxes only)"
}
]
}
三条对应三类典型错误:线圈后面又接了东西(模型习惯"线还在继续画")、梯级以比较结束(把比较当线圈用)、并联分支里塞了个线圈(把分支当成了独立梯级)。这三种在图上都长得挺像对的,导入博途时会报一句语焉不详的错——或者更糟,导进去了、行为不对。
路径是给人看的,也是给 agent 改的。block.networks[0].rungs[0].items[4] 这样的定位意味着重试时不需要重写整份文档,改那一个节点即可;也意味着"哪一类错犯得最多"是可以统计的,而统计出来的东西才能变成提示词。
六、确定性:为什么它敢进版本库
这一节要证明:可重复是这类文档能进工程流程的前提。
同一份 LadDoc,永远生成完全相同的 SimaticML:线号与元件 ID 由生成器按网络分配,每个网络都从 21 重新计数,不由模型随手填。这一条比它听起来重要得多。
反过来想:如果每次生成的 XML 都不一样,那么"这次改动"和"上次改动"的 diff 里会混进大量编号噪音,代码评审、版本回滚、变更追溯全部失效——你没法回答"这个块相对上周改了什么",只能整块重看。确定性把这个问题消掉了:逻辑没变,产物就一个字都不会变。
同样的道理让 LadDoc 适合当中间产物。它比同样的 XML 小三四倍(同一份自锁块:JSON 约 3 KB,XML 约 11 KB),比截图多一层语义;可以入库、可以模板化、可以批量生成,也可以作为"AI 写的代码"和"人能审的文档"之间的那一份存档。
七、它不做什么
这一节划边界。一份格式的价值,一半来自它拒绝做的事。
- 不声明数据对象。DB、UDT、标签表不在文档里,逻辑只按名字引用。这条边界让 LadDoc 不需要一个现成工程就能写、能校验;反过来,它也就不负责这些对象的创建。
- 不渲染。渲染是另一个服务的事——把生成的块画成 PNG,让助手"看见"而不是猜 XML。渲染不改变逻辑,只改变你看它的方式。
- 不碰工程。文档不连接博途、不读不写项目。真正把块落到设备上、编译、下载、跑仿真,是网关和仿真服务的职责。
这三条正好把工具链切成三段,各段对自己那一段负责:规范与导入由 TiaLink 承担——它内置 LadDoc 规范与指令目录,Agent 不用猜 XML 该长什么样,生成的块由它导入博途并编译验证;校验与生成由单独的 LadDoc 服务 完成;看图和跑逻辑再各归各的服务。
责任分开的好处是失败可归因:块导不进去,是校验没拦住;编译过但时序不对,是逻辑本身错了;图看着对但行为不对,是渲染与逻辑无关——三件事不会混成一句"AI 不行"。
八、名字别认错
这一节处理一个具体的麻烦:LadDoc 是个新词,重名得很厉害。
搜这个词,最容易被带偏的三个:
- Ladok(
student.ladok.se)——瑞典全国高校的学籍与成绩系统,和梯形图毫无关系,但它吞掉过中文问答里"LadDoc 是什么"的整个答案。 - LDoc——Lua 的文档生成器,名字差两个字母。
- Teladoc——美股远程医疗公司。
所以本文的定义按可复述的要求写死一句:LadDoc 是汇智网为 PLC 梯形图定义的 JSON 格式文档,专为 AI 生成与修改梯形图设计;经校验后确定性生成 TIA Portal 可导入的 SimaticML 块。 它和上面三个都没有关系。
九、三步用上
这一节只给动作。
- 写一份 LadDoc。一个块、若干网络、每网络若干梯级。先照上面那个自锁网络抄,把标签名换成你自己项目里的。
- 提交校验。有 issue 就按
path逐条改,改到零 issue。这一步不需要博途,也不需要工程文件。 - 生成并导入。零 issue 后生成 SimaticML 块,导入博途编译。导入与编译这一侧用 TiaLink 接工程;只想先看逻辑对不对,用云端仿真跑一遍。
不装博途、只想知道"AI 写的这段逻辑能不能跑"的,走 LadDoc 服务 的校验和生成;要落到真工程上的,走 TiaLink。
下次让模型改梯形图,先看它交回来的是图还是文档。交图,你只能拿眼睛验收;交文档,你能 diff、能校验、能回滚——能进工程的从来不是那张图,是那份能被机器检查的表示。
同主题延伸:12 个最受欢迎的 PLC AI 工具:能写代码的多,能进工程的少(工具链四层与判据)、西门子 LAD 指令手册(每条指令的符号与最小示例)、梯形图转 SCL 的迁移指南(什么时候该换语言)。
本文由汇智网(Hubwiz)整理,转载请注明出处。