首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >RealPLC AI编程新增PlanAgent,使得生成的PLC程序更靠近工控现场!

RealPLC AI编程新增PlanAgent,使得生成的PLC程序更靠近工控现场!

作者头像
Hello工控
发布2026-05-25 12:42:12
发布2026-05-25 12:42:12
410
举报
文章被收录于专栏:Hello工控Hello工控

我们在第一期内测的时候,有朋友也提到生成程序和代码前需要plan规划下,这几天时间针对这点做了重大更新,新增了PlanAgent,专门处理用户的输入请求。

当然,思路也很简单,跟目前所有的AI进行vibe coding前,最好使用Plan模式进行规划,反复几轮对话以后,确定好plan规划,再来执行,一般比走一步看一步再优化这种方式,既准确,而且相对来说也更加节约tokens。

所以,我们这期来简单概括下,目前代码还在优化,会放到我们第二期内测中,敬请期待!

01

PLAN模式

关于plan模式实际上,各个AI工具基本上都已经内置了,甚至都不用去某个选项里特意去配置,只需要提问的时候带上这个词,在比较复杂的应用里面也会生成plan。

从我们真正使用和体验上来看,plan模式也需要先通过大量的上下文及需求询问后,才能得到比较好的PLAN计划。

当然,我们在vibe coding当前的RealPLC产品时候,也发现不仅仅有plan文档,而且还多了spec文档,格式都是md。

也就是说,在Plan以前还多了一步spec,也就是详细的细节和设计需求和你讨论清楚后,再来执行计划。根据计划再更新todolist:

02

需求分析

实际上,我们自己在编程之前,也会详细的了解客户设备的选型清单,输入输出的具体类型,输出是变频还是伺服等等。这些信息没有,根本没办法下手。

所以,我们在生成代码之前就加入需求分析这一步,可以让AI了解系统具体需求之后,再来推理,生成代码。

为了方便交互和快速推进,我们改善了问题回答的交互方式,直接通过选项选择具体的问题答案。通过这些问题交流后,AI才知道代码方向在哪里。

03

比较

我们为了方便比较,把第一期的生成效果,和当前的效果做个对比。第一期已经在我们网站www.realplc.com,所以直接登录访问:

选择最简单的专家模板,输送带的控制为例,这样两者提示词一模一样,我们直接把这两次的具体代码贴在下方。

第一期初始代码:

代码语言:javascript
复制






VAR
// 输入变量
    xStartButton: BOOL;// 启动按钮
    xStopButton: BOOL;// 急停按钮
    xSensor: BOOL;// 传感器信号
    xSensorFault: BOOL;// 传感器故障
    xGrid: BOOL;// 输送机安全栅

// 状态变量
    xRun: BOOL;// 输送机运行状态
    xStartCmd: BOOL;// 启动命令标志
    xStopCmd: BOOL;// 停止命令标志
    bStartPress: BOOL;// 启动按钮按下标志
    bStopHold: BOOL;// 急停锁定标志

// 定时器
    tSensorTimeout: TON;
    tSensorFaultCheck: TON;

// 常量
CONST
        gSensorTimeout: TIME := T#10s;// 传感器超时时间
        gFaultCheckInterval: TIME := T#1s;// 故障检测间隔
END_VAR
//--------------------------------------------------------------------//

// ========================
// 输入处理
// ========================
// 输入消抖
xStartButton := xStartButton OR NOT bStartPress;
xStopButton := xStopButton AND bStopHold;

// 启动按钮处理
CASE bStartPress
OFTRUE:
        xStartCmd :=TRUE;
        bStartPress :=FALSE;
ELSE
        xStartCmd :=FALSE;
END_CASE;

// 急停按钮处理
IF xStopButton THEN
    bStopHold :=TRUE;
    xStopCmd :=TRUE;
ELSE
IF NOT xStopButton THEN
        bStopHold :=FALSE;
        xStopCmd :=FALSE;
    END_IF;
