如何在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
解决方案与代码改写
核心要点
- 无需重写整个状态序列,只需扩展60状态的逻辑,区分中间执行型M函数和程序结束型M函数(如M30/M02)
- 使用
ItpGetHskMFunc获取当前M指令编号,执行对应设备逻辑后再发送确认信号 - 新增设备状态检测逻辑,确保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
相关产品推荐
相关产品推荐

