搜索
bottom↓
回复: 24

转 使用补偿修正方法解决Z轴零平面不平问题,特别适用于...

[复制链接]

出0入188汤圆

发表于 2012-12-30 23:09:59 | 显示全部楼层 |阅读模式
转自:http://bbs.cdle.net/thread-47293-1-1.html


一、背景
      小哥爱好机械,但不是科班出身,所掌握的只是当年工科大学生金工实习所学皮毛,如果后面写了什么外行的话请理解。自己不会做,所以上个月购买了一台商品雕刻机,外观还美观,我这种外行用起来感觉性能还行。慢慢在论坛里学习,慢慢改良自己的机器和技能,先后自行加了三个轴的机械限位及Z轴对刀功能,没办法,老撞车,伤不起。
       小哥常玩的是电子和电脑,雕刻机用来用去也只有雕刻PCB最多。但PCB这东西实际雕刻起来最麻烦的是工件加工平面的不平整,一个原因是雕刻机本身的载物台不平,另一个是PCB很难装夹平整。论坛上常用的解决思路有:1、调校载物台至尽量平整,阿莫那边说是能调校到0.01mm精度。2、在软性载物台上铣一个绝对平面。以上两种方法只能有效解决第一个原因所致的加工平面不平问题,而难以应对第二个原因。因为PCB的装夹常用机械压夹或者不干胶大法,我这样初学者实际用起来很难有效保障精度,特别是比较薄的PCB变形非常严重,使用手上唯一测量工具卡尺不严谨的测量过,我这台机器因本身的载物台不平所带来的误差也就0.1mm左右,但PCB的变形在加工范围内经常高达0.5-1.0mm也不足为奇,相对PCB板下刀深度仅为0.1-0.2mm而言,这样大的误差直接导致手上重金购置的雕刻机无法雕刻出合格的PCB电路板。
      相信很多初学者有跟我一样的困扰,如何解决因加工平面不平问题?小哥不擅长机械,所以只得从软的方面去琢磨,得到了一个使用算法补偿修正的方法,经过试用,方法简单、普适及有效,不敢独享,全盘奉献给各位同好。