END_IF;

// ========================
// 故障检测
// ========================
// 检测传感器故障
IF xSensorFault THEN
    tSensorFaultCheck(Q :=TRUE, PT := gFaultCheckInterval);
    xSensor :=FALSE;// 优先级高故障时强制置为FALSE
ELSE
    tSensorFaultCheck(Q :=FALSE);
END_IF;

// 传感器超时检测
tSensorTimeout(Q := xSensor AND NOT xSensorFault, PT := gSensorTimeout);

// ========================
// 状态机逻辑
// ========================
// 急停优先级最高
IF xStopCmd THEN
    xRun :=FALSE;
ELSE
// 启动条件判断
IF xStartCmd THEN
        xRun := xGrid AND xSensor;
ELSE
        xRun :=FALSE;
    END_IF;
END_IF;

// 运行控制
IF xRun THEN
// 启动PLC运行
    xRun :=TRUE;
ELSE
// 停止PLC运行
    xRun :=FALSE;
END_IF;

// ========================
// 输出控制
// ========================
TONMotor(
    Q := xRun,
    IN := xRun AND xSensor,// 冲程检测
    PT := gCycleTime
);

// 输出保护
IF NOT xGrid THEN
    xRun :=FALSE;// 安全栅断开时停止
END_IF;

经过Plan之后优化的代码:

代码语言:javascript
复制






(*============================================================*)
(*  数据类型定义                                         *)
(*============================================================*)
TYPE
  E_ConveyorState :
(
    Idle,(* 1. 空闲状态 *)
    Starting,(* 2. 启动阶段 *)
    Running,(* 3. 运行阶段 *)
    Stopping,(* 4. 停止阶段 *)
    Fault          (* 5. 故障状态 *)
);
  ST_FaultRec :
  STRUCT
    dtFault : DATE_AND_TIME;(* 故障时间戳 *)
    sType   :STRING[20];(* 故障类型 *)
  END_STRUCT;
END_TYPE

(*============================================================*)
(*  功能块:输送线控制                                 *)
(*============================================================*)
FUNCTION_BLOCK FB_ConveyorControl
VAR_INPUT
  xStartBtn   : BOOL;(* 启动按钮 (干触点) *)
  xStopBtn    : BOOL;(* 停止按钮 (干触点) *)
  xEStop      : BOOL;(* 急停按钮 (硬件联锁) *)
  xOverTemp   : BOOL;(* 超温传感器 (干触点) *)
  xFaultReset : BOOL;(* 故障复位按钮 *)
  bAuxReady   : BOOL;(* 辅助设备就绪信号 *)
  rSpeedSet   : REAL;(* 手动电位器设定速度 0~50Hz *)
  rTemperature: REAL;(* 温度值,用于条件联锁 *)
END_VAR
VAR_OUTPUT
  xVFDEnable : BOOL;(* 变频器启停信号 *)
  rVFDSpeed  : REAL;(* 变频器速度设定 *)
  xFault     : BOOL;(* 故障指示 *)
  sFaultCode :STRING[20];(* 故障描述 *)
  sFaultTime :STRING[30];(* 故障时间字符串 *)
END_VAR
VAR
(* 状态机 *)
  eState          : E_ConveyorState := E_ConveyorState.Idle;
(* 边沿检测 *)
  rtrigStartBtn   : R_TRIG;
  rtrigStopBtn    : R_TRIG;
  rtrigFaultReset : R_TRIG;
(* 计时器 *)
  tonStopDelay    : TON;
  tonOverTempClear: TON;
(* 速度输出 *)
  rSpeedOut       : REAL;
(* 故障历史 *)
  arrFaultHistory :ARRAY[0..gc_iMaxFaultHistory-1]OF ST_FaultRec;
  iFaultIndex     : INT :=0;
(* 变量 *)
  xFirstScan      : BOOL :=TRUE;
  xFaultPrev      : BOOL :=FALSE;
