教导功能可以一条一条建立程序记录。加工向导采用另一种做法:操作者填写一组尺寸和工艺参数,由已经写好的宏程序计算整段刀路。
这篇用软件原有的铣矩形底讲清这个过程:从哪里输入,数值保存在哪里,“加载文件”怎样调用宏程序,宏里面的循环怎样变成文件中的一行行运动代码。先读懂现有设计,无需增加页面、按钮或参数。
进入 程序 → 加工向导 → 铣矩形底。上面一行选择加工种类,中间的“尺寸数据”填写尺寸和速度,左侧显示当前走刀方向的示意动画。
点击截图可查看原图。
图1 从标准程序页进入原有加工向导。右上角为“仿真”。本篇使用中间的尺寸数据和上方“加载文件”,下方MDI区域另有自己的“执行”按钮。
这里的加载文件不是让你选择一个已有文件。它先根据当前输入生成刀路文件,再把生成结果装入程序页。不要与文件管理中的选文件操作混淆。
先选择“横向”,按下表填写。每项输入后按回车或离开输入框,让数值写回参数。
| 页面上的名称 | 本例数值 | 看这个数值时要注意什么 |
|---|---|---|
| Y长度 | 48 | 矩形沿Y方向的尺寸 |
| X长度 | 66 | 矩形沿X方向的尺寸 |
| 开始坐标X | 10 | 矩形起始边角的X坐标,刀具中心还要加半径 |
| 开始坐标Y | 20 | 矩形起始边角的Y坐标,刀具中心还要加半径 |
| 刀具直径 | 6 | 宏直接用这个数值计算中心轨迹 |
| 每次下刀量 | 1 | 本例分两层下刀 |
| 底深度 | 2 | 输入正的深度,宏生成向负Z方向的下刀位置 |
| 刀尖间距 | 5 | 相邻走刀之间的横向步距,本例小于刀具直径 |
| 下钻速度 | 100 | 宏中下刀段使用的F值 |
| 铣底速度 | 600 | 宏中铣底段使用的F值 |
点击截图可查看原图。
图2 尺寸数据局部图。点击图文版中的图片可以放大。
这些数值用于说明计算关系,不作为特定材料或刀具的切削推荐。尺寸与进给应采用机台当前使用的单位;宏和输出文件没有另写G20/G21来切换单位。
选择“纵向”时,数值仍在,方向选择和示意动画一起改变。
点击截图可查看原图。
图3 横向与纵向共用同一组尺寸。本篇后面的代码采用横向,继续前先选回“横向”。
在空闲且已经解除复位的状态下,点击上方加载文件。生成结束后,页面切回刀路预览,当前文件变为 矩形铣底.nc,代码区显示展开后的运动指令。
点击截图可查看原图。
图4 刀路是按图2的尺寸生成的。预览采用俯视并调整了显示比例;不同缩放比例不会改变文件内容。两层刀路在俯视下会重叠,Z深度应结合代码查看。
本例生成文件的开头,按代码区的非空行列出,是:
G90G0Z5.000
M3S12000.000
G0X13.000Y23.000
G1Z-1.000
G1X73.000F600.000
G1Y28.000
G1X13.000
G1Y33.000
点击截图可查看原图。
图5 代码中的13、23、73以及Z−1、Z−2都能由输入值算出来。完整文件见本例生成代码。
这里先完成生成和检查。要加工这份文件,还要按已经学过的启动、暂停、恢复和停止操作,并确认工件坐标、刀具、主轴、退刀高度及进给。
当前输出有一个需要特别检查的地方: 首个下刀行 G1Z-1.000 没有显式F值,后面第二次下刀才出现 G1Z-2.000F100.000。不能用后面的F100来说明第一次下刀也一定采用100。执行前应确保首个切削进给已经明确;需要补写时,先另存加工副本,再补入所需F值。重新生成会覆盖同名输出文件。
下面的路径从软件运行目录开始,不是本书附件目录。
| 文件 | 负责什么 |
|---|---|
env/program/advancedpage |
第一次进入加工向导时装入页面,并准备MDI区域和初始动画 |
env/program/advanced.ui |
加工种类、尺寸输入框、方向选择及“加载文件”按钮 |
env/funcscripts/generatecode |
按当前种类选择宏文件,设置输出文件名并请求生成 |
env/macroMillRect.nc |
读取铣矩形底参数,计算刀具中心位置、层深和往返路线 |
env/timer |
生成流程空闲后,接过结果文件并切换到刀路预览 |
方向动画另由 env/program/advanced/millrect 选择。整个流程可以按下面的顺序读:
填写#2009 → 点击加载文件 → generatecode选中macroMillRect.nc → 宏计算各段运动 → 软件写出矩形铣底.nc → timer装入结果。
页面设置和 generatecode 是组态脚本;macroMillRect.nc 是NC宏程序。前者安排“用哪份文件、生成到哪里”,后者计算“刀路怎样走”。组态脚本发出生成请求后,不会在按钮脚本内部等到整段刀路完成。
在程序页切换中已经认识 #810:它在刀路预览、文件管理和加工向导之间选页。
进入加工向导之后,#812 再选择当前加工种类:
| #812 | 原有加工种类 | 输入参数 | 计算宏 | 输出文件名 |
|---|---|---|---|---|
| 0 | 割方形框 | #2007 | macroCutRect.nc |
割方形框.nc |
| 1 | 割圆形框 | #2008 | macroCutCircular.nc |
割圆形框.nc |
| 2 | 铣矩形底 | #2009 | macroMillRect.nc |
矩形铣底.nc |
| 3 | 铣圆形底 | #2010 | macroMillRound.nc |
圆形铣底.nc |
本篇详细读矩形铣底,其余三项先用于理解共同的入口安排。
“铣矩形底”控件 label_3 的点击设置为:
-A: (clickedEvent:/env/program/advanced/millrect[0](#812=2))
点击时先把 #812 设为2,再运行 millrect 准备对应动画。矩形输入区 frame_3 的显示设置为:
-C(#812==2) -V0
只有选择矩形铣底,这块输入区域才显示。相同做法也用于其他三种加工,所以一张UI可以放下四组不同的输入内容。
不要把 #812 的数值与它的其他字段混为一谈:#812.version 用于记录页面是否已经准备,#812.itemdesc[0] 存UI路径,#812.permission 则用于生成完成后的接续处理。它们服务于不同步骤。
例如X长度输入框 lineEdit_13 的属性是:
-T(#2009item2)
-D
这里的 #2009item2 对应脚本中的 #2009.item[2]。-T 指出显示和编辑的参数字段,-D 让控件随参数刷新。没有另外给这个输入框安排“计算X长度”的按钮脚本,普通输入确认直接写回该字段。
旁边的文字标签读取 #2009.itemtitle[2],所以“X长度”和数值66来自同一参数项的不同字段。切换语言可以改标题,而不改尺寸的存放位置。
| #2009字段 | 界面用途 | 宏中读入的局部变量 |
|---|---|---|
item[0] |
0横向,1纵向 | #9 |
item[1] |
Y长度 | #6 |
item[2] |
X长度 | #5 |
item[3] |
开始坐标X | #1 |
item[4] |
开始坐标Y | #2 |
item[5] |
刀具直径 | #8 |
item[6] |
每次下刀量 | #4 |
item[7] |
底深度 | #3 |
item[8] |
刀尖间距 | #7 |
item[9] |
下钻速度 | #30 |
item[10] |
铣底速度 | #31 |
这些是标准组态已经定义好的参数,不要为学习本例重新分配#2009。阅读时也不要按页面的视觉排列推测下标:页面先显示Y长度,但X长度用的是下标2。
横向按钮赋值 #2009item0=0,纵向按钮赋值 #2009item0=1,两者随后都调用 millrect。
下面是这个脚本的完整内容:
IF#2009.item[0]==0GOTO1
widgetFunc["Label","millRectLabel","setMovie","images/纵向矩形铣底.gif"]
GOTO2
N1
widgetFunc["Label","millRectLabel","setMovie","images/横向矩形铣底.gif"]
N2
widgetFunc["Label","millRectLabel","playMovie",0]
setMovie 为原有的 millRectLabel 选动画,playMovie 开始显示动画。两个方向各用一份现成GIF,它们不根据当前66×48的尺寸重新绘制,作用是说明走刀方向。
计算宏开头又读取同一个字段:
#9=#2009.item[0];路径方式 #9 0-横 1-纵 #9
后面用 IF#9==1GOTO20 进入纵向分支。这样,选择状态、示意动画和计算方向都有共同的依据;只换动画不会改变生成刀路。
按钮 pushButton 的完整操作属性是:
-T(#1100itemtitle50)
-C(#319item3==1||#319item7==1)
-E0
-A: (clickedEvent:/env/funcscripts/generatecode[1])
-D
标题来自公共文字参数。正在运行或处于暂停状态时,按钮被禁用;点击后运行 generatecode。按钮的事件通道编号沿用标准设置,不应与加工种类的0、1、2、3混用。
generatecode 先检查忙状态,再根据 #812 找到对应段落。矩形铣底的原段落如下:
N2
#331.item[2]=1;清除画板
#100=#405+"macroMillRect.nc"
#334.itemnum=0
#334.item[1]=#100
#9047=#100
#9048.channel=0
#9048.permission=widgetFunc["getFileLineNum","","",#100]
#403=#100
#319.item[17]=1;生成路径代码
#319.item[18]=0;正向路径代码
#319.item[19]="矩形铣底.nc";路径代码名称
#319.item[20]=0;关闭逆向加工
#319.item[4]=1;宏解析
IF#324.item[12]==1THEN#319.item[11]=1;仿真
#319.item[10]=0;MDI
#319.item[9]=0;取消恢复加工
#319.item[3]=1;解释器启动
#812.permission=1;设置生成代码标志,定时脚本中处理
GOTO1
这是完整脚本中的矩形分支节选,前面的选择判断和最后的 N1 还在原文件中,不能把节选单独保存为替换脚本。
按用途分成三部分读就容易了:
#100 得到源宏路径,#334、#403、#9047 等准备当前文件及代码区。#319.item[17~20] 指定生成代码、正向、输出名称及逆向开关;其中17为生成开关,不是画面上的仿真开关11。#812.permission=1 告诉后续脚本还有结果要接收。原注释“MDI”后面的赋值是0,应按实际数值理解为非MDI。本分支直接以宏为源文件,不把它作为普通的立即执行脚本。宏里面有IF、GOTO和WHILE,软件会先扫描程序结构,建立标号与循环的对应关系,再执行计算。前面的加工运行篇讲过这两种文件处理方式。
关键是先把NC解释器设为生成代码方式,再让它执行这份宏。 generatecode 负责准备这些设置,软件内置的NC解释器负责计算刀路和写文件。macroMillRect.nc 本身不需要逐行调用写文件函数。
下面几项必须放在一起理解:
| 设置 | 在本次生成中的作用 |
|---|---|
#403=#100 |
指定本次读取的源文件,即macroMillRect.nc的路径 |
#319.item[4]=1 |
先扫描宏的程序结构,再按宏规则执行分支、循环和表达式 |
#319.item[10]=0 |
选择文件运行方式;本例的刀路转代码处理要求处于非MDI模式 |
#319.item[17]=1 |
开启刀路代码生成;计算出的普通运动段将收集成G代码文本 |
#319.item[18]=0 |
按正向顺序生成;与横向、纵向走刀无关 |
#319.item[19]="矩形铣底.nc" |
指定输出文件名;它与#403中的输入宏文件是两个不同用途的路径 |
#319.item[20]=0 |
本次读取原源文件,不按逆向加工文件运行 |
#319.item[3]=1 |
前面准备好之后,请求NC解释器开始工作 |
这些字段是软件内部直接读取的控制值。给它们赋值后,NC调度线程会接到请求;按钮脚本随后可以结束,计算继续在NC解释器中进行。所以,必须先选好文件和生成方式,再设置启动值。
仿真与生成代码是两项独立设置。 #319.item[11] 控制仿真,#319.item[17] 控制生成。只切到“仿真”不会自动产生矩形铣底.nc;只把文件名写入item[19],也不会触发文件生成。
从一次正常的矩形铣底生成来看,顺序如下:
timer才接收文件并切换页面;第10节说明这部分衔接。这里仍然在执行NC宏:赋值、条件判断和循环都有实际作用,变化的是普通刀路结果的去向。生成开关不等于禁用任意宏中的全部外部操作;扩展这类向导时,应沿用本例的尺寸计算和走刀写法,另外核对所加入的M代码、IO或外部调用。
完整原宏见 macroMillRect.nc。下面按计算顺序解读,不要求记住所有局部变量号。
宏先把第6节的参数读入#1、#2等局部变量,然后用:
G0X#1+#8/2Y#2+#8/2
本例刀具半径为3,因此第一处XY位置为 (10+3,20+3)=(13,23)。矩形起始坐标是边角位置,刀具中心从边角内移半径后开始。
接着计算中心可以移动的长度:
#11=#5-#8
#12=#6-#8
X方向为 66−6=60,Y方向为 48−6=42,所以本例中心范围为X13~73、Y23~65。这里直接扣除了刀具直径,不是把刀具直径交给G41/G42处理。
横向分支先计算:
#13=ROUND[#12/#7]+1
#14=#12-[#13-1]*#7
本例 42/5=8.4,ROUND后为8,所以#13为9,余下的#14为2。内层循环的完整片段是:
#15=#13
WHILE#15>0DO1
G91X#11F#31
#11=-#11
IF#15==1GOTO2
G91Y#7F#31
N2#15=#15-1
END1
第一段沿X走60,下一段把#11变成−60,于是X来回换向。除循环的最后一次外,每次再沿Y步进5;#15每次减1,用完9次后离开循环。
循环后还执行:
G91Y#14F#31
G91X#11F#31
#11=-#11
#7=-#7
#14=-#14
这段补上余下的2,再走一次X。随后把Y步距和余量改为相反数,为下一层从另一侧走回去做准备。不要只摘走WHILE循环,漏掉循环后的余量处理。
宏首先取“每次下刀量”和“底深度”中较小的值作为第一层深度#16,再执行:
N11G1Z-#16F#30
本例第一次下到Z−1。一层横向路线完成后,#16再加每次下刀量;超过总深度时改为总深度,再进入下一层。所以本例第二层为Z−2。
外层用 WHILE#16<=#3DO2 控制,结束时通过改变#16退出循环;纵向分支用DO4控制层深,DO3控制层内Y往返。纵向时变成沿Y走42、沿X步进,不能只把页面上的“横向”文字改成“纵向”。
宏中的 G91X#11,在本例输出中已经变成 G1X73.000、G1X13.000 等绝对位置。输出文件开头有G90,不能看到源宏用G91,就认为结果文件也在按增量执行。
软件根据计算出来的运动段写出G代码,因而结果文件不保留这段宏的WHILE、IF或#11。它也不是把所有宏语句原样复制一次。
用本例第一层的几个步骤对照就很直观:
| 宏执行到哪里 | 解释器算出的结果 | 写进结果文件的内容 |
|---|---|---|
G0X#1+#8/2Y#2+#8/2 |
刀具中心到X13、Y23 | G0X13.000Y23.000 |
第一次执行G91X#11F#31 |
从X13增量走60,到X73,F为600 | G1X73.000F600.000 |
#11=-#11 |
把下一次的X增量改成−60 | 这条赋值本身不生成运动代码行 |
G91Y#7F#31 |
从Y23增量走5,到Y28 | G1Y28.000 |
下一次执行G91X#11F#31 |
从X73增量走−60,回到X13 | G1X13.000 |
因此,宏中同一行可以生成许多条不同的结果行。软件根据已经求出的坐标写出本例的绝对位置,并省略未改变的坐标字和部分重复的F值。第3节首个下刀缺少显式F,正是阅读输出文件时需要检查的细节,不能只看源宏中写了F#30。
同样,#5996.title和description里的M3、M30是准备写入文件的字符串内容;在赋值这两个字段时,并不是执行字符串里面的M指令。需要保留在结果中的头尾指令,由这些文本字段明确提供。
宏开头除了读尺寸,还设置两段文本:
#5996.title="G90G0Z"+#330.item[56]+"
M3S"+#330.item[14]+"
"
#5996.description="G90G0Z"+#330.item[56]+"
M30
"
#5996.title 是文件头,#5996.description 是文件尾。正向生成结束时,软件按“文件头 → 计算得到的运动代码 → 文件尾”写文件。本例对应Z5和S12000,这两个数来自机台参数#330,并不在图2的尺寸输入区里。
因此,读一个向导时要同时找出页面输入和其他参数来源。只抄中间几行循环,无法得到与标准向导相同的完整结果。
本例的运动代码先收集在内存中,源宏解析返回后才统一写到磁盘。写文件的是软件内置的NC处理流程,generatecode只给出设置,timer只接收写出的结果。
正常结束时,可按下面的先后关系理解:
| 顺序 | 正在做什么 | 此时的意义 |
|---|---|---|
| 1 | 执行macroMillRect.nc,收集运动代码 |
生成过程尚未结束,同名旧文件不能当成本次结果 |
| 2 | 按item[19]打开文件,写入头、运动代码、尾并关闭 | 本次输出已进行文件写入 |
| 3 | 调度end.nc,再转到safez.nc完成收尾 |
原标准脚本会识别生成状态,跳过相应的普通加工处理;safez.nc清除生成开关并放弃继续启动 |
| 4 | NC运行结束,timer处理#812.permission |
装入结果文件,切换到刀路预览 |
这条顺序说明了为什么按钮脚本不能在设置启动后紧接着读取结果,也不应在发出请求后立即把item[17]清零。标准结束流程负责结束生成状态;要保留这些衔接。
输出采用覆盖写入,同名旧文件不会自动备份。异常中断后,内置写出分支仍可能把已经收集的部分代码写入文件;因此,文件存在、运行结束或页面已切换,都不能单独证明生成完整。应结合报警、尺寸范围、层数及代码头尾检查本次结果。
生成需要时间,#812.permission=1 表示后面需要接收结果,不表示文件已经写完。
env/timer 的这一组处理位于“运行时先跳过”的判断之后:
IF#319.item[3]==1GOTO1
进入空闲处理区后,结果接收段再检查:
IF#812.permission==0GOTO1
#812.permission=0
#334.itemnum=0
#334.item[1]=#319.item[19]
#9047=#319.item[19]
#9048.channel=0
#9048.permission=widgetFunc["getFileLineNum","","",#319.item[19]]
#403=#319.item[19]
#5999.itemnum=0
#[6001+#9047.permission].itemnum=0
#810.permission=0
#810=0
上面是两个位置的节选,不能直接连起来替换完整的timer。接收段清掉标记,装入输出路径,更新代码区,并用 #810=0 回到刀路预览。
输出名称 矩形铣底.nc 没有带 env/。它是相对软件当前工作目录的路径,不是覆盖 env/macroMillRect.nc。再次生成同一类型会写同名文件,要保留上一份结果应先另存。
接收段后还有 #929.item[4] 判断:启用对应的逆向处理时,会继续生成 planning.nc,并把生成方向设为逆向。它属于后续处理,与尺寸区的“横向/纵向”不是同一个方向。本例保持这项后续处理关闭。
| 想调整什么 | 先看哪里 | 还要一起核对什么 |
|---|---|---|
| 页面名称或输入名称 | UI中的文字来源、#2009.title及itemtitle | 中英文语言文件,不能只改UI的设计时文字 |
| 输入值存放位置 | QLineEdit的-T(...) |
宏开头读取的是不是同一个字段 |
| 横向、纵向的说明动画 | advanced/millrect和原GIF |
动画表达的方向是否与宏分支一致 |
| 层深、步距、往返规则 | macroMillRect.nc |
局部变量含义、余量处理、退出条件、最终范围 |
| 输出文件名 | generatecode中的#319.item[19] |
重名覆盖、路径位置,以及生成后的文件加载 |
| 文件头和文件尾 | 宏中的#5996两个文本字段 | 退刀、主轴、单位、坐标与首个切削进给 |
先调整一个明确的要求,再用容易手算的小尺寸对照代码和预览。页面输入、动画、计算宏、输出文本各有作用;找到真正决定行为的那一处,修改才容易核对。
| 现象 | 检查顺序 |
|---|---|
| 改了输入,结果还是上一份 | 先确认输入,再重新点“加载文件”;修改参数不会自动重写结果文件 |
| “加载文件”不能点击 | 查看是否正在运行或暂停 |
| 按钮可以点,生成却不开始 | 查看是否仍处于复位;按钮禁用条件没有包含所有NC运行条件 |
| 页面切过去了,但文件为空或不是预期结果 | 查看生成时的报警、输出路径与写入权限;接收标记和切页动作不等于文件正确 |
| 方向动画变了,计算方向没变 | 对照#2009.item[0]、#9及宏的分支,不能只更换GIF |
| 刀路比输入矩形小一圈 | 本例绘制的是刀具中心路线,X、Y总长各扣除了一个刀具直径 |
| 俯视只像一层 | 两层XY轨迹重叠;看Z−1、Z−2或改变观察角度 |
| 首次下刀速度不明确 | 检查输出文件首个G1之前或该行是否已明确F值 |
输入前还应检查:刀具直径小于两个方向的尺寸;下刀量、总深度、步距和速度为合理正值。原宏没有为每一种无效组合提供专门提示,步距为0会进入除法问题,下刀量为0也不具备正常逐层退出的条件。
余量计算采用ROUND而不是统一向下取整,因此换一组尺寸后,要按原公式检查最后一个步距和边界。本例42÷5的余量为正2,不能据此推断所有尺寸都会得到正余量。
读懂这个向导后,你已经能把原生页面、参数、NC宏、输出文件和加载操作连起来。下一篇继续看DXF:输入从尺寸数值换成图形数据时,怎样接回相同的程序使用流程。