从零开始学数控编程与操作
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

第3章 子程序与宏程序

3.1 子程序与宏程序基础

3.1.1 子程序

(1)子程序的概念

在一个加工程序中,若有几个完全相同的部分程序(即一个零件中有几处形状相同,或刀具运动轨迹相同),可以把这部分程序单独抽出,编成子程序存在存储器中,需要使用时加工程序用一条简单指令即可调出应用,从而简化编程。

(2)子程序的结构

O××××;      子程序号

…  子程序内容

M99;  子程序结束,从子程序返回到主程序,是子程序最后一个程序段

(3)调用子程序指令

调用子程序的指令是:M98 P×××× ××××;

地址“P”后的前1~4位数字为子程序重复调用次数,省略时默认为调用一次。后四位数字(必须4位)为子程序号。即:


例如:调用子程序指令:

M98 P61020;  调用1020号子程序,重复调用6次(执行6次)

M98 P1020;  调用1020号子程序,调用1次(执行1次)

M98 P5001020;  调用1020号子程序,重复调用500次(执行500次)

允许重复调用子程序最多999次。为与自动编程系统兼容,在子程序中的第1个程序段顺序号——“N××××”,可以用来替代地址“O”后的子程序号,即用子程序中的第1个程序段的顺序号作为子程序号。

主程序调用子程序的执行顺序如图3⁃1所示。

图3⁃1 主程序调用子程序的执行顺序

子程序可以由主程序调用,被调用的子程序也可以调用另一个子程序,称为子程序嵌套。被主程序调用的子程序称为一级子程序,被一级子程序调用的子程序称为二级子程序,以此类推。子程序调用,可以嵌套4级,如图3⁃2所示。

图3⁃2 子程序嵌套

(4)从子程序返回

M99是子程序结束指令,该指令使执行顺序从子程序返回到主程序中调用子程序段之后的程序段,该指令可以不作为独立的程序段编写,例如:“G00 X100.0 Y100.0 M99;”。

(5)只使用子程序

调试子程序时,希望能够单独运行子程序,用MDI检索到子程序的开头,就可以单独执行子程序。此时如果执行包含M99的程序段,则返回到子程序的开头重复执行;如果执行包含“M99 Pn”的程序段,则返回到在子程序中顺序号为n的程序段重复执行。要结束这个程序,必须插入包含“/M02” 或“/M30”的程序段,并且把任选程序段开关设为断开(OFF),如图3⁃3所示。

图3⁃3 单独运行子程序

3.1.2 用户宏程序

宏程序是数控系统厂家面向客户提供的二次开发工具,是数控机床编程的最高级手工方式,合理有效地利用这个工具将极大地提升机床的加工能力。

普通程序中指令和数据均为常量,一个程序只能描述一个几何形状,普通程序不允许使用变量,程序只能按程序段排列的顺序运行。用户宏程序中允许使用常量、变量、算术、逻辑运算和条件转移,所以宏程序能够控制程序运行的流向,实现程序段运行次序的转移和循环功能。宏程序与子程序类似,可以被任一个数控程序调用。编制相同加工操作的程序时,可将相同加工操作编为通用程序,如型腔加工宏程序、固定加工循环宏程序等,加工程序中需要该类加工时只需用一条指令调出用户宏程序,和调用子程序完全一样,如图3⁃4所示。

图3⁃4 加工程序中调用宏程序

用户宏程序分为A、B两类。通常情况下,FANUC 0D系统采用A类宏程序,而FANUC 0i系统则采用B类宏程序。A类宏程序功能不直观,可读性差,在实际工作中很少使用。由于绝大部分FANUC系统支持B类宏程序,所以,本书以B类宏程序为基础,阐述宏程序知识与应用。

3.1.3 常量、变量

普通程序中指令和数据均为常量,即用数值指定G代码和移动距离,例如程序段:

G00 X150.0;

使用变量的宏程序编写该程序段:

N10 #1=150.0;  #1是一个变量