END_VAR
VAR_CONSTANT
  gc_iMaxFaultHistory   : INT   :=10;(* 故障历史记录最大数量 *)
  gc_tStopDelay          : TIME  := T#1s;(* 停止延迟 *)
  gc_tOverTempClearDelay: TIME  := T#5s;(* 超温恢复延迟 *)
  gc_tStartDelay         : TIME  := T#1s;(* 启动延迟(可选) *)
END_VAR

(*------------------------------------------------------------*)
(*  1. 首扫初始化                                      *)
(*------------------------------------------------------------*)
IF xFirstScan THEN
(* 输出安全状态 *)
  xVFDEnable :=FALSE;
  rVFDSpeed  :=0.0;
  xFault     :=FALSE;
  sFaultCode  :='';
  sFaultTime  :='';
(* 计时器重置 *)
  tonStopDelay(IN:=FALSE, PT:=gc_tStopDelay);
  tonOverTempClear(IN:=FALSE, PT:=gc_tOverTempClearDelay);
(* 边沿检测重置 *)
  rtrigStartBtn(IN:=FALSE);
  rtrigStopBtn(IN:=FALSE);
  rtrigFaultReset(IN:=FALSE);
(* 计数器重置 *)
  iFaultIndex :=0;
  xFirstScan :=FALSE;
END_IF

(*------------------------------------------------------------*)
(*  2. 边沿检测                                            *)
(*------------------------------------------------------------*)
rtrigStartBtn(CLK:=xStartBtn);
rtrigStopBtn(CLK:=xStopBtn);
rtrigFaultReset(CLK:=xFaultReset);

(*------------------------------------------------------------*)
(*  3. 计时器调用(无条件)                               *)
(*------------------------------------------------------------*)
tonStopDelay(IN:=rtrigStopBtn.Q, PT:=gc_tStopDelay);
tonOverTempClear(IN:=NOT xOverTemp, PT:=gc_tOverTempClearDelay);

(*------------------------------------------------------------*)
(*  4. 速度限幅                                            *)
(*------------------------------------------------------------*)
rSpeedOut := FC_Clamp(rSpeedSet,0.0,50.0);

(*------------------------------------------------------------*)
(*  5. 故障检测(急停 > 超温)                            *)
(*------------------------------------------------------------*)
IF xEStop THEN
  xFault     :=TRUE;
  sFaultCode :='EStop';
ELSIF xOverTemp THEN
  xFault     :=TRUE;
  sFaultCode :='OverTemp';
ELSIF tonOverTempClear.Q THEN
(* 超温恢复后清除故障 *)
  xFault :=FALSE;
END_IF

(*------------------------------------------------------------*)
(*  6. 故障历史记录(首次检测时记录)                     *)
(*------------------------------------------------------------*)
IF xFault AND NOT xFaultPrev THEN
(* 记录时间戳与类型 *)
  arrFaultHistory[iFaultIndex].dtFault := DATE_AND_TIME();
  arrFaultHistory[iFaultIndex].sType   := sFaultCode;
(* 记录时间字符串 *)
  sFaultTime := DATE_AND_TIME_TO_STRING(arrFaultHistory[iFaultIndex].dtFault);
(* 循环写入 *)
  iFaultIndex :=(iFaultIndex +1) MOD gc_iMaxFaultHistory;
END_IF
xFaultPrev := xFault;

(*------------------------------------------------------------*)
(*  7. 状态机                                             *)
(*------------------------------------------------------------*)
CASE eState OF
  E_ConveyorState.Idle:
IF NOT xEStop AND NOT xOverTemp AND NOT xFault AND rtrigStartBtn.Q AND bAuxReady THEN
      eState := E_ConveyorState.Starting;
    END_IF

  E_ConveyorState.Starting:
