ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

汇川H5U程序框架搭建指南:任务配置、变量规划与轴控制

汇川H5U程序框架搭建指南:任务配置、变量规划与轴控制 这两年用汇川H5U做了几条产线的控制改造说实话第一次在InoProShop里看到那个工程树时我愣了一下——这跟以前用日系PLC的习惯完全不一样。H5U是汇川面向中端设备控制推出的PLC支持多任务、多轴同步和EtherCAT总线编程环境基于CODESYS既可以用ST、梯形图也可以混合使用IEC 61131-3里的各种编程语言。很多从三菱、西门子转过来的朋友最容易卡在“程序框架”这四个字上不是不会写指令而是不知道整套程序该怎么组织任务怎么分配变量怎么管理轴怎么挂进去才不乱。这篇文章想分享的就是我在H5U上沉淀下来的一套可复用的程序框架包括任务配置、变量规划、状态机、轴控制和通信样例希望能给正在搭H5U项目框架的人一点参考。1. 从InoProShop工程树搭起H5U程序框架的分层设计1.1 先看工程树一个H5U项目里到底有哪些层我接手第一台H5U设备时第一件事不是写逻辑而是把默认生成的工程树完整看了一遍。H5U的编程软件InoProShop里项目结构大体包含设备配置、应用层、全局变量表、POU程序组织单元、任务配置几个部分。如果你做过CODESYS项目这套结构会非常眼熟如果你是从传统PLC转过来的那就需要先接受一个观念转变程序不是平铺在一个用户程序段里的而是分文件、分任务、分函数块组织的。工程树里的“设备配置”对应硬件组态包括CPU本体、扩展模块、EtherCAT从站、串口等“应用”这个节点下才是我们写程序的地方全局变量、POU、任务都挂在这里。POU里可以放程序PRG、函数块FB、函数FUN三种东西。我习惯的做法是程序只放调度逻辑函数块放设备动作函数放计算和转换。这样做的好处是后面改某一台设备的动作时不用在几千行梯形图里来回找。1.2 我的四层框架划分接口层、逻辑层、驱动层、硬件层在H5U上试过几个项目之后我把框架稳定成了四层这也是我自己搭建H5U程序时的总纲硬件层直接跟物理输入输出绑定的部分。比如伺服轴的轴变量、EtherCAT从站的输入输出映射、本体的DI/DO通道。驱动层把具体硬件的动作封装成函数块。比如“气缸动作”“电机启停”“轴移动”上层调用时只给目标值不关心底层寄存器。逻辑层设备工艺状态机、流程步骤、联锁条件。这一层是设备的大脑也是改的最多的地方。接口层负责和HMI、MES、上位机通讯的变量和功能块比如按钮、模式切换、配方参数、报警文本。分层有什么实际价值我举个例子。产线改造时常会遇到“把气缸A的到位传感器从X0改到X7”这种需求。如果程序里到处都是%IX0.0这种物理地址改起来得全局搜索如果用了分层框架只需要改硬件映射或者驱动层一个函数块内部逻辑层和HMI层根本不用动。这就是框架的意义——把变化隔离在某一层里。另外一个容易忽略的点函数块内部不要直接访问全局变量。我在H5U上吃过这个亏刚开始图省事FB里直接读写g_bStartBtn后来发现逻辑层一调整条件FB就没法独立测试了。后来我统一改成FB的输入输出接口变量外部逻辑“接线”进来FB本身保持独立。这样单个FB可以在模拟环境里单独验证排查问题时的范围一下就缩小了。2. 任务配置与扫描周期程序框架的“心跳”怎么设2.1 周期任务怎么定才不容易出问题H5U的Task配置常常是新手最容易忽视、老手最容易踩坑的地方。InoProShop里默认会生成一个MainTask周期我见过很多人不管直接默认10ms或者干脆空着。但一台设备如果把轴控制、普通逻辑、通信全部放在同一个10ms任务里一旦程序体量上来扫描时间超出周期轻则设备响应变慢重则触发看门狗报警。我给H5U项目分配任务时通常分成三档快速任务2ms或者1ms放轴控制、急停相关、高速输入处理。主任务5ms或10ms放工艺逻辑、状态机、常规IO扫描。慢任务50ms或100ms放通信轮询、非关键数据采集、HMI数据刷新。周期值具体定多少要看CPU负荷率但框架一定是分层的。我见过一个设备把伺服使能和普通气缸放在同一个任务里结果气缸阀切换时网络抖动影响了轴跟随精度。分开之后问题基本消失。这里有个经验轴控制相关FB尽量放在最快的周期任务里但不是越快越好太快的任务会把CPU占满留给逻辑的余量就少了。2.2 多任务协作时的优先级与共享变量处理多任务编程的关键不是任务数量多而是任务之间的数据交换要可控。H5U基于CODESYS任务之间可以通过全局变量共享数据但如果你在快速任务里写g_bAxisBusy主任务里也写同一个变量就会出现时序错位甚至偶尔看到“灵异”现象。我的做法是给跨任务变量建立“数据握手区”。比如轴的状态用一组全局变量g_axis_State写操作只由快速任务完成主任务只读。反过来主任务里的启动命令通过置位一个布尔量交给快速任务消费快速任务处理完后再复位。这样数据流向是单向的不会两边同时写。任务优先级也要规划好。H5U里的周期任务虽然有优先级设置但别把优先级调得太极端。我通常把快速任务优先级设最高主任务其次通信类放最低或单独事件触发。如果通信任务占用太多时间会影响主任务的节拍这种情况下我宁可使通信慢一点也要保证逻辑稳定。还有一个小技巧利用H5U的程序实例化机制把同一套设备逻辑做成多个FB实例。比如设备有4台相同的加热工位我写一个FB_HeatingStation在主任务里调用4次分别接不同的IO变量和参数。这样代码量能减少一大半而且修改工艺时只需要改一个FB。3. 变量规划、保持区与IO映射框架的底座工程3.1 全局变量命名与分组规范变量命名这件事看起来琐碎其实决定了一个H5U项目后期好不好维护。我在汇川H5U上维护过一个项目接手时变量名是a1、a2、b1这种局部变量里有大段魔数注释改起来非常痛苦。所以现在我对变量命名有强制习惯。全局变量统一用前缀区分数据类型和来源g_b布尔量比如g_bEmergencyg_i整数比如g_iRecipeNog_r实数比如g_rTargetPosg_ast_结构体数组比如g_ast_Cylinder[1..8]g_x物理输入输出点比如g_xIn_Clamp全局变量表按功能分区放置IO区、轴区、通信区、配方区、报警区各自独立成表。汇川的全局变量列表支持分组折叠用起来还算顺手关键是养成归组的习惯不然变量一多全挤在一起找变量比写程序还费时间。3.2 保持区变量、默认值与首次上电的坑H5U的变量有保持属性可以做到掉电保持。这个功能好用但坑也多。我踩过最典型的一个坑把工艺配方、轴当前位置、设备状态全部设成保持变量结果设备第一次上电时保持区里是上一次断电时的数据可能是因为之前手动调试时留下的中间值设备直接跳进了一个“不该进入”的状态差点撞机。现在的做法是保持区只放真正需要掉电保存的数据比如配方参数、计数器累计值、轴绝对位置。设备状态、执行步骤号、临时标志这些坚决不设保持每次上电都从初始化状态开始。如果你确实需要记住“断电前停在哪个步骤”我的建议是单独用一个保持变量存步骤号并且在程序启动时做合法性检查判断当前步骤参数是否在合理范围不合理就强制回待机再手动恢复。另外一个关于首次上电的细节程序启动时要给保持变量赋默认值。H5U的全局变量在声明时可以写初始值但有些默认值只有在程序运行时才知道比如伺服使能之前的位置。我的框架里有个FB_InitAll在主任务第一次扫描时执行把所有非保持变量和需要校验的保持变量刷一遍默认值。初始化完成后置位一个g_bInitDone逻辑层再往下走。3.3 IO映射为什么要和逻辑变量分离传统PLC里直接写X0、Y1很常见但在H5U这种基于CODESYS的平台里我更推荐用符号变量做软地址再通过映射关系绑到物理IO上。InoProShop里IO映射界面能够把物理输入点对应到内部变量比如把X0.0映射到g_xIn_Start程序里只认g_xIn_Start。这样做最大的收益是换点方便。设备发货到现场之后因为接线问题要换IO点你只需要改一处映射程序不用动。还有一个隐藏好处程序的可读性和可移植性大大提升。g_xIn_Start一看就知道是启动按钮而不是某个抽象地址。IO映射还有一个细节值得注意不要直接在物理输入变量上做逻辑判断尤其是按钮、限位这类信号建议在驱动层做一次滤波或者边沿同步。H5U本体输入有滤波器设置但程序里再处理一次更稳。比如启动按钮我习惯用R_TRIG在逻辑层取上升沿避免因为扫描时序不一致造成误触发。4. 轴控制框架实例EtherCAT配置与ST运动控制代码4.1 添加EtherCAT轴从扫描到参数整理的流程H5U接汇川伺服最常用的方式是EtherCAT。第一次配置时我差点以为整个系统坏了——总线扫描扫不到伺服后来发现是没有把从站状态切换到OP。EtherCAT从站要经过INIT、PREOP、SAFEOP、OP这几个状态InoProShop里如果总线没有进入OP模式轴使能根本不会成功。这个排查流程一定要记住先看总线状态再看轴配置最后才看逻辑。轴参数里最基础的是电子齿轮比和单位换算。H5U的轴组态界面可以设置每转脉冲数、丝杆螺距、减速比设完之后轴变量的位置单位就是用户单位比如mm。这一步别跳过我曾经偷懒直接按脉冲数写位置后面每根轴都要换算最后回归起来非常痛苦。软件限位也是我建议在框架里提前做掉的。不要只靠伺服驱动器的硬限位程序里利用H5U的轴功能块可以配置软件正负限位。我的习惯是轴初始化之后第一时间使能软件限位并且在HMI上留出修改参数的入口方便现场根据工况微调。4.2 一套可直接套用的轴控制ST代码下面这段ST代码是我在H5U项目里常用的轴控制骨架包含使能、绝对定位、相对定位和速度运动。汇川的H5U支持PLCopen运动控制库函数块名和标准一致。// 轴使能控制调用MC_Power MC_Power_0.Execute : bPowerOn; MC_Power_0.bRegulatorOn : bPowerOn; MC_Power_0.bDriveStart : bPowerOn; MC_Power_0.Axis : Axis_1; MC_Power_0(); // 绝对定位到指定位置 MC_MoveAbsolute_0.Execute : bMoveAbs; MC_MoveAbsolute_0.Axis : Axis_1; MC_MoveAbsolute_0.Position : rTargetPos; // 单位是用户单位mm MC_MoveAbsolute_0.Velocity : rMoveVel; MC_MoveAbsolute_0.Acceleration : rMoveAcc; MC_MoveAbsolute_0.Deceleration : rMoveDec; MC_MoveAbsolute_0.Jerk : 0; MC_MoveAbsolute_0(); // 相对定位当前位置基础上偏移 MC_MoveRelative_0.Execute : bMoveRel; MC_MoveRelative_0.Axis : Axis_1; MC_MoveRelative_0.Distance : rOffDistance; MC_MoveRelative_0.Velocity : rMoveVel; MC_MoveRelative_0(); // 速度运动用于手轮/寸动 MC_MoveVelocity_0.Execute : bMoveVel; MC_MoveVelocity_0.Axis : Axis_1; MC_MoveVelocity_0.Velocity : rVelCmd; MC_MoveVelocity_0();这些功能块不是调用一下就完事的执行完还要看Done、Busy、Error这几个输出。我的框架里每个轴都带一个状态字把Busy、Done、CommandAborted、Error的状态汇总到全局变量逻辑层根据状态字决定下一步动作。4.3 回原点与软限位两个最容易疏忽的设置回原点是每个用伺服的项目都躲不掉的事。H5U的运动控制库里提供了MC_Home可以实现多种回零模式。我一般喜欢用限位开关加Z脉冲找原点的方式可靠性比较高。回原点的执行顺序要注意让轴先以较慢速度朝限位方向找碰到限位后反向找Z脉冲最终停在固定位置。回原点过程里禁掉软件限位否则会在找原点过程中触发限位报警。软限位我在框架里是这样处理的每个轴结构体里带rSoftLimitPos和rSoftLimitNeg在轴使能后、任何运动指令之前检查这两个值如果目标位置越界就直接禁止执行并抛出报警。这样做比完全依赖运动控制库内部的限位更直观也方便HMI做参数约束。还有一个实际经验H5U断电后轴的“绝对位置”如果用的是增量编码器断电再上电之后必须重新回原点。如果用的是绝对值编码器也要检查H5U的轴配置里是否使能了绝对值处理。我就遇到过一次改了绝对值伺服但没改程序结果断电重启后设备认为当前位置还是断电前的位置实际已经被人推走了后续定位全乱。解决办法是上电后做一次位置校验确认偏差在允许范围内才继续自动流程。5. 状态机、通信与报警把设备逻辑组织成可维护的框架5.1 用CASE语句搭一个通用设备状态机设备逻辑是H5U程序框架里最容易写乱的部分。如果全是M0、M1这种中间继电器程序超过几百行就基本没法看了。我在H5U上统一用ST语言写状态机核心就是一个CASE结构。CASE byStep OF 0: // 待机 IF g_bStart AND g_bReady THEN byStep : 10; END_IF 10: // 初始化动作 bInitCmd : TRUE; IF bInitDone THEN byStep : 20; END_IF 20: // 自动运行 bAutoRun : TRUE; IF bCycleDone THEN byStep : 0; ELSIF g_bStop THEN byStep : 30; END_IF 30: // 暂停等待 bAutoRun : FALSE; IF g_bStart THEN byStep : 20; END_IF END_CASE;状态编号按十位、百位分组比如0-9是待机相关10-29是初始化30-49是自动流程50-79是报警处理。这样看到步骤号大概就知道设备在干什么。状态机里只做流程判断不写具体驱动动作具体动作调用函数块接口。这个习惯后来帮我省了很大的调试时间因为状态机跑飞的时候只需要看步骤号不用去猜哪一行指令出了问题。状态机之外我还会留一个byStep写入“当前位置”的功能块实时把步骤号写到HMI。这等于给设备装了一个“进度条”对现场调试和后期维护特别有用。5.2 通信功能块的框架化调用Modbus读写不散落各处H5U的串口和以太网都支持Modbus通信。通信这块最常见的框架问题就是程序里到处都有读寄存器的代码数据上来后直接使用结果通信卡一下设备逻辑就跟着抖动。我的做法是把所有外部设备通信封装成独立的通信函数块。比如一个温度控制器我只在慢任务里调用一次FB_ReadTemp这个FB内部负责Modbus读保持寄存器、数据校验、超时判断然后输出一个温度值和通信状态。逻辑层只用这两个结果完全不关心底层协议。Modbus功能码上读取保持寄存器用功能码03写入单个寄存器用06写入多个寄存器用16。如果你用的是汇川H5U的Modbus RTU主站记得要配套设置从站地址、波特率、数据格式。我在现场遇到过一次“能读但读出来是乱码”的问题查了半天是数据格式不匹配从站是8E1主站设成了8N1改成后立刻正常。通信超时必须在框架层面处理得保守一点。我习惯给每个通信FB设一个超时时间比如200ms连续3次超时就置位通信故障同时保留最后一次有效数据不更新。这样即使通信瞬间出错也不会让设备立刻乱动而是先停在安全状态报警等人处理。5.3 报警字与故障追溯给框架加上“病历本”报警处理最容易犯的错是只给一个“有报警”的布尔量具体什么事让电工去查触摸屏历史记录。我的H5U框架里专门设计了一组分页报警字。每个函数块可以产生多个报警码逻辑层把报警码汇总到g_iAlarmCode再配合报警时间、报警次数记录到保持区。报警码的设计也有讲究。我习惯用两位数分组比如10xx是气动相关20xx是轴相关30xx是通信相关40xx是工艺条件不满足。这样操作工报“20几”的警维修人员大致就能判断是轴的问题不用每次翻手册。报警产生时的关键参数也可以顺带记录一份比如轴报位置、通信超时次数、当前步骤号这些信息对事后排查特别有帮助。最后再分享一个小技巧调试H5U程序时我强烈建议在全局变量表里放几个“调试开关”变量不用时置0需要调试时通过HMI的隐藏页面修改。比如强制跳过某个报警、单独使能某根轴、切换手动/自动模式。这些开关能让你在现场少掉很多头发。但记住一条底线所有调试开关在设备正常生产前必须全部关闭并且程序里要有报警提示防止有人开着调试开关直接跑自动造成危险。我个人在实际操作中的体会是H5U这套平台的上手难度不在指令而在思维方式。从梯形图到CODESYS的结构化编程需要一点时间适应但一旦把任务、变量、函数块、状态机这套框架搭顺了后面做同类设备的速度会快很多。框架这个东西别指望一次到位每做一个项目都往里面填一点“坑位”等沉淀到第二三个项目你会发现自己写的新设备程序越来越省力。
返回列表