要点速览
子程序是什么,何时值得用
子程序是以独立 O 号存放的单独程序,由主程序调用运行。当控制读到 M98 P1001 时,跳转到 O1001,执行这些程序段,并在 M99 处返回到调用后的下一行。主程序保持原有流程。子程序存放重复的工作。
收益体现在有重复几何特征的零件上:一块有 24 个相同 M8 螺纹孔的板、一个有 8 个型腔的工装夹具、一组共用同一螺栓孔位的支架。孔加工循环写一次,用不同的 X 和 Y 调用 24 次。改一次进给,24 个孔全部改变。
不要仅因为代码看起来长就用子程序。如果一段顺序只运行两次,直接复制粘贴更易读、更易重启。当同一运动重复三次以上,或多个程序共用同一固定循环序列时,子程序才值得用。
尽量让子程序不包含机床相关的假设。如果 O1001 中含有 G54 工件偏置,每个调用它的程序都会继承该偏置。在一台机床上没问题,在另一台上可能撞机。把偏置放在主程序,让子程序只处理几何。
- 1适合重复孔位、共用型腔循环、同族零件的螺栓圆。
- 2不适合只用一两次且无参数变化的顺序。
- 3注意偏置G54–G59 放在主程序中,不要放在子程序内。
M98 和 M99:调用与返回
M98 是调用。其 P 字给出子程序号。在 M98 P1001 中,控制把 1001 读作程序号并运行 O1001。部分厂商也接受 L 字表示重复次数,例如 M98 P1001 L6,连续运行子程序六次,无需写六个调用段。
M99 是返回。把它放在子程序的最后一段。控制随后跳回 M98 调用后的程序段。如果子程序以 M30 结束,控制会倒回整个程序并停止。在攻丝中途这意味着断丝锥或零件报废。
M99 还有一个让人意外的用法。如果把 M99 放在主程序末尾而不是 M30,控制会循环整个程序并再次运行。这对棒料送料循环很方便,但忘了它存在就很危险。
调用深度很重要。子程序可以调用另一个子程序。多数 Fanuc 风格控制系统允许 4 层。超过就会触发 P/S 报警并停机。如果逻辑需要 5 层,把它展平或把工作拆成两个主程序。
- 1调用M98 P1001 — 跳转到 O1001,在 M99 处返回。
- 2重复M98 P1001 L6 — 同一子程序运行六次。
- 3返回M99 — 回到调用后的程序段。
- 4绝不要用 M30 结束子程序它会倒回并停止循环。
用 G65 和局部变量传递数值
普通 M98 不携带数据。每次调用都运行相同运动。如果想让一个子程序在 24 个位置加工 24 个孔,要么在主程序中写 24 行带位置的调用,要么用 G65 把位置作为参数传入。
G65 P9010 X50. Y30. Z-12. R2. F180 调用 O9010 并把数值装入局部变量。X 映射到 #24,Y 到 #25,Z 到 #26,R 到 #18,F 到 #9。在子程序内写 G81 Z#26 R#18 F#9,控制会代入你传入的数值。
在多数控制系统中,子程序返回时局部变量 #1 到 #33 会被清除。这是特性。意味着下次调用从干净状态开始,没有上一位置的残留值。如果某个值需要在返回后保留,把它写入公共变量,如 #100 或 #500。
参数不是免费的。每次 G65 调用比普通 M98 多花少量加工节拍,且深度嵌套的 G65 调用在尺寸出错时难以追踪。对于永不改变的固定模式,普通 M98 更简单。对于由位置表驱动的模式,G65 是更清晰的路线。
- 1X → #24,Y → #25,Z → #26Fanuc 风格控制系统的标准参数映射。
- 2R → #18,F → #9用于子程序内的固定循环。
- 3局部变量在返回时复位若数值需保留,用 #100 以上。
命名、编号,以及哪些内容应放在子程序内
给子程序分配一个独立的 O 号,放在车间为子程序保留的号段内。常见做法是:O1000–O1999 用于共享子程序,O9000–O9999 用于机床厂商程序或宏程序。保留书面记录。两个编程员把 O1050 分配给不同代码,就是等着撞机。
开头程序段应设定已知状态。写入安全 Z 值、用 G80 取消任何固定循环,以及子程序所需的模态值。绝不要假设主程序把系统留在了方便的模式。子程序若意外以 G91 开头,就会把孔钻成一条直线而不是一个圆。
编写子程序时要保证它能从任意起点运行。除非确实需要增量运动,否则阵列几何用绝对定位。从某一位置调用能正常工作的增量代码,从另一位置调用常常失效,因为机床停在了意料之外的位置。
结束时让机床停在可预测的位置。抬到安全平面,用 G40 取消刀具补偿,用 G80 取消循环,然后 M99。主程序的下一个程序段不应替子程序收拾残局。
- 1保留号段O1000–O1999 用于共享子程序,并在一处登记。
- 2入口设定状态G80、G40、安全 Z 值,以及所依赖的模态值。
- 3出口保持状态干净G40、G80、安全 Z 值,然后 M99。
分步操作:编写、测试并调用子程序
按顺序执行。跳过第 5 步,正是大多数首次运行撞机的原因。
- 1明确子程序的任务写一句话:“在 X、Y 传入的位置钻一个 M8 孔。”如果这句话里有“和”,说明子程序做得太多。拆开它。既钻孔又攻丝的子程序是两个子程序。
- 2分配程序号并添加注释从预留号段中选一个未占用的编号,例如 O1050,并在同一行添加注释:O1050 (M8 DRILL CYCLE)。这条注释就是下一位操作员在凌晨 2 点看到的内容。
- 3设定入口状态开头用 G80 取消任何活动固定循环,用 G40 取消刀具补偿,再用 G0 Z50. 到达已知安全高度。然后设定循环所需的模态值,例如 G90 绝对坐标和 G17 XY 平面。
- 4编写运动程序段钻孔循环:G0 X#24 Y#25,然后 G81 Z-12. R2. F180.。型腔加工:下刀、斜降切入、走轮廓,然后 G40 并退刀。每个坐标要么用绝对坐标,要么明确用增量坐标,没有注释时绝不混用。
- 5干净地结束子程序用 G80 取消循环,用 G40 取消补偿,用 G0 Z50. 抬到安全平面,然后写 M99。不要写 M30。除非下一次调用需要,否则不要让主轴继续转。
- 6不装工件,用单段测试载入主程序,把快速倍率设为 25%,单段执行前两次调用。观察剩余距离显示。确认每次 M98 后机床回到准确程序段,再允许全速运行。
- 7从主程序调用用 G65:G65 P1050 X50. Y30.。固定阵列且无参数:M98 P1050。带重复次数:M98 P1050 L6。所有工件坐标系(G54–G59)都放在主程序里,不要放进子程序。
- 8批量运行前验证首件切一件,按图纸检查孔位,并确认返回点没有漂移。在 24 孔的板上,一个局部变量写错,会表现为整排孔位置错误。
M98、G65 与宏程序:该用哪种调用
根据子程序是否需要传入数据来选择调用方式。
| 方法 | 传递数值 | 适用场景 | 注意事项 |
|---|---|---|---|
| M98 P1001 | 否 | 固定顺序,每次运动相同 | 无参数;位置必须写在主程序中 |
| M98 P1001 L6 | 否 | 同一循环按设定次数重复 | 重复次数必须与实际阵列一致 |
| G65 P9010 X.. Y.. | 是,传入局部变量 | 位置驱动的阵列和零件族 | 每次调用稍慢;出错尺寸更难追踪 |
| G66 模态宏调用 | 是 | 同一宏应用于后续多个程序段 | 容易意外保持激活;用 G67 取消 |
| 直接复制粘贴 | 否 | 只用一两次的顺序 | 改了一份却忘了其他副本 |
常见子程序错误与修复
先看现象,再看原因和修复方法。
| 现象 | 可能原因 | 处理 |
|---|---|---|
| M98 行报警 | 程序号不在内存中或 O 号错误 | 载入 O1001 并检查 P 字是否匹配 |
| 最后一个孔后循环中途停止 | 子程序以 M30 而不是 M99 结束 | 把 M30 改为 M99 |
| 机床反复运行程序 | 主程序末尾写了 M99 | 把主程序结束改为 M30 |
| 第二次调用在错误位置切削 | 第一次调用后增量运动仍处于激活状态 | 在子程序开头设定 G90 |
| 每次调用孔位偏移越来越大 | 返回前未取消补偿或循环 | 在 M99 前加 G40 和 G80 |
| 深层嵌套时出现 P/S 报警 | 子程序调用超过 4 层 | 简化逻辑或拆成两个主程序 |
工程师常问的子程序问题
子程序和宏程序有什么区别?
子程序是用 M98 调用的存储程序,每次运行相同的程序段。宏程序也是存储程序,但能做算术运算、读取系统变量、用 IF 和 GOTO 跳转,并通过 G65 接收参数。
实际使用中两者界限并不清晰。很多系统允许子程序读取局部变量,所以简单的宏程序就是一个恰好用到 #24 和 #25 的子程序。如果代码需要数学运算或条件逻辑,就称它为宏程序,并存放在 O9000 号段。
子程序加工位置不对,怎么调试?
先检查子程序处于绝对还是增量模式。在开头加一行 G90 或 G91 再试。多数位置错误来自残留的 G91,而不是坐标写错。
如果模式正确,就看变量值。用 G65 调用时,在调用执行前到宏变量画面查看 #24 和 #25。数值正确说明错误在子程序内部;数值错误说明错误在调用程序段。
子程序可以嵌套吗?
可以。子程序能调用另一个子程序。多数 Fanuc 风格系统允许 4 层嵌套。有些系统把主程序算作第一层,有些不算,依赖这个限制前先在机床上实测。
嵌套时出现 P/S 报警,通常就是层数超限。把最内层顺序移到调用方以压平结构,或把任务拆到两个主程序。
使用子程序有哪些限制?
内存是一方面。每个子程序都占用系统内存,老系统内存很少。加工节拍是另一方面。G65 调用因参数处理比内联代码略慢。
更大的限制是可读性。一个编号背后做六件事的子程序,比六个短程序更难调试。每个子程序只做一件事,并把编号范围记录在全车间都能看到的地方。
工件坐标系偏置应该放在子程序里吗?
不要。G54 到 G59 保留在主程序中。偏置放在子程序里,每个调用它的程序都会继承该偏置。在一台机床上没问题,在另一台机床上就可能撞刀。
刀长偏置同理。在主程序中调用刀具和偏置,子程序只处理几何轨迹。
子程序返回后需要保留某个值怎么办?
用公共变量。多数系统在子程序返回时会清除局部变量 #1 到 #33。在 M99 之前把值写入 #100 或 #500,在主程序中读取。
公共变量在系统断电或手动清除前一直保留。用它做 24 次调用的计数器很方便,但下一件工件开头忘记清零就很危险。