(* 先等待辅助设备就绪后再启用 VFD *)
IF bAuxReady THEN
      xVFDEnable :=TRUE;
      rVFDSpeed  := rSpeedOut;
      eState     := E_ConveyorState.Running;
    END_IF

  E_ConveyorState.Running:
IF rtrigStopBtn.Q OR xEStop OR xOverTemp THEN
      eState := E_ConveyorState.Stopping;
    END_IF

  E_ConveyorState.Stopping:
(* 等待停止延迟后关闭 VFD *)
IF tonStopDelay.Q THEN
      xVFDEnable :=FALSE;
      rVFDSpeed  :=0.0;
      eState     := E_ConveyorState.Idle;
    END_IF

  E_ConveyorState.Fault:
(* 故障时保持 VFD 关闭 *)
    xVFDEnable :=FALSE;
    rVFDSpeed  :=0.0;
(* 等待复位按钮 *)
IF rtrigFaultReset.Q THEN
      xFault :=FALSE;
      eState := E_ConveyorState.Idle;
    END_IF

ELSE
(* 防止意外状态,安全退回 Idle *)
    eState := E_ConveyorState.Idle;
END_CASE

(* 结束状态机 *)

(*------------------------------------------------------------*)
(*  8. 输出映射(已在状态机内完成)                      *)
(*------------------------------------------------------------*)

END_FUNCTION_BLOCK

(*============================================================*)
(*  主程序:IO 映射与 FB 调用                           *)
(*============================================================*)
PROGRAM PRG_Main
VAR
(* 实例 *)
  fbConveyor : FB_ConveyorControl;

(* 输入变量(示例,实际映射到硬件 IO) *)
  xStartBtn   : BOOL;(* 启动按钮 *)
  xStopBtn    : BOOL;(* 停止按钮 *)
  xEStop      : BOOL;(* 急停按钮 *)
  xOverTemp   : BOOL;(* 超温传感器 *)
  xFaultReset : BOOL;(* 故障复位按钮 *)
  bAuxReady   : BOOL;(* 辅助设备就绪 *)
  rSpeedSet   : REAL;(* 手动电位器设定速度 0~50Hz *)
  rTemperature: REAL;(* 温度值,供条件联锁使用 *)

(* 输出变量 *)
  xVFDEnable  : BOOL;(* VFD 开启信号 *)
  rVFDSpeed   : REAL;(* VFD 速度设定 *)
  xFault      : BOOL;(* 故障指示 *)
  sFaultCode  :STRING[20];(* 故障描述 *)
  sFaultTime  :STRING[30];(* 故障时间字符串 *)
END_VAR
//-------------------------------------------------------------------------------------//

(* 读取硬件 IO(示例,需根据实际 IO 名称进行替换) *)
(* 这里仅作演示,实际项目请使用系统 IO 映射或 HMI 读取 *)

(* 赋值给 FB 输入 *)
fbConveyor.xStartBtn   := xStartBtn;
fbConveyor.xStopBtn    := xStopBtn;
fbConveyor.xEStop      := xEStop;
fbConveyor.xOverTemp   := xOverTemp;
fbConveyor.xFaultReset := xFaultReset;
fbConveyor.bAuxReady   := bAuxReady;
fbConveyor.rSpeedSet  := rSpeedSet;
fbConveyor.rTemperature := rTemperature;

(* 调用 FB *)
fbConveyor();

(* 将 FB 输出映射到硬件 IO 或上位系统 *)
xVFDEnable  := fbConveyor.xVFDEnable;
rVFDSpeed   := fbConveyor.rVFDSpeed;
xFault      := fbConveyor.xFault;
sFaultCode  := fbConveyor.sFaultCode;
sFaultTime  := fbConveyor.sFaultTime;

END_PROGRAM

当然,除了plan Agent外,代码的生成规则也做了优化,从代码的水平及具体的质量看,确实有了巨大提升。

参考链接:

【1】https://www.realplc.com

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-05-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Hello工控 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档