多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

三轴码垛PLC仿真:FactoryIO场景搭建与博图V16状态机实现

三轴码垛PLC仿真:FactoryIO场景搭建与博图V16状态机实现 说起工控入门我脑子里最先蹦出来的不是点亮一个电机正转反转也不是Modbus轮询读取几个寄存器而是一整套能“从头到尾走完流程”的小项目。三轴码垛仿真就是这么个对象它既没有高温高压这种让人手心冒汗的工业危险也没有PID整定那种调三天都稳不住的玄学但它把位置控制、传感器联锁、流程状态管理、报警处理这些工控日常全塞进来了。这次我用FactoryIO搭了一个立体仓库的仿真场景再用博图V16TIA Portal V16写PLC程序把取料、搬运、码放整套逻辑完整跑了一遍。整个过程走下来我最大的感受是三轴码垛仿真真正值钱的地方不在“动”而在“什么时候能动、什么时候必须停、停了以后怎么接着干”。今天这篇就把我整个实操过程拆开揉碎从场景搭建设计、PLC程序骨架到联调时踩进去的坑都记录下来。准备入坑工控的朋友可以当项目复现参考已经在做设备调试的同行也可以看看仿真和实物之间差的那些“细账”我是怎么补的。1. 为什么要搞三轴码垛仿真——这题考的不是“动”是“怎么动才安全”1.1 码垛动作的控制复杂度正好卡在入门门槛上先说说为什么很多人把三轴码垛当作入行练手项目的首选。你去看一套实际的立体仓库设备本体可能有一台堆垛机或者龙门式码垛机外加输送线、托盘位、货架库位一大堆传感器和执行器搅在一起。但真正拆到单次搬运任务逻辑其实就是一句话从A点把箱子抓起来放到B点放正。可就这么一句话落在控制上要拆成“X轴走到取料上方、Z轴下降到抓取高度、抓手闭合、Z轴抬升到安全高度、X/Y轴联动走到目标库位、Z轴再下降、抓手松开、Z轴回安全高度”。每一次动作切换都必须建立在“上一个动作确实完成”的前提下这就是典型的顺序控制。而顺序控制恰恰是PLC最擅长、工控日常最高频的内容。更进一步三轴联动要考虑路径上会不会撞到货架、目标位置有没有被占、抓手上有没有料、码放层数是否超限这又牵扯到安全联锁和报警逻辑。难度不高不低覆盖面还全比单纯跑个流水线或者启停一台变频器能练出来的东西多得多。1.2 用FactoryIO仿真正是为了把“工艺思维”练出来有人会问直接买套二手设备练不是更真实成本是最大的门槛而且电气调试初期有大量时间花在换线、查保险丝、处理机械卡滞上真正用来练控制逻辑的时间反而被压缩了。FactoryIO这类仿真软件的价值就在这里它自带物理引擎传感器会抖动传送带上的箱子会滑动码放位置偏了箱子会倒给了你接近现场的“体感反馈”。但和真实设备相比它又不会因为程序写错就烧掉一个伺服驱动器或者撞坏一个丝杠模组非常适合大胆试错。这次我选择的场景是立体仓库的码垛工艺段设备构型是经典的桁架式结构X轴做长距离水平移动Y轴负责货架深度方向的伸缩Z轴承担升降末端是一个气动抓手。场景文件定下来之后我直接用博图V16建了一个S7-1200的项目来控这套设备。FactoryIO那边支持多种通信协议我最终走的是S7-PLCSIM仿真接口把博图里的仿真PLC和FactoryIO场景连接起来。这种“软PLC虚拟场景”的组合有个隐形好处变量表、程序块、监控表全是博图原生的操作习惯和实际调试完全一致练出来的迁移成本很低。2. 搭建立体仓库仿真场景——先把设备和坐标系统搞明白2.1 FactoryIO里的设备构成与传感器布局打开FactoryIO选择“立体仓库/码垛”这一类场景之后第一件事不是急着连线而是把场景里的执行器和传感器全部盘点一遍。我用的场景大概包含这么几个部分设备区域主要部件作用入库输送线皮带线、入库到位传感器把待码垛的箱子运到抓取工位抓取工位对中挡块、到位检测传感器保证箱子停在固定抓取点码垛机本体X轴电机、Y轴电机、Z轴电机、抓手开闭实现空间三轴运动与取放立体货架多列多层库位、库位占位传感器存放箱子的目标区域出库侧出库输送线部分场景带用于后续取料流程扩展场景里每个传感器在FactoryIO中都对应一个内部地址需要在通信配置里映射成PLC的输入变量。别小看这份盘点工作很多人在FactoryIO里跑不起来就是因为漏看了某个传感器程序流程一直卡在等待信号那一步。2.2 坐标系设定和库位规划是绕不开的第一步码垛程序的第一步是确定坐标原点。这次我把码垛机的机械原点设在了货架最左侧前方、Z轴最高位附近。也就是说X轴坐标从最左端开始增长Y轴从货架外侧向内侧增长Z轴从上往下计数。有了这个约定所有目标点就都变成了一组组坐标数值程序里只需要查表取坐标就行。立体仓库库位我规划成3排×4列×3层一共24个库位。注意实际场景中不是每个库位都能无脑放箱子还要考虑托盘的物理尺寸和码垛机的行程边界。我这里每排货架的宽度是200毫米每层高度是150毫米抓手在Z轴降到最低时要留出至少10毫米的脱扣间隙。这些尺寸看起来琐碎但它们直接决定了坐标表里每个数值的合理范围也是后面排查“为什么Z轴下降过深把箱子压扁”这类问题的根源。2.3 FactoryIO配置PLC通信接口的完整步骤FactoryIO与博图V16之间的联机方式取决于FactoryIO版本里支持的驱动接口。常见的有S7-PLCSIM、OPC UA和Modbus TCP几类。我这次选的是S7-PLCSIM的方式整体配置可以分三步走。第一步在博图V16里建好S7-1200项目并启用仿真。PLC的IP地址、子网掩码这些不需要刻意设置因为PLCSIM作为本机软仿真和外部通信走的是虚拟网卡。但需要注意博图的仿真PLC必须先处于运行状态FactoryIO侧才能连接成功顺序不能反。第二步在FactoryIO的“驱动”设置中选择对应PLC类型并指定连接参数。这里要填的PLC地址和机架/插槽号需要和你在博图里组态的硬件保持一致大多数S7-1200默认是机架0、插槽1。第三步完成通信测试。如果变量列表中的信号全部变成绿色联通状态说明PLC和FactoryIO已经握手成功。这个步骤里最容易翻车的点是PLCSIM的版本。博图V16对应的是S7-PLCSIM V16如果电脑里装了博图V15或V17的仿真器FactoryIO那边根本识别不到。我在第一次联机时也遇到过一次“驱动连接超时”排查了一圈后发现是开着V15的PLCSIM进程没关干净两个版本的仿真服务抢端口。把所有PLCSIM进程结束后重新启动V16问题就消失了。3. PLC变量表设计——把场景信号映射到博图V16工程里3.1 输入输出信号的地址规划原则博图V16里新建S7-1200项目后最核心的前置工作是把FactoryIO场景里面的所有信号在PLC变量表里老老实实建出来。这个地方我踩过不少次坑最后养成一个习惯输入输出都按“区域_功能_信号名”的方式命名比如抓手工位传感器叫Sensor_Pickup_OccupiedX轴正限位叫Limit_X_Positive而不是叫I0.0、I0.1这种裸地址。建变量表的时候推荐把PLC变量分成几类数字量输入传感器、数字量输出电机使能、抓手控制、警示灯、虚拟中间变量状态机步号、坐标数组索引。对于三轴码垛这种项目还可以把各轴的当前位置以32位实数或双整数形式建立变量方便在博图监控表里实时观察运动位置。FactoryIO的通信适配会把你设定好的变量地址与场景里的信号做映射变量名和地址必须与场景配置一一对应。PLC变量类型示例名称数据类型关联说明输入Sensor_Pickup_OccupiedBool抓取工位有箱检测输入Limit_Z_DownBoolZ轴下限位输入Encoder_X_PositionDIntX轴当前坐标编码器反馈输出Motor_X_EnableBoolX轴电机使能输出Motor_X_DirectionBoolX轴方向输出Gripper_OpenBool抓手打开中间变量Act_StepInt当前状态步号中间变量Target_XRealX轴目标坐标毫米3.2 编码器位置反馈到底怎么进PLCFactoryIO的运动轴和真实伺服轴最大的不同是它默认通过场景内部的物理引擎计算位置。为了让PLC知道轴的实时位置通常要把轴的编码器计数作为输入反馈给PLC。我在变量表里分别建了Encoder_X_Position、Encoder_Y_Position、Encoder_Z_Position三个DInt变量单位是脉冲数。至于脉冲数和毫米之间怎么换算需要先确认FactoryIO场景里的电机减速比和丝杠导程。我这套场景的换算关系很简单X轴每毫米对应10个脉冲Z轴每毫米对应20个脉冲。这个参数不是凭空来的我先在FactoryIO里手动点动X轴移动了100毫米再看PLC读回来的编码器值是1000反推出来的换算系数。做仿真的时候这种“测出来”的系数可以直接用但如果这套逻辑搬到真实伺服系统上就必须以伺服电机编码器分辨率和机械传动比为准了千万别照搬仿真参数。3.3 从FactoryIO侧反向核对地址映射刚才说的都是从PLC变量表往场景映射的流程但实际联调时我习惯再加一道反向检查。在FactoryIO场景里手动触发一个传感器比如用手去遮挡一下抓取工位的对射传感器然后切到博图的监控表里看对应的PLC输入点有没有变为TRUE。如果没变多半是通信驱动中的变量映射配置有问题而不是程序逻辑问题。另一种常见情况是信号极性搞反。FactoryIO里有些传感器输出的是常闭逻辑在PLC侧读出来和实际状态正好相反。这种问题如果在程序里用常开触点去判断就会导致系统明明已经到位却一直等不到位信号。所以场景联调的第一步不是写大段程序而是把所有数字量信号在人机交互侧都点一遍确认极性、变量地址、数据类型三样全对后面才能进入正常编程流程。这一步花的时间越多后面查逻辑的时间就越少。4. 三轴码垛PLC程序骨架——为什么核心要写成状态机4.1 梯形图还是SCL我的选择逻辑博图V16同时支持梯形图LAD、功能块图FBD和结构化控制语言SCL。对于三轴码垛这种流程性很强的项目我强烈推荐核心控制逻辑用SCL来实现原因很直接码垛流程有一大串连续步骤用梯形图写的话置位复位指令会铺满好几张网络别人很难在一屏之内看出流程走到哪里。而SCL可以把整个状态机浓缩在一个函数块里数据流的走向非常清楚调试时也只需要监控一个块内的几个局部变量就能定位故障。当然我并不是完全放弃梯形图。手动操作、急停回路、单轴点动这类安全相关和操作相关的逻辑依然用梯形图写更直观。一个工程实践里很常见的做法是OB1里调用自动程序功能块和手动控制功能块两者通过互锁变量做切换。自动程序用SCL状态机维护手动逻辑用梯形图做按钮操作各取所长。4.2 SCL码垛状态机的核心代码结构我在博图V16里新建了一个名为FB_CodingRobot的函数块内部用CASE语句构建状态机。整个自动周期分成几个大步骤复位、取料准备、下降到抓取位、抓取、抬升、移动到目标库位上方、下降到放置位、释放、抬升返回。把这几个步骤映射到CASE的数值分支上每一段分支执行完之后给下一步的步号赋值流程图就变成了代码。下面这段是我在项目里实际写过的SCL状态机骨架省略了轴定位函数的具体实现重点展示流程结构CASE #step OF 0: // 待机/复位状态 #busy : FALSE; #done : FALSE; IF #startAuto THEN #step : 10; END_IF; 10: // 检查取料位是否有箱有箱则运动到取料上方 IF #pickupOccupied THEN #targetX : #pickupPoint.X; #targetX : #pickupPoint.Z; // 先上行到安全高度 #step : 20; END_IF; 20: // 等待X轴和Z轴都到位 IF #xInPos AND #zInPos THEN #step : 30; END_IF; 30: // 下降到抓取位 #targetZ : #pickupPoint.Z; IF #zInPos THEN #step : 40; END_IF; 40: // 闭爪抓取并延时确认 #gripperClose : TRUE; #timerON(T#200MS); IF #timerON.Q THEN #step : 50; END_IF; 50: // 抬升到安全高度 #targetZ : #safeHeight; IF #zInPos THEN #step : 60; END_IF; 60: // 运动到目标库位上方 #targetX : #rackPoint[#row, #col, #level].X; #targetY : #rackPoint[#row, #col, #level].Y; #step : 70; 70: // 等待X、Y到位后下降到放置位 IF #xInPos AND #yInPos THEN #targetZ : #rackPoint[#row, #col, #level].Z; #step : 80; END_IF; 80: // 下降到位开爪释放 IF #zInPos THEN #gripperClose : FALSE; #timerOFF(T#300MS); IF #timerOFF.Q THEN #step : 90; END_IF; END_IF; 90: // 抬升回安全高度 #targetZ : #safeHeight; IF #zInPos THEN #step : 100; END_IF; 100: // 更新库位占位状态等待下一次循环或结束 #rackOccupied[#row, #col, #level] : TRUE; #done : TRUE; #busy : FALSE; #step : 0; END_CASE;这里的坐标数据我用了一个三维数组来保存库位目标点博图V16里的数组元素可以是UDT结构体里面包含X、Y、Z三个坐标分量。调用时用#row、#col、#level三个索引变量来指向当前要码放的库位每放一个箱子就更新一次索引。库位排布顺序我采用先填满第一层、再往上一层的方式这样能降低箱子重心不稳导致的倒塌概率。4.3 轴控功能块让每个轴都具备点到点定位能力如果直接在状态机里写每一拍都要给哪个轴发脉冲那程序会膨胀到没法维护。所以我把三根轴分别封装成了带定位功能的功能块或者直接使用TIA Portal自带的运动控制指令如MC_MoveAbsolute、MC_MoveRelative来实现点对点运动。对于S7-1200来说如果走PTO脉冲轴模式可以调用Motion Control指令集如果只是做仿真场景也可以自己写一个简化的速度控制块把目标坐标和当前坐标做比较来决定输出方向。我这次为了更贴近实际伺服调试方式使用了PTO轴组态。每根轴的运动指令都统一输出到同一个引脚接口上目标坐标、速度、加减速时间、到位宽度。在这个基础上我再在轴功能块内部做了方向判断和使能控制比如X轴目标坐标大于当前坐标就置正向输出小于就置反向输出到位信号通过编码器位置偏差小于设定值的比较来判断。4.4 手自动切换与报警停机逻辑怎么嵌进状态机真实设备不允许“自动运行从头跑到尾不让人插手”程序员必须把手动、自动、报警、暂停这几种模式全部设计好。我的做法是在FB_CodingRobot外部再套一层模式管理逻辑当模式选择开关在手动挡时自动状态机不允许启动轴的输出只能受手动点动按钮控制当切回自动挡时如果设备不在原点先执行回零逻辑而不是直接开始取料。报警处理也直接影响状态机跳转。立库码垛最常见的报警是气压低、抓取超时、轴到位超时。我的习惯是凡是检测到报警立即把当前步骤保持在报警前一步不允许进入下一步。博图V16里可以通过在每个CASE步骤中判断同一个报警变量来实现统一拦截也可以把报警处理放在状态机外层通过一个“本周期是否有报警”的BOOL变量同时控制电机的使能和抓手动作。等报警解除后再配合一次人工的“复位”按钮把状态置回安全状态。提示自动运行过程中暂停功能和复位功能要分开处理。暂停只是冻结输出并保持状态复位则是把状态机强制拉回0步并清空执行标志。很多初学者会把暂停做成跳回0步导致从暂停恢复时没法续跑这是程序逻辑里很常见的设计问题。5. 联调过程中实际遇到的问题——比功能实现更容易让人长经验5.1 传感器抖动导致的重复计数第一次联调时我遇到一个很有意思的现场箱子明明只经过入库输送线一次PLC记忆里的入库计数却变成了3。用博图监控表盯着传感器变量看发现这个信号在箱子挡光瞬间产生了多次跳变一下TRUE一下FALSE每次跳变都触发一次上升沿计数。这个问题在FactoryIO仿真环境中也存在追根溯源是场景里的传送带在低速重载情况下会产生微小的震动传感器检测区域在临界状态反复触发。这种传感器抖动问题在真实设备上同样存在而且更隐蔽常发生在对射传感器被灰尘污染或者安装位置正好卡在检测边界时。处理办法有两条路子硬件上给传感器加抗干扰措施、调整安装位置软件上在PLC里做延时滤波或者连续确认。后续我使用的是软件滤波方案传感器由FALSE变TRUE之后延时50毫秒再确认有效有效之后立刻开始输送线停车的联锁逻辑。这样既没有明显增加响应时间又把抖动带来的重复上升沿问题彻底压住了。5.2 程序运行中点了急停再复位状态机回不去了还有一次是测试急停功能时发现的。按着急停习惯我把急停信号串到了电机的使能回路里急停按下后电机全部断电轴停在半空。一切正常。但等我松开急停按下复位自动状态机却原地卡死不继续往下走了。排查后发现问题出在状态机上急停触发瞬间程序正好执行到“下降取料”的步骤已经发出了下降指令因为电机断电轴没有到位而复位逻辑只负责清除报警并没有修正目标Z轴坐标和当前Z轴坐标之间可能存在的偏差。换句话说轴还停在离抓取位一截的位置程序却以为它还停在之前完成的状态里于是等待一个永远等不到的到位信号。解决方案也不复杂在急停复位之后增加一个“重新回安全点”的中间步骤。任何报警复位后程序都不允许直接恢复到报警前的状态继续执行而是先让三轴回到一个确定的安全点再让操作员从断点重新启动。这和很多数控系统里“急停后必须回参考点”的逻辑是一个道理。把这句话刻在习惯里复位就是回到原点而不是回到断点。5.3 通过博图监控表与FactoryIO物理画面互相对照找问题联调阶段最实用的排错方法就是同时开着博图的监控表和FactoryIO的三维画面。程序卡住的时候先在FactoryIO里看设备姿态抓手在哪、箱子在哪、哪个传感器被触发。有了这个直观信息后再去博图监控表里查对应的PLC输入输出状态通常会很快找出症结。还有一种情况是PLC侧已经发出了移动指令但FactoryIO里的轴就是不动。这时候别急着改程序先看轴的使能信号通没通。我遇到过一次很典型的低级错误功能块里我用了两个不同的变量来保存X轴的使能输出一个在手动逻辑里置位一个在自动逻辑里置位。自动运行时虽然置位了自动变量但真正接到FactoryIO驱动接口的另一个变量还是FALSE轴自然纹丝不动。查了十分钟才发现是变量用混了。这也是我前面强调变量命名规范的重要原因设备一变复杂变量表几百个点位靠“看起来像”的记忆去写程序一定会翻车。6. 从仿真向真实设备迁移的补课思路——很多经验是场景教不会的6.1 伺服电机加减速时间不能拍脑袋FactoryIO里运动轴的速度调节相当“宽容”你给它一个阶跃速度指令它内部的物理引擎会平滑过渡不会产生实际伺服系统那种猛烈的冲击感和机械抖动。但真实伺服轴不一样如果不设合理的加减速时间电机启动瞬间产生的冲击可能直接让设备结构发生共振丝杠模组也会加速磨损。从我调试真实设备的经验来说X轴这种长行程大惯量结构加减速时间一般设置在0.3到0.6秒之间Z轴因为有重力参与如果使用了垂直安装并带有配重或者刹车要把加速度曲线设置得更平滑必要时还要单独做防坠落互锁。在仿真里你会发现加减速时间设成零也能跑但到了现场一定不能省这个参数。6.2 原点回归、限位开关和安全继电器在仿真里容易被简化仿真场景通常默认码垛机开机时已经知道自己的位置或者只需要简单回一下零就能获得坐标。实际设备上伺服驱动器断电后位置信息是会丢失的绝大多数设备都需要在每次上电后执行一次“原点回归”动作用原点开关加编码器Z相脉冲来确定机械原点。限位开关也是仿真很容易忽略的环节。场景里轴走到极限位置会被物理墙面挡住但真实设备靠硬挡块去挡电机一定会坏。我通常在博图项目里给每个轴都组态软限位同时把FactoryIO场景提供的限位传感器当作硬限位处理程序里不仅要在到达硬限位时切断使能还要触发报警并禁止向同方向继续运动。另外一个真实项目里不会省的安全继电器比如急停回路、门锁回路、双手启动回路这些在仿真里最多用一个按钮代替但到了电气图纸上它们往往是独立于PLC的安全链。6.3 码垛防倒塌的控制细节最后聊一个经常被当成“可选项”但其实很重要的细节码垛过程中的防倒塌。严格来说码垛不是把箱子放到坐标上就完事放置位置误差超了、上层箱子压在下层缝隙上、平台运动速度过快把刚放好的箱子横推出去都有可能导致整个托盘倒塌。在FactoryIO这种带物理引擎的仿真环境中这个问题已经能部分体现比如码放偏了箱子会重心不稳。程序侧我做的处理是每次码放前强制检查对应库位的占位状态防止重复放置导致箱子相互干涉每次抬升动作必须垂直抬到安全高度后才允许水平移动水平移动过程中如果抓手真空丢失立刻停住并且报警不允许带着半空掉落的“假抓取”继续跑。这些逻辑虽然不需要多深的理论但没有它们一台码垛设备就谈不上可靠两个字。把三轴码垛仿真项目完整跑通我自己最大的收获并不是学会了某个具体指令或者某条通信配置而是建立起了“从场景信号到PLC程序再到机械动作”的闭环思考方式。在FactoryIO里你可以放心大胆地让设备撞一下限位、让抓手抓空一次反正机床和箱子都是虚拟的试错成本几乎为零。也正因如此仿真里越是大胆到了现场越要对每一个细节保持敬畏。如果你也开始在这个方向练手建议别急着去背那些指令先把场景里的传感器、坐标、安全边界这盘账算清楚程序写出来自然就有章法了。
返回列表