N20 G00 X[#1];  #1是一个变量

上述程序中,#1是变量,N20程序段中用变量代替了常量(距离150mm),实际上变量还可以代替刀补号、G指令编号等数据。用户宏程序中数据可以用常量直接指定,也允许用变量指定。变量值可用程序赋值,或通过MDI面板上的操作改变变量的值。变量的使用给程序的设计带来了极大的灵活性。

(1)变量的表示形式

宏程序中,用“#”号后面紧跟1~4位数字表示一个变量,如#1,#50,#101是变量。其中“#”号是变量符号,数字是变量号。

变量号可以用表达式指定,此时表达式必须放在括号中,例如变量:#[#1+#2-12],其中:


使用变量前,变量必须带有正确的值。如下述宏程序:

#1=25;  使#1为25

G01 X[#1];  表示G01 X25

#1=110;  运行过程中可以随时改变#1的值

G01 X[#1];  表示G01 X110

(2)变量类型

变量根据变量号可以分成以下四种类型。

① 空变量。#0为空变量,该变量总为空,不能赋值。

② 局部变量。编号#1~#33的变量为局部变量,局部变量的作用范围是当前程序(在同一个程序号内),如果在主程序或不同子程序里,出现了相同名称(编号)的局部变量,它们不会相互干扰,值也可以不同。系统断电后,局部变量数据初始化为空。举例如下。

O100;

N10 #3=30;  主程序中变量#3为30

M98 P101;  进入子程序后变量#3不受影响

#4=#3;  #3仍为30,所以#4=30

M30;

O101;

#4=#3;  这里的#3不是主程序中的#3,所以#3=0(没定义),则:#4=0

#3=18;  这里使#3的值为18,不会影响主程序中的#3

M99;

③ 公共变量。#100~#199、#500~#999为公共变量。公共变量在不同的宏程序中意义相同,作用范围是整个零件程序,即不管是主程序还是子程序,只要名称(编号)相同就是同一个变量,带有相同的值,在某个地方修改它的值,所有其他地方都受影响。当断电时,变量#100~#199被初始化为空,变量#500~#999的数据不会丢失。例:

O1100;  主程序号

N10 #120=30;  使#120为30

M98 P101;  进入子程序(注:在子程序O101中#120为18)

#4=#120;  由子程序O101返回,#120变为18,所以此时#4=18

M30;  程序结束

O101;  子程序号

#4=#120;  #120的值在子程序里也有效,所以#4=30

#120=18;  这里使#120=18,然后返回

M99;  子程序结束

④ 系统变量。#1000以上的变量为系统变量,系统变量用于读和写CNC运行时的各种数据,如刀具的当前位置和补偿值等。系统变量是数控系统内部定义好了的,用户不可以改变它们的用途。系统变量是全局变量,使用时可以直接调用。

(3)变量的引用

① 为了在程序中使用变量,必须在程序中指定变量号的地址,给变量赋值。没指定的变量地址为无效变量。

② 当用表达式指定变量时,必须把表达式放在括号中。例如“G01 X[#1+#2] F#3”。

③ 被引用变量的值根据地址最小设定单位自动地舍入。例如指令“G00 X#1”,X地址最小设定单位为1/1000mm,当CNC把“12.3456”赋值给变量#1,实际指令值为“G00 X12.346”。

④ 改变引用变量值的符号,要把负号“⁃”放在“#”的前面。例如“G00 X⁃#1”。

⑤ 当引用未指定的变量时变量及地址字都被忽略,或称没指定的变量为空变量。

例如,当变量#1的值是0,并且变量#2的值是空时,“G00 X#1 Y#2”的执行结果为“G00 X0”。

注意“变量的值是0”和“变量的值是空”是不同的,“变量的值是0”是指把0赋值给某变量,所以该变量的值等于数值0,而“变量的值是空”指该变量所对应的地址不存在,是无效的变量。

(4)变量值的精度

变量值的精度为8位十进制数。

例如,用赋值语句#1=9876543210123.456时,实际上#1=9876543200000.000。

用赋值语句#2=9876543277777.456时,实际上#1=9876543300000.000。

(5)赋值

把常数或表达式的值送给一个宏变量称为赋值,赋值号为:“=”。

格式:宏变量 = 常数或表达式。例如:

#2 =SQRT[2] *COS[55 *PI/180 ]

#3 = 124.0

#50 = #3+12

赋值号后面的表达式里可以包含变量自身,如:#1=#1+4,该表达式是把#1的值与4相加,结果赋给#1。这不是数学中的方程或等式,如果#1的值是2,执行#1 = #1+4后,#1的值变为6。

(6)变量限制

程序号、顺序号和任选程序段跳转号不能使用变量,例如在以下方式中不可使用变量:

O#1

/#2 G00 X100.0

N#3 Z200.0

3.1.4 变量的算术和函数运算

(1)算术运算符

变量算术运算符:“+”“-”“*”“/”。

(2)函数

宏程序中的变量可以进行函数运算,函数运算符:SIN(正弦)、COS(余弦)、TAN(正切)、ATAN(反正切-π/2~π/2)、ABS(绝对值)、INT(取整)、SIGN(取符号)、SQRT(开方)、EXP(指数)。

(3)表达式

用运算符连接起来的常数、宏变量构成表达式。例如:

175/SQRT[2] *COS[55 *PI/180];

#3 *6 GT 14;

表达式中用方括号表示运算顺序。宏程序中不用圆括号,规定圆括号中的内容是注释。

(4)运算符的优先级

运算符优先级顺序依次为:方括号→函数→乘除→加减→条件→逻辑。

宏程序中的变量可以进行算术运算和函数运算,如表3⁃1所示。

表3⁃1 算术与函数运算功能

3.1.5 宏程序语句和NC语句

下面的程序段为宏程序语句。

•包含算术或逻辑运算(=)的程序段。

•包含控制语句(例如:GOTO,DO,END)的程序段。

•包含宏程序调用指令(例如:用G65,G66,G67或其他G代码、M代码调用宏程序)的程序段。

除了宏程序语句以外的任何程序段都为NC语句。

3.1.6 转移和循环

(1)条件运算符

条件运算符用在程序流程控制IF和WHILE的条件表达式中,作为判断两个表达式大小关系的连接符。条件运算符:


  注: EQ—equal;NE—not equal;GT—greater than;GE—greater than or equal;LT—less than;LE—less than or equal。

(2)逻辑运算符

在IF或WHILE语句中,如果有多个条件,用逻辑运算符来连接多个条件。逻辑运算符:

AND (且):多个条件同时成立才成立;

OR(或):多个条件只要有一个成立即可;

NOT(非):取反(如果不是)。

例如:

#1 LT 50 AND #1 GT 20   表示:[#1<50]且[#1>20]

#3 EQ 8 OR #4 LE 10  表示:[#3=8]或者[#4≤10]

有多个逻辑运算符时,可以用方括号来表示结合顺序,如:

NOT[#1 LT 50 AND #1GT 20]  表示:如果不是“#1<50 且 #1>20”

(3)转移和循环

数控程序一般按程序段排列的先后顺序运行,称为顺序程序结构,在宏程序中使用GOTO语句和IF语句,可以控制程序运行的流向,实现程序段运行次序的转移和循环功能,称为分支程序结构和循环程序结构。有三种转移和循环指令,即:

① GOTO语句。无条件转移。

② IF语句。条件转移,“IF…THEN…”。

③ WHILE语句。循环语句,当…时循环。

(4)无条件转移(GOTO)

格式:GOTOn;

n为顺序号(1~9999)。

转移到标有顺序号n的程序段,当指定1~9999以外的顺序号时,出现P/S报警NO.128。

例如:GOTO6;

语句组:N6 G00 X100;

执行GOTO6语句时,转去执行标号为N6的程序段。

可用表达式指定顺序号,例如:GOTO #10。

(5)条件转移(IF)

格式:IF[关系表达式] GOTOn;

例如,“IF[#1 GT 210] GOTO2;”。

语句组:N2 G00 G91 X10.0;

解释:如果变量#1的值大于20,转移执行标号为N2的程序段,否则按顺序执行GOTO2下面的语句组,如图3⁃5所示。

图3⁃5 “IF[关系表达式] GOTOn”语句

(6)条件转移(IF…THEN…)

格式:IF[条件表达式] THEN  (注:THEN后只能跟一个语句)

如果条件表达式满足,执行预先定义的宏程序语句,只执行一个宏程序语句。

例如,“IF[#1 EQ #2] THEN #3=0;”。

当#1的值等于#2的值时,将0赋给变量#3。

例3⁃1:编宏程序,计算自然数1到10的累加总和,宏程序如下。

O6000;  宏程序名

#1=0;  存储和数变量的初值

#2=1;  被加数变量的初值

N1 IF[#2 GT 10] GOTO2;  当被加数大于10时转移到N2

#1=#1+#2;  计算累加和数(该语句为累加器)

#2=#2+1;  下一个被加数(该语句为计数器)

GOTO1;  转到标号N1段

N2 M30;  程序结束

(7)循环(WHILE)

格式:WHILE[关系表达式] DOm;(m=1,2,3)

循环区语句组;

END m;

在WHILE 后指定一个条件表达式,当指定条件满足时,执行从DO 到END之间的程序,否则转去执行END后面的程序段,如图3⁃6所示。DO后的m和END后的m,是指定程序执行范围的标号,m标号值为1、2、3,m若用1、2、3 以外的值会产生P/S报警NO.126。

图3⁃6 WHILE语句执行顺序

例如宏程序:

#1=5;

WHILE[#1 LE 30] DO1;

 #1=#1+5;

 G00 X#1 Y#1;

END1;

M99;

上述宏程序含义:当变量#1的值小于等于30时,执行循环程序,当#1大于30时结束循环返回主程序。

例3⁃2:用WHILE语句编宏程序,计算自然数1~10的累加总和。

宏程序如下。

O3000;  宏程序名

#1=0;  存储和数变量的初值

#2=1;  被加数变量的初值

WHILE[#2 LE 10] DO1;  当被加数小于10时执行循环区程序

#1=#1+#2;  计算累加和数(该语句称为累加器)

#2=#2+1;  下一个被加数(该语句称为计数器)

END1;  循环区终止

M30;  程序结束

3.1.7 宏程序调用

调用宏程序的方法有:非模态调用(G65);模态调用(G66、G67);用G代码调用宏程序;用M代码调用宏程序;用M代码调用子程序;用T代码调用子程序。为减轻读者负担,本书只推荐非模态调用(G65)。

(1)宏程序非模态调用G65

① 调用指令格式:

G65 P(p) L(l) (自变量赋值);

其中,p为调用的程序号;l为重复次数;自变量赋值为传递到宏程序的数据。

宏程序与子程序相同,一个宏程序可被另一个宏程序调用,最多嵌套4层。

G65指令调用以地址P 指定的用户宏程序,数据自变量能传递到用户宏程序体中,调用过程如图3⁃7所示。

图3⁃7 宏程序非模态调用G65执行过程

② 宏程序的开始与返回。宏程序的编写格式与子程序相同。其格式为:

O0010;(0001~8999为宏程序号)     程序名

N10…;     程序指令

N30 M99;     宏程序结束

宏程序以程序号开始,以M99结束。


(2)G65指令说明

① 在G65之后用地址P指定用户宏程序的程序号。

② 当要求重复时,在地址L后指定从1~9999 的重复次数,省略L值时认为L等于1。

③ 使用自变量指定,其值被赋值到相应的局部变量。

(3)自变量指定

可用两种形式的自变量指定。自变量指定Ⅰ使用除了G、L、O、N和P 以外的字母,每个字母指定一次,自变量指定Ⅱ使用A、B、C和Ii、Ji和Ki,其下标i=1~10,系统根据使用的字母自动决定自变量指定的类型。

① 自变量指定Ⅰ。表3⁃2为自变量指定Ⅰ的自变量与变量的对应关系。

a.自变量指定Ⅰ中,G、L、O、N、P不能用,地址I、J、K必须按顺序使用,其他地址顺序无要求。

举例:G65 P3000 L2 B4 A5 D6 J7 K8;         正确(J、K符合顺序要求)

在宏程序中将会把4赋给#2,把5赋给#1,把6赋给#7,把7赋给#5,把8赋给#6。

举例:G65 P3000 L2 B3 A4 D5 K6 J5;         不正确(J、K不符合顺序要求)

b.需要指定的地址可以省略,对应于省略地址的局部变量设为空。

c.不需要按字母顺序指定,但应符合字地址的格式。但是I、J和K需要按字母顺序指定。

表3⁃2 自变量指定Ⅰ的变量对应关系

② 自变量指定Ⅱ。表3⁃3为自变量指定Ⅱ的自变量与变量的对应关系。自变量指定Ⅱ中使用A、B、C各1次,使用I、J、K各10次。自变量指定Ⅱ用于传递诸如三维坐标值的变量。

表3⁃3 自变量指定Ⅱ的变量对应关系

  注:表中I、J 、K的下标用于确定自变量指定的顺序,在实际编程中不写。

③ 自变量指定Ⅰ、Ⅱ的混合。系统能够自动识别自变量指定Ⅰ和自变量指定Ⅱ,并赋给宏程序中相应的变量号。如果自变量指定Ⅰ和自变量指定Ⅱ混合使用,则后指定的自变量类型有效。


说明:I4.0为自变量指定Ⅱ,D为自变量指定Ⅰ,数值4.0和5.0都赋值给变量#7,但后者有效,所以变量#7中为5.0,而不是4.0。

④ 小数点的位置。一个不带小数点的数据在数据传递时,其单位按其地址对应的最小精度解释,因此,不带小数点的数据,其值在传递时有可能根据机床的系统参数设置而被更改。应养成在宏调用参数中使用小数点的好习惯,以保持程序的兼容性。