如果你调试过机械手抓取和涂胶的工位,一定见过这种场景:单步走的时候一切完美,真空吸得稳稳的,胶路拉得又直又均匀,可一按下自动启动跑不到半小时,要么吸盘把工件摔了,要么某段胶突然粗了一大截。我去年在一个西门子S7-1500项目里就撞上了这堆事,最后把整套标准程序从头到尾拆了一遍,才把问题一个个摁死。这篇文章我想把对西门子标准程序里"机器手抓取+涂胶控制"这部分内容的完整理解写出来,包括程序怎么分层、抓取子程序怎么判断真空、涂胶子程序怎么控胶量、机械臂和PLC的信号怎么握手,以及我在现场调试时攒下的那些坑。无论你是在写新程序还是在一堆旧代码里加功能,应该都能从里面找到直接能用的东西。
1. 抓取涂胶工位到底在做什么:先把工艺边界搞明白
1.1 典型工位的硬件组成与信号清单
机械手抓取加涂胶控制,听起来是个很具体的应用,但不同行业的工位配置差异其实很大。我在项目里遇到的最常见组合是:机械手本体用三到四轴的桁架结构,由PLC直接控制伺服轴;抓取端用真空吸盘或者两指气爪;涂胶单元由胶泵、胶阀、回吸机构组成。吸盘适合平面工件,气爪适合有抓取面的异形件,选型不同,程序里的判定逻辑也不一样。
无论硬件怎么变,IO信号的大类基本固定。我习惯先把信号清单列出来再写程序,否则边写边想点位,逻辑容易乱。
| 信号类型 | 典型点位 | 作用说明 |
|---|---|---|
| DI | 吸盘真空压力开关 | 确认是否真正吸住工件 |
| DI | 气缸磁性开关(夹爪开/到位) | 确认夹爪的实际状态 |
| DI | 工件检测光电/接近开关 | 判断上料位有无工件 |
| DI | 伺服轴原点/正负限位 | 防止轴冲出机械范围 |
| DI | 胶枪开/关到位反馈 | 确认胶阀动作到位 |
| DO | 真空电磁阀 | 控制真空发生器的压缩空气通断 |
| DO | 夹爪气缸电磁阀 | 控制夹爪打开/闭合 |
| DO | 伺服使能/脉冲/方向/硬复位 | 轴运动控制 |
| AO | 胶泵变频器频率给定 | 按涂胶速度调节供胶量 |
1.2 控制需求的三个层次
抓取涂胶工位看着简单,实际控制需求是分层的。第一层是单机动作,比如把工件从上料台抓起来放到涂胶台,这属于最基础的逻辑。第二层是工序协同,涂胶时胶枪开关和轴运动必须同步,先走一点再开胶、结束前提前关胶,否则轨迹两端会缺胶或者滴胶。第三层是安全与保护,抓取后必须校验真空确认,涂胶过程必须有流量或压力监控。
很多程序写出来设备能动,但节拍、质量、稳定性全不对,问题就出在只实现了第一层,后面两层根本没考虑。代码的复杂度和工艺的复杂度成正比,写程序前先把这三个层次拆清楚,后面会省很多返工时间。
2. 标准程序为什么这样拆:FC/FB/DB的设计思路
2.1 按动作设备拆FB,按工序拆FC
拆程序是最考验经验的一步。拆得好,后期加料型、换型号都轻松;拆不好,改一个动作要翻几十个块,改完还容易带出新故障。
我的建议是:抓取和涂胶是两条相对独立的设备动作线,应该拆成两个基础功能块FB_Gripper和FB_GlueUnit,再加一个FB_AxisCtrl用于伺服轴运动控制,这是按设备动作来拆。然后单独做一个FC_ProcessSequence负责整条工序状态的调度,把前面几个FB按节拍串起来。这样分层之后,每个功能块内部只关心自己的事,工序调度块只关心当前该调用谁。
为什么不把这些逻辑全部塞进一个FB里?我吃过这个亏。第一个项目为了偷懒,把抓取、涂胶、轴运动全写在一个FB里,结果设备上其他工位也想复用抓取逻辑,只能复制粘贴一份,后期改真空确认时间要改两处。拆得越独立,复用性越强,维护成本越低。
使用多重背景数据块可以让数据管理更清爽。比如在FB_Cell里声明几个子功能块的实例:
FUNCTION_BLOCK FB_Cell VAR fbGripper : FB_Gripper; // 多重实例,不需要单独建背景DB fbGlue : FB_Glue; fbAxisX : FB_AxisCtrl; END_VAR如果不使用多重背景,就得在OB1里为每个子功能块建独立的背景DB,调用层次一多,HMI里引用变量的路径就会变得很长。多重背景把所有子模块封装进一个FB_Cell,数据管理、HMI访问都简单很多,这也是西门子标准程序里很常见的做法。
2.2 数据怎么放:背景DB、全局DB与I/O映射表的边界
一个常见错误是直接在程序里访问I0.0、Q0.0这种物理地址。前期接线没改的时候没问题,等现场调线或者换IO模块就得一个个改地址,改漏一个就要花半天查问题。
标准程序通常会把输入映射到一个全局DB,比如DB_InputMap,输出映射到DB_OutputMap,程序内部只跟DB变量打交道。接线改线只影响映射区,逻辑代码完全不用动。在OB1扫描周期开始的时候做一次批量映射,程序结构也清晰,监控变量时看DB比看物理点直观得多。
2.3 命名规范的小讲究
命名规范看着是小事,实际上影响很大。我见过有些程序里变量叫a1、b1、c1,三个月后自己回来看都认不出来。我现在的习惯是:DI_、DO_、AI_、AO_开头的映射点,FB_Xxx表示功能块,布尔量用b开头比如bStart、bReady,整数状态用iState,定时器用fbXxx。这套规则虽然没什么技术含量,但能让别人接手程序的时候少骂两句。
3. 抓取子程序的核心逻辑:真空建立、到位确认与超时保护
3.1 抓取状态机怎么设计
抓取过程如果用状态机表示,至少要有七个状态:空闲、下落/靠近、夹紧或者吸真空、真空确认、抬起、搬运、松开。状态机的好处是每个时刻只有一个状态处于激活,代码路径单一,排查问题的时候只看当前状态和转移条件就可以,不需要把整段逻辑从头到尾读一遍。
下面是一个简化的抓取状态机SCL代码,我用的是FB_Gripper内部的状态字段iState:
CASE iState OF 0: // IDLE 空闲 IF bStart THEN iState := 10; END_IF; 10: // 下落/靠近 bMoveDown := TRUE; IF bInPosition THEN iState := 20; END_IF; // 超时保护 fbTimeOut(IN := TRUE, PT := T#3S); IF fbTimeOut.Q THEN iState := 100; // 报警状态 bAlarm := TRUE; END_IF; 20: // 吸真空/夹紧 bVacuumOn := TRUE; fbPressureTime(IN := bVacuumOK, PT := T#800MS); IF fbPressureTime.Q THEN iState := 30; END_IF; 30: // 抬起 bMoveDown := FALSE; bMoveUp := TRUE; IF bUpPosition THEN iState := 40; END_IF; 40: // 搬运 bMoveUp := FALSE; bMoveForward := TRUE; IF bTransferPosition THEN iState := 50; END_IF; 50: // 松开 bVacuumOn := FALSE; fbReleaseTime(IN := NOT bVacuumOK, PT := T#500MS); IF fbReleaseTime.Q THEN iState := 0; END_IF; END_CASE;这段代码只是个骨架,现场还要根据实际机械结构补充联锁条件。状态机写好后,HMI上可以做一个状态显示,当前程序走到哪一步一目了然,调试效率提升很明显。
3.2 真空信号不要直接当成"已抓取"信号
很多新手把真空压力开关的ON信号直接当成工件吸牢了,这是典型的误区。真空压力上升到设定值需要时间,短则两三百毫秒,长则超过一秒,具体取决于真空发生器流量、吸盘大小、管路长度和工件表面平整度。压力开关本身也有响应延迟。直接拿瞬间信号去触发下一步动作,很可能在真空还没稳定的时候就把工件抬起来了,轻则工件移位,重则直接掉落。
正确做法是:启动真空后,持续检测真空信号,要求信号保持超过一个设定时间才认为抓取成功。上面代码里的fbPressureTime(IN := bVacuumOK, PT := T#800MS)就是这个意思,bVacuumOK必须保持800ms为真才输出成功信号。这个延时时间需要现场标定,吸盘大、管路长就适当加大到1到1.5秒,吸盘小、工件轻可以缩到500ms。
3.3 超时保护的几种做法对比
抓取动作任何一个环节卡住,没有超时保护的话设备就会一直等下去,节拍浪费不说,还可能因为气缸长时间通电发热甚至烧毁电磁阀。超时保护在标准程序里一般有三种做法,我对比过它们的适用场景:
| 做法 | 实现方式 | 适用场景 |
|---|---|---|
| 固定延时 | 每个状态进入时启动一个TON,超时未转移到下一状态就报警 | 各动作时间相对固定的简单工位 |
| 指令完成位互锁 | 用轴运动指令的Done位、气缸磁性开关等真实反馈作为超时清零条件 | 需要精确区分"动作中"和"已完成"的场合 |
| 多段超时时间 | 不同状态设置不同PT值,存放在数组或配方DB里 | 工件型号多、各型号抓取差异大的设备 |
我实际项目里用的是第三种。抓取的接近时间、真空建立时间、搬运时间都存到DB里,换型号时HMI直接改参数,不需要改程序。超时之后不能只是闪个报警,最好能把当前状态号和超时状态号都记录下来,方便快速定位是哪一个动作卡住了。
4. 涂胶子程序的关键算法:轨迹状态机、胶量补偿与断胶保护
4.1 涂胶轨迹状态机的控制思路
涂胶和抓取在程序结构上很像,但时序要求更严格。涂胶轨迹状态机涉及的动作包括:定位到起点、开胶延时、沿轨迹移动、到达终点先关胶、抬枪或者回吸、返回安全位。
关键点在于开胶和关胶的时刻相对轴运动有一个提前量或者滞后量。如果轴已经走起来才开胶,轨迹起点会缺一段胶;如果到达终点先停轴再关胶,末端会堆一坨胶。标准做法是:
- 轴先加速到达设定速度,稳定后再开胶,开胶到出胶稳定有一个小延时。
- 接近终点前提前关胶,提前量根据当前速度和胶泵响应时间来算,胶泵响应慢就提前多一点。
- 轴继续走到终点后再停下来,这样末端胶量才均匀。
这个逻辑用状态机写非常自然,每个状态只需要关心当前输出和转移条件。我一般会把轨迹拆成直线段和圆弧段,每段有独立的起点、终点、速度、胶枪状态,存到配方DB里,换产品时调用不同配方就行。
4.2 胶量怎么算:速度-流量匹配的基本公式
涂胶量的控制方法主要有两种。一种是速度跟随,轴的移动速度作为胶泵频率的主给定,乘一个标定系数,适合对胶量精度要求不高的场合。另一种是定量挤出,用伺服电机驱动螺杆泵,精确控制每单位长度轨迹的挤出量,适合精密涂胶。
不管哪种方式,核心公式都是胶量与轨迹参数的关系:
[ Q = v \times w \times h \times \rho ]
其中,Q是所需胶泵流量,v是涂胶速度,w是胶路宽度,h是胶路厚度,ρ是胶的密度。实际项目中w和h由胶嘴口径和离板高度决定,很难直接量准,所以更常用的是标定法。先固定一个涂胶速度,手动调胶泵频率让胶路宽度达到要求,记下这个频率值作为基准点,然后按速度线性插值。程序里就是一个比例系数k(胶泵Hz除以轴速度),不同胶种的k值不一样,存到配方里。
涂胶最怕的是轴速度突然变化,比如轨迹上有圆弧或者拐角,轴必须减速通过,此时胶泵如果没有同步减速,胶量就会堆积。所以在程序里胶泵的频率给定不能只取轴速度目标值,要取轴速度的实际值或者经过平滑后的设定值,让胶泵柔性地跟随。这一步我踩过坑,后面详细说。
4.3 断胶保护与回吸处理
涂胶工位还有一个很容易被忽略的问题:胶管里气泡多了、胶嘴堵了、胶泵机械故障,都会导致断胶,但是程序如果只看轴运动轨迹,根本发现不了,结果就是一批工件全涂了个半截胶。
断胶保护的两种常用方案:
- 胶路压力监控:在胶枪前装压力传感器,涂胶过程中监测压力是否在正常区间。压力突然掉下去说明断胶或者气阻,压力突然飙高说明胶嘴堵塞。
- 流量计监控:高精度场合直接装流量计,把实际流量和设定流量做比较,偏差超过阈值立刻报警停机。
我建议至少装压力传感器,成本低效果好。程序里对压力信号做滑动平均滤波,防止胶泵脉动造成误报警。
回吸处理是另一个细节。胶枪关闭后,胶嘴里的胶会因为重力和表面张力慢慢往外渗,如果停留在工件上方就会滴到工件上,造成外观缺陷。结构上一般会加回吸机构,程序里要单独做一个回吸状态:先关闭胶枪,再启动回吸电磁阀,保持一小段延时,然后才执行抬枪动作。这个动作不能用关胶信号直接替代,必须有一个独立的状态,否则整个动作时序会乱。
5. 机械臂与PLC的信号交接:循环节拍里最容易被卡住的地方
5.1 握手信号的时序设计
机械手抓取工位通常不是PLC单独控制全部动作,而是PLC和机械臂控制器协同工作。这时候PLC和机械臂之间的通信就特别重要,常见的有PROFINET IO、Profinet智能设备通信或者硬接线IO。
无论用哪种方式,握手信号的设计原则是一致的:用沿触发,不要用电平触发。我给PLC和机械臂之间定义了几组握手信号:
- PLC给机械臂"请求取件"。
- 机械臂到达安全位置后返回"到达就绪"。
- PLC确认机械臂就绪后,给出"抓取指令"。
- 机械臂完成抓取动作后返回"抓取完成"。
- PLC收到"抓取完成"后,才允许机械臂执行下一个动作。
这里的关键是每个信号都必须用上升沿或者下降沿来判断,不能只看电平。因为PLC扫描周期和机械臂程序运行周期不一样,一个电平信号可能在同一个扫描周期里被重复读取,导致程序重复触发。我习惯在程序里先把通信区信号的上升沿锁存到一个中间变量,再用这个中间变量去做后续逻辑。
5.2 轴运动的使能与到位判断
伺服轴控制也有固定的顺序,不能乱。我现在的标准顺序是:
- 先给伺服使能,等待使能反馈。
- 执行回原点,确认原点信号。
- 再下发定位指令。
- 等待到位信号或者运动完成位。
- 最后处理报警复位。
很多现场问题出在使能和定位指令同时下发,或者还没回原点就给了绝对定位指令,轴直接飞了。这个顺序在程序里要用状态锁住,不能在手动和自动模式之间乱跳。
还有一个细节:轴运动完成信号不能用轴的到位信号代替。到位信号的精度受伺服参数影响,可能还有几丝误差,而运动完成信号是伺服驱动器确认整个运动过程结束的标志。我是两个信号都监测,先到位再等完成,都满足才认为这一步结束了。
5.3 手动/自动切换的状态一致性
手动调试时可能会直接在HMI上动作伺服轴、开关胶枪,这些操作会改变轴的实际位置和I/O状态。切回自动模式后,如果程序还保留着之前的状态,自动运行时可能直接从半途继续执行,导致碰撞、漏胶或者抓空。
解决这个问题我采用了两个措施。第一,模式切换时强制将状态机复位到空闲态,并关闭所有动作输出,包括真空电磁阀、胶枪、伺服使能。第二,自动启动前做一个完整的初始条件检查,包括所有轴必须回原点、所有执行器必须在初始位、所有报警必须复位,全部满足才允许启动。这个初始条件检查就像飞机起飞前的检查单,缺一项都不能起飞。
6. 现场调试避坑:抓取涂胶项目里攒下的8类典型问题
6.1 真空回路被忽略的"脏东西"
有个项目调试了很久,发现偶尔会误报吸盘没吸住工件,但是机械上检查吸盘、真空发生器、管路全都没问题。后来发现是真空过滤器堵了,真空压力开关装在过滤器前端,过滤器堵塞后压力开关读数正常,但吸盘端的实际真空度根本不够。这个问题的隐蔽之处在于,压力开关显示的压力是"管路压力"而不是"吸盘压力"。最后我把压力开关移到了过滤器后端,并且在程序里加了一个真空泵累计运行时间提醒,定期检查更换过滤器。这个坑提醒我,传感器测到的位置和物理真实状态的位置要尽量一致。
6.2 工件到位信号抖动导致重复抓取
工件到位信号是由光电开关提供的,但机械手抓走工件后,光电开关信号要经过一段时间才真正变为OFF,如果程序没有处理沿信号,机械手返回后会再次触发抓取逻辑,造成重复抓取。这个问题的典型现象是,设备偶发抓了两个工件,但现场看真空吸盘上只有一个。解决办法是:工件到位信号在程序里锁存一次,每次抓取循环开始时清除锁存,只允许响应一次上升沿。同时工件到位信号要加一个20到50ms的去抖滤波,防止信号在临界状态反复跳变。
6.3 涂胶轨迹速度突变导致胶量不均
这是一个很难一眼看出来的问题。我的设备在直线段涂胶正常,到了圆弧段胶路明显变宽,甚至出现堆积。查了很久才发现,轴的设定速度在圆弧段被插补器降低了很多,但胶泵频率给定用的还是直线段的速度值,没有跟上实际轴速。现象就是胶泵觉得轴还在快速跑,拼命挤胶,而轴实际已经减速了,胶全堆在原地。
程序修复思路是,胶泵频率给定改成从轴的实际速度读取,而不是从运动指令的设定速度读取。如果PLC使用的是S7-1500的运动控制功能块,可以直接读状态字里的实际速度;如果是外部伺服,则通过伺服驱动器的反馈字获取实际速度。标定系数也要根据实际速度重新整定一遍。
6.4 胶泵启停和胶枪开关的顺序没有协调
胶泵如果先于胶枪启动,胶路压力会瞬间升高,胶枪一开胶就喷出来,轨迹起点一大坨胶;反过来胶枪先关但胶泵还在转,胶路压力会憋高,下次开胶又是一阵喷。标准做法是:
- 启动顺序:先启胶泵,延时几百毫秒待胶路压力稳定,再开胶枪。
- 停止顺序:先关胶枪,再停胶泵,同时开启回吸机构。
这两个延时都要能通过HMI调整。不同胶种的粘稠度和管道长度影响很大,不能写死。
6.5 手动/自动切换后状态错乱
前面第5.3节讲了原理,这里说一个实际案例。操作工在手动模式下把机械手轴移动到了半路,切回自动模式后直接按启动,程序从状态机的第30步(抬起)继续执行,结果机械手带着吸盘直接往涂胶台方向冲。幸好有急停,不然就是一次碰撞事故。自那以后我在所有项目里都加了自动启动前强制复位状态机和初始条件检查,并且把"自动启动前所有轴必须回到原点"写进了操作规范。
6.6 多重背景数据块的工程陷阱
用多重背景数据块时有一个隐蔽的问题:如果子功能块(比如FB_Gripper)的接口增加了新的参数,系统会自动更新多重背景数据块的结构,但是某些情况下HMI里已经建立连接的变量会失效,需要在TIA Portal里重新编译整个项目,否则下载后HMI会报变量连接错误。我的建议是,功能块接口尽量稳定,前期考虑周全,后期不要频繁增删引脚。如果确实需要改接口,一定要在改动后重新编译PLC程序和HMI画面,并完整下载一次,不要只下载PLC程序。
6.7 报警复位后设备从半中间继续跑
这是我在一个涂胶工位上遇到的典型案例。设备报了一个涂胶压力过低的报警,操作工按了复位,程序直接回到报警前的状态继续跑,胶枪重新打开继续涂。但实际工件已经挪了位置,胶路涂在了错误的位置,整件报废。报警复位后到底该从哪里继续,一定要在设计程序时想清楚。我现在对报警有一个分类:可恢复的报警(比如工件没放正,重新放正后可以从头继续)和不可恢复的报警(比如涂胶中断,必须人工干预后从头开始)。不可恢复的报警复位后一律回到空闲状态,不允许从中间状态继续执行。
6.8 配方切换时参数没有初始化
设备支持多产品切换的话,配方表的参数一定要在切换时全部初始化,包括涂胶速度、胶泵系数、轨迹点坐标、真空确认时间、超时时间等。我见过一个项目,切换产品后涂胶轨迹是对的,但因为胶泵系数没有更新,还是用上一个产品的大系数,第一件工件直接胶量过量,胶水顺着工件流了一地。配方切换动作要放在工序调度的起始位置,切换完成后做一次参数完整性校验,确认所有关键参数都在合理范围再允许启动。
做这个项目最大的体会是,程序稳定性的关键不在于某一条算法多精巧,而在于每一个边界条件都有对应保护。抓取要确认真空才能真正抬起,涂胶要监控压力才能及时发现断胶,信号交接要沿触发才不会重复误动。这些经验看起来都是小事,但每一个都曾经让我在现场多熬了好几个晚上。如果你也在搞同类设备,我建议先把状态机画清楚再动笔写代码,把上面这8类问题在调试前就预防掉,能省下的时间绝对远超你画状态机花掉的时间。