You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TwinCAT 2 NC I PLC Control ST中创建与编写M函数逻辑

自定义M函数的ST逻辑实现(Beckhoff NCI框架)

问题背景

已在System Manager中定义M函数,但不清楚如何在ST语言中编写对应逻辑。目前已掌握插值组构建/清除、轴链接、NC程序加载等操作,NC文件需求示例如下:

do smth
Turn on cooling (via M100)
do smth else
Turn off cooling (via M100 or M101)
etc.

在Plc Control TcNci.lib中找到ItpConfirmHsk、ItpGetHskMFunc(理解为返回当前行的M指令编号)等功能块,但不明确其使用时机与方法。预定义的M30、M02可正常工作,但需要实现自定义M函数逻辑。

测试Beckhoff文档中的FirstNciSample时,该示例可正常处理M30和M02,但修改60状态段代码后频繁报错。现疑问:若M函数并非总是位于NC文件末尾,是否需要重写整个状态序列?如何改写60状态段以处理自定义M函数?

原始ST代码

nState: UDINT;
fbBuildGrp: CfgBuildExt3DGroup;
fbLoadProg: ItpLoadProgEx;
fbStart: ItpStartStopEx;
fbConfirm: ItpConfirmHsk;
fbClearGrp: CfgReconfigGroup;
--
CASE nState OF
0: pre define states
10: build interpolation group
20: load part program
30: wait until interpreter is READY
40: start part program
50: check if interpreter is not READY
60:
    (* confirm m-func - e.g. m30 *)
    (* add code to handle m-functions *)
    (* in the moment all m-functions are directly confirmed *)
    IF ( ItpIsHskMFunc(in_stItpToPlc) ) THEN
        bConfirm    := TRUE;
    ELSE
        bConfirm    := FALSE;
    END_IF
    fbConfirm(
        bExecute:= bConfirm,
        sNciToPlc:= in_stItpToPlc,
        sPlcToNci:= out_stPlcToItp );
    IF NOT fbConfirm.bBusy THEN
        IF fbConfirm.bErr THEN
            (* an error occured *)
            (* this usually can just occur, if a confirmation is triggered without a request *)
            bErr        := TRUE;
            nErrId  := fbStart.nErrId;
            nLastState  := nState;
            nState  := 9999;
        END_IF
    END_IF
    nItpState   :=  ItpGetStateInterpreter( in_stItpToPlc );
    IF nItpState = NCI_INTERPRETER_READY THEN
        (* part program is finished without an error *)
        fbConfirm( bExecute:= FALSE, sNciToPlc:= in_stItpToPlc, sPlcToNci:= out_stPlcToItp );
        nState  := 70;
    ELSIF nItpState = NCI_INTERPRETER_ABORTED THEN
        (* a runtime error occured - e.g. a lag distance error occured *)
        bErr        := TRUE;
        nErrId  := ItpGetError(in_stItpToPlc);
        nLastState  := nState;
        nState  := 9999;
    END_IF
70: clear interpolation group and switch nState to 0
9999: stop all and display an error
END_CASE

解决方案与代码改写

核心要点

  1. 无需重写整个状态序列,只需扩展60状态的逻辑,区分中间执行型M函数和程序结束型M函数(如M30/M02)
  2. 使用ItpGetHskMFunc获取当前M指令编号,执行对应设备逻辑后再发送确认信号
  3. 新增设备状态检测逻辑,确保M函数对应的动作完成后再继续NC程序执行

修改后的60状态段代码

(* 新增变量:存储当前M指令编号、设备状态标志 *)
nCurrentMFunc: UDINT;
bCoolingOn: BOOL;
bCoolingReady: BOOL; -- 根据实际设备添加的状态检测变量
--
60:
    (* 检测是否收到M函数请求 *)
    IF (ItpIsHskMFunc(in_stItpToPlc)) THEN
        (* 获取当前M指令编号 *)
        nCurrentMFunc := ItpGetHskMFunc(in_stItpToPlc);
        
        CASE nCurrentMFunc OF
            100: 
                (* 执行M100逻辑:打开冷却 *)
                bCoolingOn := TRUE;
                (* 等待冷却设备到位(根据实际硬件逻辑调整检测条件) *)
                IF bCoolingReady THEN
                    bConfirm := TRUE;
                ELSE
                    bConfirm := FALSE;
                END_IF
            101:
                (* 执行M101逻辑:关闭冷却 *)
                bCoolingOn := FALSE;
                (* 等待冷却设备关闭到位 *)
                IF NOT bCoolingReady THEN
                    bConfirm := TRUE;
                ELSE
                    bConfirm := FALSE;
                END_IF
            30, 02:
                (* 处理程序结束型M函数,直接确认并进入收尾流程 *)
                bConfirm := TRUE;
            ELSE
                (* 未定义的M函数:可选择直接确认或触发报错 *)
                bConfirm := TRUE;
                (* 可选:添加未定义M函数的报错逻辑 *)
                (* bErr := TRUE; nState := 9999; *)
        END_CASE
        
        (* 发送M函数确认信号 *)
        fbConfirm(
            bExecute:= bConfirm,
            sNciToPlc:= in_stItpToPlc,
            sPlcToNci:= out_stPlcToItp );
        
        (* 确认完成后的逻辑处理 *)
        IF NOT fbConfirm.bBusy THEN
            IF fbConfirm.bErr THEN
                bErr := TRUE;
                nErrId := fbConfirm.nErrId;
                nLastState := nState;
                nState := 9999;
            ELSE
                (* 重置确认标志 *)
                bConfirm := FALSE;
                fbConfirm(bExecute:= FALSE, sNciToPlc:= in_stItpToPlc, sPlcToNci:= out_stPlcToItp);
                
                (* 检查解释器状态:若为READY则程序结束,否则回到运行监控状态 *)
                nItpState := ItpGetStateInterpreter(in_stItpToPlc);
                IF nItpState = NCI_INTERPRETER_READY THEN
                    nState := 70;
                ELSE
                    (* 回到50状态,继续监控NC程序运行 *)
                    nState := 50;
                END_IF
            END_IF
        END_IF
    ELSE
        (* 无M函数请求,直接监控解释器状态 *)
        nItpState := ItpGetStateInterpreter(in_stItpToPlc);
        IF nItpState = NCI_INTERPRETER_READY THEN
            nState := 70;
        ELSIF nItpState = NCI_INTERPRETER_ABORTED THEN
            bErr := TRUE;
            nErrId := ItpGetError(in_stItpToPlc);
            nLastState := nState;
            nState := 9999;
        END_IF
    END_IF

关键说明

  • nCurrentMFunc:新增UDINT变量,用于存储当前获取的M指令编号,实现不同M函数的分支处理
  • bCoolingOn、bCoolingReady:根据实际设备需求添加的变量,用于控制冷却设备并检测其运行状态
  • 确认逻辑:必须等待M函数对应的设备动作完成后,再发送bConfirm := TRUE,避免NC程序提前继续执行
  • 状态跳转:M函数确认完成后,若解释器未进入READY状态,说明还有后续NC代码,需回到50状态继续监控程序运行

内容的提问来源于stack exchange,提问作者w1r2s

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 07:16:11