二、原理
     PCB工件平面的变形各式各样,不遵守严格的规律。但从微分的角度上看,在指定加工精度(比如0.1-0.2mm)情况下,我们可以认为在一个足够小(比如5mm*5mm)的加工范围,PCB的工件平面的变形仅是一个简单的平面倾斜。换而言之,在这个足够小的加工范围内,PCB工件平面各点处处共面,只不过这个平面相对加工的绝对平面有一定的倾斜。这个结论针对不是绝对柔性的工件而言是显然的。
     从上面结论出发,我们只需要在需要加工的范围内取样足够数量的加工平面样本点Si (xi,yi,zi),针对一个加工点A(x,y,z),找到距离该点最近的3个样本点Si ,使用这3个样本点构制一个平面(三点确定一个平面),得到该平面的方程,因为认为加工点A就落在这个平面上,所以将加工点A的xy轴坐标代入所得到的平面方程,就能得到一个新的z轴坐标值z`,接下来修正加工点A的实际加工坐标点为(x,y,z`),也就是说,让雕刻机在x,y位置上实际下刀深度为z`,最后雕刻出来的效果即会有一个深度为原来的需求值z的刀路。
三、实现
      雕刻PCB,我采用的是用protel99se输出dxf文件,使用ArtCAM导入矢量后产生刀路(前后要删去几行关于相对坐标设置等代码,论坛中有介绍),再通过Mach3控制雕刻机完成加工。要实现上述补偿修正方法,我的步骤是:
     1、装夹好PCB板,连接好对刀线路,对刀线路两个端子一端在刀头,一端在PCB铜箔。在加工零点处进行z轴对刀;
     2、我在林大夫的Mach3对刀界面上增加了z轴校零功能(界面及代码文件见附件1),在该Mach3界面上相应输入框内设置z轴校零范围,该范围要稍大于实际加工范围,比如设置x最大为100mm,y最大为120mm,步长为5mm(见图1. Mach3校零界面示意所示);
                                   
                               图1. Mach3校零界面示意.jpg
     3、此时保持对刀线路工作正常,点击z校零按钮后,雕刻机会在x从0至100mm,y从0至120mm的范围内,每隔5mm步长抬刀、落刀进行z平面零点的取样。注意:只能指定x和y的最大值,x和y的最小值默认为0,不能修改。这只是个人使用习惯问题,并不会影响雕刻的实现;
     4、耐心等到所有取样完成后,刀头会退回到加工零点,Mach3界面上会提示所有样本数据已经保存到CNCZ0fix.z0f文件中。CNCZ0fix.z0f在Mach3安装目录下,比如C:\Mach3,实在找不到就搜索一下。
     5、启动程序Z0Fix.exe(程序见附件2,附图见图2),该程序的功能是根据之前的取样数据,读取并修改加工源文件G代码坐标数据,补偿其中的z轴下刀深度,并为了保证精度,还会对水平加工距离较长(暂时设置为大于二分之一个取样点步长的距离)的G1代码进行加工点插值,修正后的刀路会存在新文件中(不会对源文件进行任何写操作)。
                              
                                     图2. Z0Fix界面.jpg
          Z0Fix.exe的使用步骤是:(1)手工输入或打开步骤4生成的CNCZ0fix.z0f文件,并点击导入,确认界面上提示的x最大值、y最大值、步长及样本点数无误;(2)打开加工源文件,我使用的是ArtCAM导入dxf矢量后产生刀路*.nc文件;(3)手工输入或打开新文件*.nc;(4)点击“修正”按钮,修正结果会出现在界面上。
    6、在Mach3中加载步骤5中生成的新刀路文件,确认刀头的x,y坐标回位到加工零点,建议此次再做一次z轴对刀,确认需要加工的范围在做z轴零点校准步骤中所指定的范围内,本例中为:x从0至100mm,y从0至120mm。接下来按正常操作进行加工即可,会看到z轴实际走刀深度在各处有深有浅,这是针对每处工件平面的具体情况补偿后的结果,加工出来的实际效果应当是符合原期望的。
四、说明
    1、除了Z0Fix.exe外,其余思路、方法、代码针对任何刀路产生程序都是通用的,而Z0Fix.exe只针对使用ArtCAM导入Protel99se的dxf矢量后产生nc刀路(前后要删去几行代码)环境下使用过(因为软件编制的初衷仅仅是满足我个人使用需求,如果要考虑其他各种情况,那就太麻烦了),其他软件产生的刀路不一定能兼容。事实上我认为,如果能保证两个简单条件:(1)源文件每行G代码的各个字符之间连着写,不要有空格;(2)坐标定义不一定要xyz齐全,但一定要保证次序,即x一定要在y和z之前,y一定要在z之前。比如如下的各个例子都不会有问题。
     N70G0X0.000Y0.000S8000M3
     G0X5.588Y0.679Z3.000
     N90G1Z-0.200F120.0
     G1X5.233Y1.034F300.0
   2、z校零范围只能指定x和y的最大值,x和y的最小值默认为0,不能修改。实际加工范围必须在z校零范围之内。
   3、Mach3的界面和代码要更改成附件1提供的文件,否则没有校零功能,具体方法请参考林大夫的帖子:http://bbs.5imx.com/bbs/viewthread.php?tid=355431&extra=&highlight=%B6%D4%B5%B6&page=1
   4、回馈论坛,完全公开,附件3和4是 Z0Fix.exe的CBuilder6源代码及相应功能的Matlab代码(事实上最早只是写成了Matlab代码给自己用的,为方便大家才重新用C++做了.exe文件),供有兴趣同好们的参考。如果 Z0Fix.exe在使用中不便,大家也可自行修改代码。  
   5、只要保持PCB装夹固定不变,保持加工原点(x=0,y=0)不变,原理上z轴校零产生的CNCZ0fix.z0f数据文件可以反复使用,比如雕刻PCB的线路和钻孔刀路,都可以用同一个CNCZ0fix.z0f数据文件补偿。如果要换刀,须在加工原点(x=0,y=0)再做一次z轴对刀。如果相关环境改变,或者间隔时间较长或者操作频繁,使工件表面相对状态变化了,都需要再次做z轴校零,形成新的CNCZ0fix.z0f。
   6、附图3中是一个雕刻实例,在同一块1mm厚,平整度很差PCB板上,保持相关环境不变,使用0.2mm深度雕刻同一线路;左下为不补偿的雕刻结果,可以看到很多地方因为加工平面形变完全不着刀或只有很浅的划痕,导致雕刻无法继续下去; 右上为补偿修正过的刀路雕刻结果,同一块板子上各处下刀深度均匀,补偿是有效的。
                                   
                                       图3. PCB效果图.jpg
   7、本文为个人经验,如有不妥或需要改进的地方请各位不吝指出,目标是给坛友造福,大家共同学习进步。本文原创首发至CDLE.net及5imx.com,这两个论坛对我帮助很大。至于x莫那里就不发了,他喜欢当自己是上帝,但我恰是无神论者。









未经试验,纯分享,有条件的大虾,试了回来说一声!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2012-12-31 12:36:23 | 显示全部楼层
这个一定要顶的 ! 怎么没人支持啊 ! 很好的Z轴校正思路 !

出0入188汤圆

 楼主| 发表于 2012-12-31 22:54:23 | 显示全部楼层
现在才认真看完了贴子,转过来是纯技术交流的,对于里面有得罪阿莫大哥多多包涵。

出15入190汤圆

发表于 2013-2-6 22:25:43 | 显示全部楼层
这个真的是技术帖啊

出0入0汤圆

发表于 2013-2-7 13:01:45 | 显示全部楼层

出0入0汤圆

发表于 2013-2-8 07:47:25 | 显示全部楼层
有用。。。 mark

出0入0汤圆

发表于 2013-2-8 08:12:38 | 显示全部楼层
mark,take a look.

出0入0汤圆

发表于 2013-4-29 16:47:23 | 显示全部楼层
MARK,一会试下

出0入0汤圆

发表于 2013-4-29 21:42:23 | 显示全部楼层
请问ARTCAM保存成哪种NC文件

出0入0汤圆

发表于 2013-5-6 12:56:31 | 显示全部楼层
好人,大力的顶起

出0入0汤圆

发表于 2013-5-7 11:34:39 | 显示全部楼层
有试成的吗?我没试成。

出0入0汤圆

发表于 2013-5-23 13:55:18 | 显示全部楼层
wonderful!!!!!!

出0入0汤圆

发表于 2013-5-24 00:57:45 | 显示全部楼层
原作者后来有个更新,看看
(2012.7.12日:经过雕刻试验,不断优化Mach3的对刀及校零代码,现再传上最新版本,含对刀、Z校零两个代码文件,下 载请见本段文字后,可以代替原帖中附件1内相应代码文件。新版本代码的精度及效率均高过旧版本)
直接把优化后的Mach3的对刀及校零代码原文贴上来,这样就不怕丢了,大家拷贝后直接贴到相应按钮的VB代码中。


一. 对刀代码:

Message "对刀开始,请准备..."
CurrentFeed=GetOEMDRO(818)  '获得当前进给率
CurrentZ=GetOEMDRO(802)   '获得当前Z坐标值
MsgBox("请务必确认对刀线路连接良好!!")
Code "G4 P1"    '执行G4代码,程序停顿1秒,等候准备工作
Code "F100"     '为探测设置进给速率为100 mm/min
GageH=GetUserDRO(1001)    '获取用户设置的测量块高度
ZNew=CurrentZ-30     'Z轴目标为当前高度向下移动30mm
Code "G31 Z"&ZNew    '执行G31,向下进行30mm探测
While IsMoving()     '等待触碰,执行这个函数后,当所有轴停止则返回0
Wend                 ' end while
Znew=GetOEMDRO(802)   '获得当前Z坐标值
Call SetDro(2,GageH)   '将量块高度指定给Z轴坐标,实现量块底面为Z轴0坐标
FinalMove=GageH+3    '对刀后Z轴上移至量块顶面上方3mm
Code "G0 Z"&FinalMove  '执行Z轴移动到最终位置
Code "F"&CurrentFeed    '回存保留的进给率
Message "Z0=" & Znew & ", 对刀结束,工件顶面已置为Z轴零点。"







二、Z校零代码

Dim Lz(100) As Double    '每行的Z值先记录在数组中
Dim Yk As Integer   
Dim Xk As Integer
TotX=GetOEMDRO(1221)      '用户从DRO输入需要测试区域X方向最大坐标mm
TotY=GetOEMDRO(1222)        '用户从DRO输入需要测试区域Y方向最大坐标mm
Testep=GetOEMDRO(1223)    '用户从DRO输入每个测试样本点步进mm
Open "CNCZ0fix.z0f" For Output As #1    '新建测试数据记录文件  
Print #1,  TotX & "," & TotY & "," & Testep    ' 写TotX,TotY,Testep到文件
Message "检查开始,请准备..."
MsgBox("请务必确认对刀线路连接良好!!")
Code "G4 P1"    '执行G4代码,程序停顿1秒,等候准备工作
CurrentFeed=GetOEMDRO(818)  '获得当前进给率
Code "F100"     '为探测设置进给速率为100 mm/min
GageH=GetUserDRO(1001)    '获取用户设置的测量块高度
X0=GetOEMDRO(800)   '获得起始点X坐标值
Y0=GetOEMDRO(801)   '获得起始点Y坐标值
Message "TotalX=" & TotX & ",TotalY=" & TotY & ",Testep=" & Testep
Yk=0               '当前行号
For Y=Y0 To TotY Step Testep
   Code "G0 Y" & Y   '走刀到当前Y
   Yk=CInt(Y/Testep)           '当前行号(从0开始)
   If  (YK Mod 2)=0    Then
      Xbg=X0      '奇数行X轴起始位置
      Xed=TotX    '奇数行X轴终止位置
      Xsp=Testep  '奇数行X轴步进
   Else
      Xbg=TotX      '偶数行X轴起始位置
      Xed=X0    '偶数行X轴终止位置
      Xsp=-Testep  '偶数行X轴步进
   End If
   For  X=Xbg To Xed Step Xsp
        Code "G0 X" & X   '走刀到当前X
        CurrentZ=GetOEMDRO(802)   '获得当前Z坐标值
        ZNew=CurrentZ-10     'Z轴目标为当前高度向下移动10mm
        Code "G31 Z" & ZNew    '执行G31,向下进行探测
        While IsMoving()     '等待触碰,执行这个函数后,当所有轴停止则返回0
        Wend                    'end while
        Znew=GetOEMDRO(802)    '记录刀尖触碰时Z的位置
        FinalMove=Znew+2    '对刀后Z轴上移至量块顶面上方2mm
        Code "G0 Z" & FinalMove  '执行Z轴移动到最终位置
        Z0=Znew-GageH           '减去量块高度,得到Z0平面误差
        Xk=CInt(X/Testep)       '当前列号(从0开始)
        Lz(Xk)=Z0               'Z0值暂存数组中
        Message "TotalX=" & TotX & ",TotalY=" & TotY & "; X=" & X & ",Y=" & Y & ",Z0=" & Z0   '信息栏输出完成的测试点信息
   Next
   For  X=X0 To TotX Step Testep     '完成一行后,统一写测试信息
        Xk=CInt(X/Testep)       '当前列号(从0开始)
        Print #1,  X & "," & Y & "," & Lz(Xk)    '写X,Y,Z0到文件
    Next
Next
Close #1
Code "F" & CurrentFeed    '回存保留的进给率
Code "G0 X" & X0 & "Y" & Y0  '返回起始点
Message "检测完毕,数据保存至CNCZ0fix.z0f"

出0入188汤圆

 楼主| 发表于 2013-5-24 08:42:26 | 显示全部楼层
颜靖峰 发表于 2013-5-24 00:57
原作者后来有个更新,看看
(2012.7.12日:经过雕刻试验,不断优化Mach3的对刀及校零代码,现再传上最新版本 ...

谢谢LS帮忙更新

出0入0汤圆

发表于 2013-5-27 22:38:54 | 显示全部楼层
我试过,对原点设在工件中心的,不适用。。原点设在工件左下角的有用。

出0入0汤圆

发表于 2013-6-25 14:35:17 | 显示全部楼层
不错好东西,刻pcb用得上。

出0入0汤圆

发表于 2013-7-2 08:59:00 | 显示全部楼层
MARK!

出0入0汤圆

发表于 2013-12-26 22:47:38 | 显示全部楼层
刚才试验了一下你的软件,为啥z轴对 刀的话明明提升是5mm 却显示的提升7mm结果撞刀,悲剧了。

出0入0汤圆

发表于 2014-1-29 17:44:44 | 显示全部楼层

请问楼主 我用您的代码发现 Z轴向上寻找0点,把代码的+改成-之后 正常了,请问 影响校准效果吗?

出0入0汤圆

发表于 2014-3-11 17:00:41 | 显示全部楼层
我用CopperCAM出刀路。底层出隔离刀路,x坐标都为负值。更改了下楼主的程序,发上来供大家参考。

Dim Lz(100) As Double    '每行的Z值先记录在数组中
Dim Yk As Integer   
Dim Xk As Integer
TotX=-105 'GetOEMDRO(1221)      '用户从DRO输入需要测试区域X方向最大坐标mm
TotY=45 'GetOEMDRO(1222)        '用户从DRO输入需要测试区域Y方向最大坐标mm
Testep=5 'GetOEMDRO(1223)    '用户从DRO输入每个测试样本点步进mm
Open "CNCZ0fix.z0f" For Output As #1    '新建测试数据记录文件  
Print #1,  TotX & "," & TotY & "," & Testep    ' 写TotX,TotY,Testep到文件
Message "检查开始,请准备..."
MsgBox("请务必确认对刀线路连接良好!!")
Code "G4 P1"    '执行G4代码,程序停顿1秒,等候准备工作
CurrentFeed=GetOEMDRO(818)  '获得当前进给率
Code "F100"     '为探测设置进给速率为100 mm/min
GageH=0 'GetUserDRO(1001)    '获取用户设置的测量块高度
Code "G0 Z10"
Code "G0 X0 Y0"
X0=0 'GetOEMDRO(800)   '获得起始点X坐标值
Y0=0 'GetOEMDRO(801)   '获得起始点Y坐标值
Message "TotalX=" & TotX & ",TotalY=" & TotY & ",Testep=" & Testep
Yk=0               '当前行号
Dim xTestep As Integer
Dim yTestep As Integer
If (TotX > X0) Then
  xTestep = Testep
Else
  xTestep = -Testep
End If
If (TotY > Y0) Then
  yTestep = Testep
Else
  yTestep = -Testep
End If
For Y=Y0 To TotY Step yTestep
   Code "G0 Y" & Y   '走刀到当前Y
   Yk=CInt(Y/yTestep)           '当前行号(从0开始)
   If  (YK Mod 2)=0    Then
      Xbg=X0      '奇数行X轴起始位置
      Xed=TotX    '奇数行X轴终止位置
      Xsp=xTestep  '奇数行X轴步进
   Else
      Xbg=TotX      '偶数行X轴起始位置
      Xed=X0    '偶数行X轴终止位置
      Xsp=-xTestep  '偶数行X轴步进
   End If
   For  X=Xbg To Xed Step Xsp
        Code "G0 X" & X   '走刀到当前X
        CurrentZ=GetOEMDRO(802)   '获得当前Z坐标值
        ZNew=CurrentZ-10     'Z轴目标为当前高度向下移动10mm
        Code "G31 Z" & ZNew    '执行G31,向下进行探测
        While IsMoving()     '等待触碰,执行这个函数后,当所有轴停止则返回0
        Wend                    'end while
        Znew=GetOEMDRO(802)    '记录刀尖触碰时Z的位置
        FinalMove=Znew+2    '对刀后Z轴上移至量块顶面上方2mm
        Code "G0 Z" & FinalMove  '执行Z轴移动到最终位置
        Z0=Znew-GageH           '减去量块高度,得到Z0平面误差
        Xk=CInt(X/xTestep)       '当前列号(从0开始)
        Lz(Xk)=Z0               'Z0值暂存数组中
        Message "TotalX=" & TotX & ",TotalY=" & TotY & "; X=" & X & ",Y=" & Y & ",Z0=" & Z0   '信息栏输出完成的测试点信息
   Next
   For  X=X0 To TotX Step xTestep     '完成一行后,统一写测试信息
        Xk=CInt(X/xTestep)       '当前列号(从0开始)
        Print #1,  X & "," & Y & "," & Lz(Xk)    '写X,Y,Z0到文件
    Next
Next
Close #1
Code "F" & CurrentFeed    '回存保留的进给率
Code "G0 X" & X0 & "Y" & Y0  '返回起始点
Message "检测完毕,数据保存至CNCZ0fix.z0f"

对应matlab程序
clear all;
clc;
ztest=load('d:\CNCZ0fix.z0f');  %导入CNC Z轴零点测试数据
fnc=fopen('d:\test.CNC','rt');  %原nc文件
fncnew=fopen('d:\newline.nc','wt');  %带生成的新的nc文件

totx=ztest(1,1);  %零点测试区域x轴最大值
toty=ztest(1,2);  %零点测试区域y轴最大值
testep=ztest(1,3);   %零点测试步长mm
x_testep = testep;
y_testep = testep;
if (totx < 0)
    x_testep = -x_testep;
end
if (toty < 0)
    y_testep = -y_testep;
end
xPointNum = round(totx./x_testep)+1;
yPointNum = round(toty./y_testep)+1;
zerr=zeros(xPointNum, yPointNum);
m=2;
for j=1:1:yPointNum
  for i=1:1:xPointNum
      zerr(i,j)=ztest(m,3);        %生成Z轴零点误差矩阵
      m=m+1;
  end
end


ptsrd=zeros(1,7);   %nc文件行号,点x值,点y值,点z值,本句中用于更新(插入)修正后的z值的首位、尾位、G语句值
m=0;
lncnt=0;  %文件行号
Gval=1;  %当前是否G语句值
xx0=0;    %之前点x,y值
yy0=0;
xx=0;     %当前点x,y,z值
yy=0;
zz=3;
wh_z=[0,0];  %x,y,z定义值所在当前语句中的字符首尾位置


fln=fgets(fnc);
while(fln~=-1)
  lncnt=lncnt+1;
  wh_z=[0,0];
  flg=0;
  for i=1:1:size(fln,2)
      if((fln(i)=='G') | (fln(i)=='g'))    %当前语句中包含G语句的定义
         for j=i+1:1:size(fln,2)
            if(~(fln(j)>='0' & fln(j)<='9'))   %找到G语句定义的尾位
                break;
            end
         end
         Gval=str2num(fln(i+1:j-1));   %获取G语句值定义
      end
      
      if((fln(i)=='X') | (fln(i)=='x'))    %当前语句中包含x值的定义
         for j=i+1:1:size(fln,2)
            if(~((fln(j)>='0' & fln(j)<='9') | (fln(j)=='.') | (fln(j)=='-') | (fln(j)=='+')))   %找到x值定义的尾位
                break;
            end
         end
         flg=1;  %flg==1,本语句有坐标值定义
         xx=str2num(fln(i+1:j-1));   %获取x值定义
         wh_z=[j,j];             %本句中用于更新(插入)修正后的z值的首尾位(新语句的首位位置置'Z',旧语句尾位起为其他后续语句)
      end
      if((fln(i)=='Y') | (fln(i)=='y'))    %当前语句中包含y值的定义
         for j=i+1:1:size(fln,2)
            if(~((fln(j)>='0' & fln(j)<='9') | (fln(j)=='.') | (fln(j)=='-') | (fln(j)=='+')))  %找到y值定义的尾位
                break;
            end
         end
         flg=1;   %flg==1,本语句有坐标值定义
         yy=str2num(fln(i+1:j-1));  %获取y值定义
         wh_z=[j,j];             %本句中用于更新(插入)修正后的z值的首尾位(新语句的首位位置置'Z',旧语句尾位起为其他后续语句)
      end
      if((fln(i)=='Z') | (fln(i)=='z'))   %当前语句中包含y值的定义
         for j=i+1:1:size(fln,2)
            if(~((fln(j)>='0' & fln(j)<='9') | (fln(j)=='.') | (fln(j)=='-') | (fln(j)=='+')))  %找到z值定义的尾位
                break;
            end
         end
         flg=1;    %flg==1,本语句有坐标值定义
         zz=str2num(fln(i+1:j-1));     %获取z值定义
         wh_z=[i,j];    %本句中用于更新(插入)修正后的z值的首尾位(新语句的首位位置置'Z',旧语句尾位起为其他后续语句)
      end
  end
  if(flg==1)
     if(m>0)
        xx0=ptsrd(m,2);
        yy0=ptsrd(m,3);
     else
        xx0=0;
        yy0=0;
     end
     
     dis=sqrt((xx-xx0).^2+(yy-yy0).^2);
     if( (dis>testep/2) & (Gval==1) )  %当前走刀为G1,且当前点较之前点水平位移大于testep/2,则进行插值
         zz0=ptsrd(m,4);
         n=ceil(dis/(testep/2));  %将本条刀路内共分为n个子刀路,需插值n-1个
         for k=1:1:n-1
            m=m+1;
            ptsrd(m,1:4)=[0,k/n*(xx-xx0)+xx0,k/n*(yy-yy0)+yy0,k/n*(zz-zz0)+zz0];    %插值的行号设为0
            ptsrd(m,7)=Gval;    %存放G值
         end
     end
     m=m+1;
     ptsrd(m,1:4)=[lncnt,xx,yy,zz];   %写入本语句行号,x,y,z值
     ptsrd(m,5:6)=[wh_z(1),wh_z(2)];   %本句中用于更新(插入)修正后的z值的首尾位(新语句的首位位置置'Z',旧语句尾位起为其他后续语句)
     ptsrd(m,7)=Gval;    %存放G值
         
  end
  fln=fgets(fnc);
end



%以下通过Z轴零点误差矩阵修正各点z值
for i=1:1:size(ptsrd,1)
   x0=ptsrd(i,2)/x_testep;
   y0=ptsrd(i,3)/y_testep;
   x1=floor(x0);
   x2=ceil(x0);  
   y1=floor(y0);
   y2=ceil(y0);
   if(x2==x1 & y2==y1)      %当前雕刻点与样本点重合
      z0=zerr(x1+1,y1+1);
      ptsrd(i,4)=ptsrd(i,4)+z0;   %z0取重合的样本点的零点位置,修正当前点z轴的下刀量
   else                     %当前雕刻点与样本点不重合  
      if(x2==x1)
         if(x1>0)
           x1=x1-1;
         else
           x2=x2+1;
         end
      end
     
      if(y2==y1)
         if(y1>0)
           y1=y1-1;
         else
           y2=y2+1;
         end
      end

      nbpts=[x1,y1,zerr(x1+1,y1+1);x1,y2,zerr(x1+1,y2+1);x2,y1,zerr(x2+1,y1+1);x2,y2,zerr(x2+1,y2+1)]; %四周的样本点
      dis=sqrt((x0-nbpts(:,1)).^2+(y0-nbpts(:,2)).^2);   %计算与四周样本点的水平距离
      [Y,I]=sort(dis);     %距离从小到大排序
      plpts=nbpts(I(1:3),:);  %选出距离最小的三个样本点
      a1=x0-plpts(1,1);        %将当前点的x,y值代入由三个样本点构建平面方程,得到z0
      a2=plpts(2,1)-plpts(1,1);
      a3=plpts(3,1)-plpts(1,1);
      b1=y0-plpts(1,2);
      b2=plpts(2,2)-plpts(1,2);
      b3=plpts(3,2)-plpts(1,2);
      c2=plpts(2,3)-plpts(1,3);
      c3=plpts(3,3)-plpts(1,3);
      c1=(a1*b3*c2+a2*b1*c3-a1*b2*c3-a3*b1*c2)./(a2*b3-a3*b2);
      z0=c1+plpts(1,3);
      ptsrd(i,4)=ptsrd(i,4)+z0;   %通过估计的零点位置z0,修正当前点z轴的下刀量

   end
end

fseek(fnc,0,'bof');

m=1;
lncnt=0;
wh_z=[0,0];
fln=fgets(fnc);
while((fln~=-1) & (m<=size(ptsrd,1)))
   lncnt=lncnt+1;
   if(lncnt==ptsrd(m,1))  %只修改有坐标值定义的语句
     wh_z=ptsrd(m,5:6);    %本句中用于更新(插入)修正后的z值的首尾位(新语句的首位位置置'Z',旧语句尾位起为其他后续语句)
     flnnew=sprintf('%sZ%0.3f%s',fln(1:wh_z(1)-1),ptsrd(m,4),fln(wh_z(2):size(fln,2)));  %生成新语句
     fprintf(fncnew,'%s',flnnew);
     while((m<size(ptsrd,1)) & (ptsrd(m+1,1)==0))  %本语句后面有插值,创建新语句输出
         m=m+1;
         flnnew=sprintf('G%dX%0.3fY%0.3fZ%0.3f\n',ptsrd(m,7),ptsrd(m,2),ptsrd(m,3),ptsrd(m,4));  %生成新语句
         fprintf(fncnew,'%s',flnnew);
     end
     m=m+1;
   else
     fprintf(fncnew,'%s',fln);   %没有坐标值定义的语句直接输出
   end
  
   fln=fgets(fnc);
end
fclose(fnc);
fclose(fncnew);
plot3(ptsrd(:,2),ptsrd(:,3),ptsrd(:,4));

出0入0汤圆

发表于 2014-3-11 20:27:15 | 显示全部楼层
好。。先赞个,慢慢看

出0入0汤圆

发表于 2014-3-11 22:02:55 | 显示全部楼层
技术帖..

出0入0汤圆

发表于 2014-3-12 18:49:36 | 显示全部楼层
谢谢分享,慢慢看

出0入0汤圆

发表于 2014-3-14 07:47:04 | 显示全部楼层
很棒的技术帖,谢谢分享

出0入0汤圆

发表于 2016-4-17 14:45:05 | 显示全部楼层
好东西, 村长的好像是手动取点的,操作很困难
这个是自动的
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-27 02:00

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表