三菱FX5U多轴定位FB封装:ST语言实现原点复归、点动与定位

发布时间:2026/10/19 3:30:57
三菱FX5U多轴定位FB封装:ST语言实现原点复归、点动与定位 简介面向工业自动化工程师与三菱PLC编程人员这份压缩包提供了基于ST语言编写的FX5U轴控制FB块模板将原点复归、点动、定位运动等常用轴控逻辑封装为可复用模块适用于多轴伺服/步进系统开发。通过实例化同一FB块即可扩展轴数有效减少重复编程工作量提升调试效率。包内共8个文件整体990KB包含1个txt示例代码、1个HTML使用说明以及6张JPG示意图可辅助理解FB块的配置流程与实际效果。目前已有1071人学习浏览适合具备基础PLC知识、正在推进多轴运动控制项目的工程师参考。该模板直接给出ST语言源码与调用说明结合图片拆解原点复归、点动、定位运动的关键参数设置帮助读者快速搭建轴控制框架规避常见配置误区是多轴设备程序结构化设计的实用参考资料。1. 三菱FX5U轴FB封装用ST把原点复归、点动、定位一次写成通用块第一次在FX5U上写多轴程序时我把原点复归、点动、绝对定位三套逻辑在梯形图里复制粘贴了四遍每加一个轴就多三十几个网络改一句速度要翻四个地方。后来我把整套逻辑重写成ST语言的FB块用GX Works3直接在ST里定义输入输出和各轴参数把原点复归、点动、定位运动封装成一个轴FB块多轴重复时只要复制实例不需要重复编轴控制逻辑。这篇文章不讲花哨的算法就讲我在FX5U内置定位上跑过的这个轴FB块接口怎么定、ST代码怎么拆、多轴怎么配、哪里容易翻车。适合正在给设备写多轴定位、被重复梯形图折磨的程序员直接照着改。2. FX5U内置定位与FB设计先定接口再写逻辑2.1 FX5U内置定位的轴号与脉冲输出FX5U主打的是CPU内置定位不需要额外插定位模块高速脉冲输出由晶体管输出点担任轴号按0、1、2、3的顺序编排。我第一次用的时候就踩了轴号从0开始的坑设备图纸上写“1轴Y0”程序里我理所当然地填了K1结果定位指令一直不执行GX Works3监控里指令触发位为ON但当前值不动查手册才知道轴号是K0。所以设计FB时轴号千万不要直接从HMI读数塞进去最好在FB内部做一个“轴号缓冲区”让外部传0、1、2这样的纯数字再由内部映射到对应脉冲点。FB封装之前有一个前提得先明白FX5U每条定位指令的“触发条件”。和伺服驱动器里那种运行信号不同FX5U的DRVZ、DRVI、DRVA这类指令一般要求边沿触发也就是信号从OFF变ON的那一瞬间才有效。如果用一个位置开关一直给信号FB一次定位做完之后这个信号还停在ON那么下一次再让FB跑指令不会重新接收。所以FB内部不能直接拿外部按钮信号去触指令必须自己做上升沿检测把边沿脉冲和原信号分开处理。2.2 FB接口输入、输出和内部变量怎么划分这个FB块我起名叫FB_AXIS接口定义是经过三个项目迭代出来的FUNCTION_BLOCK FB_AXIS VAR_INPUT bEnable : BOOL; // 总使能OFF时所有运动命令无效 bHome : BOOL; // 原点复归请求 bJogFwd : BOOL; // 正向点动按住走松开停 bJogRev : BOOL; // 反向点动 bGo : BOOL; // 定位启动请求 bAbsMode : BOOL; // TRUE绝对定位FALSE增量定位 iAxisNo : UINT; // 轴号0,1,2,3... uiHomeSpd : DINT; // 原点复归高速 uiCreepSpd: DINT; // 原点复归爬行速度 uiJogSpd : DINT; // 点动速度 diSpd : DINT; // 定位速度 diPos : DINT; // 目标位置 END_VAR VAR_OUTPUT bBusy : BOOL; // 运动执行中 bDone : BOOL; // 定位完成/回零完成 bAlarm : BOOL; // 轴报警 diCurPos : DINT; // 当前值 wErrCode : WORD; // 错误代码 END_VAR VAR bPrevHome : BOOL; bPrevGo : BOOL; bCmdOn : BOOL; eCmdKind : WORD; END_VAR接口设计上我有三个原则第一所有输入信号都用BOOL或者DINT的普通变量不让外部程序直接给定位指令传结构体因为HMI数据写入和另一个PLC的通信都要操作普通标签太复杂的外部结构体会让联调很难查第二速度单位统一用Hz位移统一用脉冲数不在FB内部做毫米到脉冲的换算换算放到上层因为不同轴的丝杆螺距和电子齿轮比不一样FB只管“多少脉冲、多少速度”换算逻辑留在设备参数页第三错误代码用WORD输出而不是只给BOOL方便上位机直接查故障码。要注意的是输入输出变量里的DINT长度FX5U的定位寄存器按32位处理位置值超过正负20亿脉冲就会溢出FB里最好不要用INT统一用DINTHMI写入也要对应32位格式。2.3 边沿检测与运动状态机FB内部真正的难点是外部那些按钮信号都是电平信号而定位指令需要边沿信号。“上升沿”在梯形图里一句话的事到了ST里就得自己造一个沿记忆IF bHome AND NOT bPrevHome THEN bCmdOn : TRUE; eCmdKind : CMD_HOME; END_IF; bPrevHome : bHome; IF bGo AND NOT bPrevGo THEN IF bBusy THEN bCmdOn : FALSE; ELSE bCmdOn : TRUE; eCmdKind : CMD_POS; END_IF; END_IF; bPrevGo : bGo;这段代码的逻辑是bHome从OFF变ON时记录一次原点复归命令bGo从OFF变ON时记录一次定位命令但如果FB已经在忙就把启动命令清掉避免后面的指令把正在跑的动作打断。bPrevHome和bPrevGo就是上一扫描周期留下的影子变量这是ST语言里替代上升沿最通用的做法。参数说明eCmdKind保存命令类型我用CMD_HOME、CMD_JOG、CMD_POS三个常量来区分具体常量的值可以定义为内部静态变量或直接写“0”、“1”但不推荐直接写魔法数。常见的做法是在FB里留一个枚举声明GX Works3的ST支持枚举可以避免命令类型写错。这里把边沿检测放到每个扫描周期的开头后面的运动逻辑都以bCmdOn和eCmdKind为准这样同一个FB里无论以后加多少种命令都不会出现多处同时触发指令的冲突。3. ST语言核心逻辑原点复归、点动、定位的顺序与互斥3.1 原点复归分支高速找原点低速爬行确认原点复归按FX5U的DRVZ系列做法基本套路是先以高速向原点方向走碰到原点信号后减速再以爬行速度找原点。我一般不让驱动器自己回零而是让FB直接接管脉冲输出因为FX5U内置定位的DRVZ指令本身就支持回零速度、爬行速度两个参数外部要做的只是把速度传对CASE eCmdKind OF CMD_HOME: bBusy : TRUE; bDone : FALSE; // 调用原点复归指令iAxisNo为轴号 DRVZ(iAxisNo, uiHomeSpd, uiCreepSpd); eCmdKind : CMD_NONE; bCmdOn : FALSE; CMD_JOG: bBusy : TRUE; bDone : FALSE; JOGZ(iAxisNo, uiJogSpd); eCmdKind : CMD_NONE; bCmdOn : FALSE; CMD_POS: bBusy : TRUE; bDone : FALSE; IF bAbsMode THEN DRVA(iAxisNo, diPos, diSpd); ELSE DRVI(iAxisNo, diPos, diSpd); END_IF; eCmdKind : CMD_NONE; bCmdOn : FALSE; END_CASE;这里我给的是一个简化版的命令分发每个指令执行前先把bBusy置位做完这段后清掉命令标志确保同一个扫描周期内只启动一个动作。要注意DRVZ、DRVI、DRVA这类指令的助记符在GX Works3的FX5U ST程序里是可以直接调用的但不同固件版本的参数个数和排列有差异我工程里这套写法的顺序是轴号、位置、速度你复现的时候先按自己软件里的指令帮助对齐一遍。3.2 点动分支按住走、松开停还要跟定位互斥点动和定位最大的冲突是点动手一直按着结果定位命令也来了两个动作都想抢脉冲输出。我的做法是首先在命令采集阶段就判断点动信号只在FB空闲时才能进入命令队列进入运动状态以后点动松开就马上停止但不打断正在跑的定位。先列点动时的处理逻辑// 点动命令按上升沿进入松开后由内部检测停止 IF (bJogFwd OR bJogRev) AND NOT bBusy THEN bCmdOn : TRUE; eCmdKind : CMD_JOG; END_IF; // 点动中的停止检测到点动按钮都松开或状态异常 IF bBusy AND eCmdKind CMD_JOG THEN IF NOT bJogFwd AND NOT bJogRev THEN // 停止点动指令 JOG_STOP(iAxisNo); bBusy : FALSE; bDone : TRUE; END_IF; END_IF;这里JOG_STOP是我在工程里自己封装的一个停止函数实际做的是把对应轴的脉冲输出停止位置ON。很多新人在ST里面写点动喜欢一直用JOGZ指令其实JOGZ一旦触发后并不会自己松开必须由程序给出停止信号让它停下来所以点动分支里“松开按钮”本身就是一个停止动作。参数说明点动速度uiJogSpd我建议设成比定位速度低的数值通常在50%左右因为手动操作时操作员要盯着机械位置速度太高容易撞机。还有一点点动正反转两个信号不要同时为ON我在FB接口里没有做强制互斥而是交给外部梯形图去保证理由是现场设备HMI上都做了按钮互锁如果你担心操作员乱按可以在FB内部再加一个IF判定两个都为ON时直接忽略正转。3.3 定位分支绝对和增量到底什么时候用定位分支看bAbsMode绝对定位DRVA要求当前值有意义所以必须先知道机械原点在哪里否则位置坐标系是错的增量定位DRVI相对当前点走一段不用原点也能跑适合推料、步进这类只关心相对位移的机构。我一般会在设备手动模式下让操作员先回一次原点再切自动模式运行绝对定位。FB里处理得比较粗暴如果bAbsMode为TRUE而当前值寄存器里已经是个很大的随机数说明这台设备还没有回过原点FB输出bAlarm并拒绝执行DRVA。这一步很关键不然机械手第一次自动运行就可能直接撞到硬限位。实现方式如下IF bAbsMode THEN // 用当前值寄存器判断是否回零过绝对值大于环境值时报警 IF diCurPos -100000 OR diCurPos 100000 THEN bAlarm : TRUE; wErrCode : 16#4021; bCmdOn : FALSE; ELSE DRVA(iAxisNo, diPos, diSpd); END_IF; ELSE DRVI(iAxisNo, diPos, diSpd); END_IF;这段把绝对定位的安全检查放进了FB不依赖调用方的自觉。判断阈值100000脉冲要根据设备实际量程改我写过一台设备丝杆行程120mm螺距5mm步进细分2000一个来回就是480000脉冲阈值设到100000会因为原点偏了一点就误报警所以这个阈值别写死做成FB内部参数比较合适。3.4 运动完成和报警汇总定位指令执行之后FX5U会通过特殊继电器表示“定位结束”。FB里不能只在指令下发那一刻置位bDone因为脉冲没走完之前设备还在运动。我的做法是每个扫描周期读一次“轴运动中”标志从运动变为停止的下降沿才算完成// 读取轴的执行状态不同型号寄存器地址不同这里只写访问逻辑 xInMotion : READ_AXIS_BUSY(iAxisNo); // 完成信号从运动中变成停止的下降沿 IF bPrevMotion AND NOT xInMotion THEN bDone : TRUE; bBusy : FALSE; END_IF; bPrevMotion : xInMotion; // 报警汇总报警时强制退出运动状态 IF bAlarm THEN bBusy : FALSE; END_IF;这里我把READ_AXIS_BUSY写成一个占位函数实际工程里需要查看FX5U的轴状态地址表也可以直接用特殊继电器和寄存器。建议在调试时先用监控表确认自己轴上“运动结束”和“定位结束”两个标志然后用正确的标志位来产生bDone不同CPU和固件对这两个标志的定义不完全一致。4. 多轴复用实例化、参数映射和HMI对接4.1 创建多个FB实例FB写完后复用就是“复制实例”。在GX Works3全局标签或程序内声明中写四个实例VAR stAxis0 : FB_AXIS; // 1号轴Y0输出 stAxis1 : FB_AXIS; // 2号轴Y1输出 stAxis2 : FB_AXIS; // 3号轴Y2输出 stAxis3 : FB_AXIS; // 4号轴Y3输出 END_VAR每个实例拥有独立的输入输出变量和内部变量。程序里调用方式一模一样stAxis0( bEnable : xAxis0Enable, bHome : xAxis0Home, bJogFwd : xAxis0JogFwd, bJogRev : xAxis0JogRev, bGo : xAxis0Go, bAbsMode : xAxis0AbsMode, iAxisNo : 0, uiHomeSpd : 50000, uiCreepSpd : 1000, uiJogSpd : 10000, diSpd : 20000, diPos : iAxis0TargetPos );关键点是iAxisNo在外部赋值而不是FB内部写死。如果你发现FB代码里出现“0”这种轴号常量建议立刻改成输入参数。理由很简单复制实例时手一抖把0号轴的实例参数填成1两轴就会抢同一个脉冲输出程序编译不报错设备动作完全乱套。4.2 每个轴的参数映射表多轴FB最容易乱的就是参数和轴对应关系。我把每台设备的轴参数集中放在一个结构体或全局标签区域里并用注释的方式在代码里留轴参数表。实例名轴号脉冲输出原点传感器正限位负限位stAxis00Y000X002X003X004stAxis11Y001X005X006X007stAxis22Y002X010X011X012这张表不是为了写文档而是为了在GX Works3里做全局标签绑定的时候不出错。我一般先把这张表放在工程注释里然后把脉冲输出点通过GX Works3的定位参数配置窗口分配到Y0/Y1/Y2再启动FB实例。比如轴1实际用Y0输出但全局标签绑定到Y1程序编译后运行时会发现指令都没触发排查半天才看到标签映射错了。4.3 HMI联动HMI和FB的对接最忌讳的是HMI直接读写FB内部的变量。FB内部变量对HMI是不可见的需要把要显示和控制的数据引到全局标签去比如手自动切换、速度写入、当前位置显示、报警状态。我一般做一组中间标签在FB调用处做一次拷贝// 全局显示标签 g_Axis0CurPos : stAxis0.diCurPos; g_Axis0Busy : stAxis0.bBusy; g_Axis0Done : stAxis0.bDone; g_Axis0Alarm : stAxis0.bAlarm;我不建议HMI通过请求式通信直接在画面刷新上千次每秒的当前值即使FX5U的以太网读写速度够快也要克制刷新频率。当前值这种变量通常设定每200ms刷新一次按钮和模式切换这类变化不频繁的信号按需写入。在FB输出上还有一个细节bDone是脉冲信号FB跑完就消失HMI如果刷新周期太长看不到建议把bDone做成“完成脉冲保持”并加一个清除条件或者让HMI读取后由画面触发清除。5. FX5U轴FB调试避坑五个常见坑从现象到原因到解决5.1 轴号从0开始还是从1开始现象FB实例启动后定位指令的触发位已经为ON但对应脉冲输出点完全没有脉冲当前位置一点不动。排查GX Works3的定位监视画面发现目标位置和当前位置都没有变化。原因FX5U内置定位轴号从0开始第一个轴是K0不是K1。我在初版工程里按习惯填了1结果指令一直发给“1号轴”但设备上实际只有0号轴被初始化。GX Works3的定位参数区也是从0号开始所以指令找不到对应的运行通道。解决把iAxisNo统一改为0开始的编号并在FB接口注释里写清楚“0为第一轴”同时建议在HMI的画面上把1号轴显示成“Axis 0”而不是“Axis 1”让操作员也习惯这个编号法。如果现场人员只看设备铭牌上的1号轴最好让程序里的注释和HMI标签名显式对应设备编号。5.2 完成信号不刷掉第二次定位没反应现象设备第一次自动定位正常再一次触发定位时FB的bGo有了上升沿但定位指令不执行位置停在原地。原因第一次定位完成后bDone一直为ON调用方程序里没有清掉bDone而我的FB里面在收到新命令时看到bDone还置着就把整个使能条件给拦下来了。这个锅一半在调用方的梯形图一半在FB接口设计没有做完成自复位。解决我在FB内部增加了一个“完成信号看门狗”逻辑命令执行完成后bDone置位但在某个输入条件不满足时自动清除同时要求调用方必须用一个沿或按钮信号来启动定位不要用自锁信号去置bGo。从那以后我每写一个FB都会检查所有输出信号是否存在“不依赖外部清除”的自复位可能。5.3 ST类型不匹配WORD、INT、DINT的显式转换现象把FB编译后调用处报“类型不一致”的编译错误或者传入的定位速度参数运行时比设定值大很多。原因ST语言是强类型语言梯形图里自动进行的DINT到INT转换在ST里不会自动发生。尤其输入标签来自HMIHMI写入类型经常是INT16而FB要求的diSpd是DINT直接接上去编译不通过。解决在调用处加显式转换例如stAxis0( diSpd : DINT_TO_DINT(HMI_Axis0Spd), diPos : INT_TO_DINT(HMI_Axis0Pos) );GX Works3的ST里有很多类似的转换函数。在编写FB内部时也要注意字变量和位变量的区别常用的是WORD_TO_UINT、UINT_TO_DINT这种显式写法别用隐式转换去赌编译器。5.4 多轴同时触发脉冲输出点冲突现象两个轴FB同时启动点动或定位其中一个轴没有动作另一个轴速度明显不对而且监控到两个FB的bBusy都在TRUE。原因把两个轴配置到了同一个脉冲输出点。最常见的错误是在GX Works3的定位参数里1号轴和2号轴都选用了Y0作为脉冲输出。代码层面是独立的FB硬件层却是同一个输出脉冲通道冲突。解决先核对参数映射表确保每个轴的脉冲点不同然后再检查代码。如果硬件上确实不够用就要考虑加扩展定位模块不能靠软件去复用同一个输出点。在调试时我一般会把每个轴的脉冲点先做成常量并在FB里做一次输出点“互斥校验”发现两个实例传入了相同轴号立即输出报警。5.5 原点复归后位置偏差现象每次设备回原点后再做绝对定位目标位置和实际机构位置都有固定偏差偏差值和原点复归的爬行速度有关。原因原点复归分高速和爬行两段如果爬行速度设置太高机械在碰到原点传感器后还没来得及停下来脉冲数已经多走了一段。不同机械的惯性不一样这个值需要现场试验。解决把爬行速度放低并留出可调整的余地。我一般先设成高速的十分之一然后手动回原点一次量机械位置偏差再微调爬行速度直到偏差一致。另外原点传感器信号最好做成上升沿触发而不是常闭触点不然可能产生两次触发导致Z相信号对不上。6. 验证与进阶让每一根轴都能在30分钟内验收完FB写好之后光编译通过不算完。我习惯在GX Works3的监控表里做一个“轴的验收清单”把每根轴按顺序过一遍原点复归一次、正向点动、反向点动、增量定位5000脉冲、绝对定位回到原点、报警断开一次。每个动作都要观察bBusy和bDone的时序变化bBusy上升沿和bDone下降沿之间的时间就是实际定位耗时。进阶做法是增加一个轴参数结构体把原点速度、爬行速度、定位速度、软限位全部放进结构体而不是散落在多个输入参数里。这样FB实例可以简化成“一个结构体加几个BOOL”后续维护时开设备参数页就能改速度不用翻程序。我在第三个版本里把接口改成了这样VAR_INPUT bEnable : BOOL; bHome : BOOL; bGo : BOOL; stParam : ST_AXIS_PARAM; // 轴参数结构体 END_VAR此外验证时可以用模拟运行模式把脉冲输出点和原点信号用内部软元件替代先不接伺服驱动器跑一遍状态逻辑。这样可以确认FB内部沿检测、互斥、完成信号都正确再上真实机械。不要跳过这一步直接在真机上测试撞机的概率很高。最后还有一个习惯我每次发布多轴设备程序之前都会在GX Works3的注释里把每根轴的映射和参数更新日期写一遍就当是给未来的自己留的后悔药程序里所有和轴有关的常量必须以这张表为准谁改了丝杆螺距就得同步更新参数表和替换实例的输入速度。从那以后我每建立一个新轴FB程序都强制自己把第一件事从“先写逻辑”改成“先填参数表”再写逻辑希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询