简介:面向三菱FX5U系列PLC开发者的可复用轴控制功能块模板,采用ST(结构化文本)语言编写程序。功能块将原点回归、手动点动、单段/多段定位等核心运动逻辑封装为独立模块,参数通过接口引脚灵活配置,同一项目内多台伺服轴或步进轴均可直接调用同一FB实例,免去重复编写底层逻辑,显著减少编程与调试时间,尤其适合装配线定位、简易机械手、送料机构等中小型自动化设备开发场景。压缩包共10个文件,整包约994KB,以6张实操截图、1份HTML说明文档和1份带关键注释的TXT源码为主,另含inscode工程文件;截图覆盖调用示例、引脚定义、参数设置及运行效果,源码存放于sorce目录下,便于对照代码理解功能块封装思路。目前已有29人学习,适合需要快速搭建多轴定位控制系统的PLC工程师参考。 设备上要同时管几根伺服轴,回原、点动、定位都要做,以前的程序全是梯形图,占屏不说,换一台设备改地址改到怀疑人生。后来我用三菱FX5U系列PLC的ST语言把整套轴控制逻辑封装成了可复用的轴控制功能块,支持原点回归、点动和定位三种动作,一个功能块实例化一次就是一根轴,项目里新增一根轴就复制一行调用代码。这篇文章就把这个功能块的设计思路、状态机、ST实现细节和调试经验完整拆一遍,适合正在用FX5U做单轴或多轴伺服控制的工程师,也适合想从梯形图转结构化编程的朋友。
1. 为什么我把轴控逻辑从梯形图改成ST封装
1.1 梯形图做轴控制的三个硬伤
先声明一下,我不是说梯形图不行,FX5U用梯形图做简单启停、互锁完全没有问题。但轴控制这种东西,放到梯形图里画,时间长了真的会乱。
第一个痛点是状态管理太散。点动、回原、定位天然是互斥动作,一张设备操作面板上同时有回原按钮、正反转点动按钮、定位启动按钮,梯形图里要表达“当前正在回原,所以点动无效”,通常就是一堆M继电器互锁。动作一多,很容易出现两个状态同时为ON的竞争情况。比如回原还没走完,操作工手快按了正转点动,程序到底响应还是不响应,全看互锁写没写全。
第二个痛点是重复代码多。同一条轴控逻辑,放到1号轴能用,放到2号轴就得整体复制一遍,然后把里面的软元件号全部改掉。复制到第7、8根轴的时候,发现一个逻辑漏洞,要把七八个地方全部改一遍,漏任何一个都是隐患。而且这样的复制代码,地址分散,换个人接手根本不敢动。
第三个痛点是参数管理零散。定位指令、当前进给值、偏差计数器清零、DOG信号、运行中标志,这些软元件在梯形图里是东一个西一个的,每根轴都有一套。你越往后越会发现,真正难的不是那一段运动程序,而是让轴在整个生命周期里始终保持一致的状态、不互相干扰。
1.2 为什么选ST语言,FX5U又凭什么能这么干
FX5U是三菱MELSEC iQ-F系列的机型,CPU本体自带4轴脉冲定位,回原、点动、相对定位、绝对定位这些动作指令都是现成的。同时GX Works3里支持ST语言编程,也可以把一段逻辑封装成功能块(FB),在主程序里实例化调用。
CASE状态机、IF条件、结构化参数,这些ST语言特性天然适合描述轴控制这种带时序、带状态的任务。我可以用一个状态变量把回原、点动、定位全部锁进同一套互斥逻辑里,任何请求先过状态判断,不是当前状态该干的事全部不理。这个优点在梯形图里要绕很多弯才能实现。
而且ST功能块还有一个隐藏好处:调试的时候可以直接把内部状态值映射到HMI上。现场说轴不动了,看一眼状态码就知道它卡在回原中、报警中还是等使能,不用拿电脑在线一点一点查软元件。
2. 先定边界再写代码:功能块接口设计
2.1 输入输出信号如何分层
写功能块第一步不是写逻辑,而是想清楚“外面要给它什么、它要往外报什么”。这个FB的接口我大致分成三层。
输入层是请求和参数:主使能bEnable、回原触发bStartHome、正转点动bJogPlus、反转点动bJogMinus、绝对定位bStartAbs、相对定位bStartRel、目标位置rTargetPos、运行速度rSpeed、加减速时间rAccTime/rDecTime,还有一根轴的完整参数结构体stAxisParam。
输出层是状态和诊断:bBusy运行中、bDone定位完成、bHomeDone回原完成、eState当前状态编号、eErrorCode错误码。其中eState我强烈建议你接到HMI上,调试时一眼就能看穿轴到底卡在哪一步。
这里有个设计细节要说明:bDone和bHomeDone不能混用。定位完成只代表本次运动走完了,不代表轴已经建立原点基准;回原完成才代表轴有了绝对坐标的前提。如果你拿bDone去当回原成功的标志,后续做绝对定位一定会出问题。
2.2 状态变量是控制互斥的命脉
FB内部我维护一个模式状态eState,取值大概是这几个:
0 空闲待机;1 回原中;2 回原完成;3 定位执行中;4 点动中;5 停止中;6 报警。
整个FB的调度核心就是这一个变量。任何动作请求进来,先判断当前eState允不允许进入新动作。比如定位只能在0或2状态下启动,回原只能在0状态下启动,点动只在0或2状态下有效。不在允许范围内的请求,FB直接忽略,也可以顺手置一个错误码。
这种集中式状态判断,最大价值就是把设备上五花八门的操作按钮、HMI按钮、程序内部请求全部收口到一个地方。不管外面怎么乱按,FB内部只有状态机说了算,相互打架的场景从根本上被消灭。
2.3 参数结构体让实例化成本大幅降低
如果FB的输入是十几个零散变量,调用时会写得很长,传参顺序错了还不好查。我把每根轴的参数打包成结构体ST_AXIS_PARAM,里面放回原模式、回原方向、回原快速速度、爬行速度、点动速度、定位速度、加减速时间、每毫米脉冲数这些字段。
调用FB时只传入一个结构体实例,代码马上清爽很多。同一台设备上轴1和轴2参数不同,就在调用处分别声明两个结构体实例,把表填好。后续想加功能,比如速度倍率、位置补偿,往结构体里加字段就行,不用改动调用处的所有变量名。
这个设计还有个额外好处,就是方便做配方切换。一台设备可能做几种产品,每种产品的行程、速度都不一样。把ST_AXIS_PARAM做成数组,按配方号索引,切换配方时把对应元素赋给当前实例的输入结构体,控制逻辑完全不用动。
3. 原点回归:最容易出问题也最需要耐心的动作
3.1 机械Dog回原的完整过程
原点回归看着简单,按一下按钮轴往回走,碰到限位开关停住,完事。实际上不是这么回事。机械挡块本身有加工误差和安装误差,如果直接靠挡块上升沿停止,每次回完原的位置可能差出好几个毫米。
标准的机械Dog回原过程要分几步走:先按设置的方向高速去找Dog,Dog信号接通后,速度降下来,改成爬行速度继续往同方向走,等Dog信号断开,或者等伺服Z相脉冲触发时,执行偏差计数器清零,把当前位置设成0。这个流程可以把原点精度收敛到伺服编码器的一个脉冲当量级别,而不是挡块的机械精度级别。
我在FB里把回原拆成四个阶段:启动条件检查、触发回原动作、等等回原完成信号、回原完成置位。启动条件检查里最重要的一件事是确认“当前状态允许回原”,并且回原请求是一个沿信号,不是电平信号。如果请求始终为ON,状态机又没有沿检测,就会出现扫描周期反复触发回原的诡异现象。
3.2 回原完成信号为什么不能直接当“轴已就绪”
现场最常见的坑,是回原完成后bHomeDone一直保持ON,后面绝对定位也就一直有权限执行。但如果中间有人用手动方式推过轴,哪怕只推了0.5毫米,轴的实际坐标已经偏离,bHomeDone却还是ON,这时候做绝对定位,位置基准就是错的,严重情况直接撞机。
解决办法是在FB内部增加一个“轴已同步”标志位。只要FB检测到任何手动动作,比如点动按钮按下、手动脉冲输入,就把这个标志清零。只有完整走完一次回原流程,标志才重新置为ON。绝对定位在发出之前,必须同时检查bHomeDone和这个同步标志,两者都为ON才放行,否则视为非法请求。
回原过程中还有一个显示问题要处理。回原启动时,当前位置会先往反方向跑,屏幕上数值跳动是正常的,但千万别在HMI脚本里把这个瞬时值写回到定位参数区。我见过有人回原还没结束,触摸屏上的当前坐标就被写回了配方,结果坐标基准一次比一次偏,最后设备直接跑飞。
4. 点动和定位在同一个状态机里如何调度
4.1 点动的假死问题和复位处理
点动看着最简单,按钮按多久轴动多久,松手就停。但放到功能块里,它其实最麻烦。麻烦在哪呢?FX5U的点动指令是一直接通的,按钮按多久它就输出多久,一旦在FB内部切换到其他状态,或者脉冲指令还没结束就又被别的地方触发,很容易出现“点动停不下来”或者“状态已经切走,脉冲还在跑”的假死情况。
我的做法是把点动也纳入状态机统一调度。只有eState是0或2时才允许进入点动状态,进入之后,只要JogPlus和JogMinus同时为OFF,或者bStop有效,就退出点动状态。这里有个关键点:点动过程中如果来了定位请求,不能立刻切状态,必须先把点动停止,等脉冲输出通道完全空闲下来,再走定位启动流程。中间这几十毫秒的间隙不会影响实际工艺,但会让定位启动条件始终干净、可预测。
另外,现场按钮的抖动问题必须处理。伺服点动按钮如果开关触点老化或接线不良,可能出现按一次松手,轴却一直自己跑的情况。我在FB内部把按钮信号做了一层延边处理,用一个局部变量保存上一个周期的状态,再比较当前周期,生成单周期触发脉冲。这样即使按钮被长时间按住,也只是保持点动状态,不会反复触发启动逻辑。
4.2 绝对定位、相对定位的执行门槛与完成信号锁存
定位是FB的第三个动作面,我支持绝对和相对两种方式。相对定位只基于当前进给值做偏移,不依赖原点,所以只要状态机允许就可以执行。绝对定位则必须基于原点坐标,FB里明确规定:如果“轴已同步”标志是OFF,而请求是绝对定位,直接置“需要先回原”的错误码,不执行。
定位真正启动时,FB内部要做的事比较多:把目标位置、速度、加减速时间写入轴参数区,触发定位启动指令,然后等待定位完成标志。这里有一个工程细节要注意:FX5U内置定位的完成信号,在定位结束时可能只保持一个扫描周期的ON,尤其走定位表格连续执行模式时,主程序扫描周期稍微长一点,HMI和上位机就看不到这个完成信号。
所以我在FB内部加了一个完成信号锁存机制:当检测到定位完成标志的上升沿后,把内部的bDoneLatch置ON,保持至少2到3个扫描周期,同时对外输出bDone。这样不管上位机轮询快慢,都能稳定抓到定位完成事件。锁存标志在下次启动定位前统一复位,避免残留影响下次判断。
5. 多轴复用:实例化方式、轴号映射与上层同步
5.1 一个FB实例化四根轴
功能块最舒服的使用方式,就是在主程序里声明几个实例,然后分别调用。假设这个FB名字叫FB_AxisControl,在主程序里先声明fbAxis1 : FB_AxisControl;和fbAxis2 : FB_AxisControl;,然后ST里写:
fbAxis1( bEnable := bServoReady1, bStartHome := bHomeBtn1, bJogPlus := bJogP1, bJogMinus := bJogN1, bStartAbs := bPosAbs1, rTargetPos := rTargetPos1, rSpeed := rSpeed1, stAxisParam := stParam1 );复制这份调用,把实例名和参数换成轴2的对应变量,第二根轴就有了。从“复制十屏梯形图”到“复制三五行调用”,这种改进带来的维护效率提升是实打实的。如果项目有四个轴,就声明fbAxis2、fbAxis3、fbAxis4,它们各自独立运行,互不干扰。
5.2 轴号与系统软元件映射要集中处理
FB内部要访问定位指令对应的系统软元件,比如当前进给值、定位中标志、回原完成标志。问题是,这些软元件是分轴的,我要让同一个FB逻辑在实例化后自动指向不同轴,怎么办?
我一般在FB内部放一个轴号变量iAxisNo,在初始化阶段用一个CASE语句,把不同轴号对应的系统软元件全部映射到FB内部的局部变量。比如轴号1时读第1轴的当前进给值区域,轴号2时读第2轴的对应区域。这里要注意,ST语言不支持用字符串拼软元件号,PLC软元件号在编译期就确定了,不能动态寻址。所以老老实实做映射表,或者用系统自带的轴结构体索引,关键是提前设计,别到现场才改。
还有一点,换PLC型号时,软元件映射也可能跟着变。把映射集中在FB头部处理,后面换CPU或者改轴号,就只改这一段,FB核心逻辑不用动。
5.3 多轴同步逻辑不能压在FB内部
FB只负责单轴执行,多轴同步和工艺互锁要在上层程序里做。比如双轴龙门结构,要求轴1和轴2同时启动、同时到达指定位置,这个协调逻辑放在单个FB内部是没有意义的,必须由主程序统一给两个FB同时发定位请求,再监视两个轴的bBusy标志和实际位置做同步偏差判断。
所以我在FB里把定位请求做成电平触发而不是内部锁存。主程序可以在同一个扫描周期内把两个轴的请求都置为ON,两个FB同步进入定位状态。如果同步偏差超过设定值,主程序统一给两个轴发bStop,大家一起停下来。这样FB保持单轴执行器的纯粹性,上层工艺逻辑想要多灵活就有多灵活。
6. 我能想到的调试经验和常见坑
6.1 先仿真状态机,再上实机
这个FB写完以后,第一步不是在设备上试,而是用GX Works3的仿真器先把状态机跑通。仿真时没有真实伺服反馈,重点看状态跳转和完成信号,不看实际脉冲。先把每个请求触发后eState的变化记录下来,确认只有预期状态被激活、其他状态保持不动,再上电做实机测试。这一步能省掉现场大量调参时间。很多人跳过仿真直接上设备,中途改一处逻辑,回原参数和定位参数来回调,半天就折腾没了。
6.2 回原和定位共用一个通道时,请求必须串行
如果回原、点动、定位走的是同一个内置定位通道,那么三者串行是必然的。最容易踩的坑是:回原还没完成就发了绝对定位请求,或者定位执行中又按了回原。我在FB内部用一个“通道占用”标志来防止这个问题。任何动作占用脉冲输出通道后,都把这个标志置ON,其他动作请求在标志为ON时统一忽略并返回占用错误码。这个标志不是物理信号,就是状态机的忙标志,但它保证了整个FB在同一时刻只干一件事。
6.3 伺服READY没到位,定位指令会“假启动”
最后一个现场经验,是我调试里遇到最多的。FX5U发定位脉冲之前,一定要检查伺服驱动器的READY信号和使能信号。如果伺服还没准备好,PLC却已经触发了定位指令,有的驱动器会把它当无效指令丢掉,但PLC侧可能已经认为执行完成,于是定位逻辑莫名其妙中断,而且不报错。
我在FB里加了一段处理:启动定位前先读取伺服READY状态,确认READY为ON后,再等待2到3个扫描周期,确认脉冲输出已经真正启动,才算定位开始。如果READY没到,就置一个“伺服未就绪”错误码,不发启动指令。就这么一段逻辑,帮我挡掉了好几次现场“偶发性定位失败”,排查起来能少走很多弯路。
最后再分享一个实战习惯
每台设备我都会在HMI的调试页面把FB的eState、bBusy、bHomeDone、eErrorCode全部显示出来,做成一行诊断状态条。现场打电话过来说轴不动了,我先问一句“状态条显示什么”,一半问题当场就能定位。状态码如果显示报警,去查错误码;显示回原中,多半是回原超时或者DOG信号没回来;显示点动中,可能就是按钮卡住了。这个FB我用了几年,从单轴平推到四轴联动的小专机都在复用,状态机核心逻辑基本没大动过,变的就是参数结构和报警分支。如果你的设备轴数多、逻辑散,建议也动手写一个属于自己的轴控FB,一次封装,长期受益。
本文还有配套的精品资源,点击获取