原创 基于单片机平台的最小偏差圆弧插补算法

2009-12-21 08:41 8167 11 14 分类: MCU/ 嵌入式

CNC机床的G代码中,最常见的有G0G1G2G3代码,分别表示直线和圆弧插补,直线插补对于单片机来说,比较容易实现,只需要将位移增量转换为脉冲增量然后输出给步进电机就可以了,但对于圆弧插补,则需要单片机根据G指令中给出的起始点、半径、结束点这三个参数来控制X Y轴进行圆周运动;因此需要通过特定的圆弧插补算法来控制步进电机运动,圆弧插补算法比较多,常用的有逐点比较法、最小偏差法和数字积分法等等,本文使用的是逐点比较法。

先不介绍逐点比较插补算法的原理,给出一幅图,下面再结合文字进行介绍。

点击看大图

 

一、判断圆弧所在象限

G代码的圆弧插补指令中,给出的圆弧可以是任意象限的,而不同象限的圆弧绘制算法又不一样,因此首先需要判断圆弧所在象限。当然给出的圆弧可以是在一个象限内,也可能是跨两个相邻的象限比如图中四段橙色的弧线。象限的判断比较简单,只要通过判断起始点坐标和结束点坐标的值便可。

 

二、找出圆弧运动过程中变化快的一轴

由上图可见,当圆弧位于045度、135度~180度、180225度和315360度区域时Y的变化大于XX坐标值的绝对值大于Y坐标的绝对值;而当圆弧位于4590度、90135度、225270度和270315度区域时X的变化大于YX坐标值的绝对值小于Y坐标的绝对值,因此可通过XY坐标值的比较来找出运动过程中变化快的一轴。

 

三、偏差计算与判别

如果我们给变化快的那一轴(假设是X)进给一个脉冲,则加工点到圆心的距离会发生变化,而Y轴是否进给,则通过偏差计算来判断。

众所周知:圆心在坐标原点的圆方程为

x*x+y*y=r*r

设偏差Fx*x+y*yr*r

假设Y轴不进给,则F1=(x1*x1+y*yr*r

假设Y轴进给,则F2=(x1*x1+y1*y1)-r*r

 

比较F1F2的绝对值,如果不进给时的偏差小,则Y轴进给,否则Y轴不进给。

 

若没到终点,则一直循环。

 

注意:电机动动的方向需要通过判断象限来决定的。

 

四、终点判别

如果到达终点则表示弧线绘制完毕,退出插补循环体。

 

五、跨象限的圆弧段处理

跨象限的圆弧段处理也按照上述方法,选择一变化快的轴进给,另一轴通过偏差来判别是否进给。电机运动的方向同样通过象限来判断。

 

本人之前尝试过给变化快的轴进给N个脉冲量,再通过解圆的方程来计算出Y的脉冲进给量,由于解圆的方程需要进行开根号运算,因此影响了插补的速度,同时一次进给N个脉冲量会使电机运动不连续,更重要的是加工的精度会有很大的影响。采用以上方法,不但减少了大量的运算时间,提高了插补的速度,精度也得到了很大的提高。

该方法简单,便于理解,也适合在单片机平台上运行。

 

以下是某一象限的顺时针圆弧插补代码,其它象限类似:

#define   e(x,y)  (x)*(x)+(y)*(y)-r_r   //偏差计算  r_r为半径的平方

#define DT 1

 

 

//如果在第一象限

case 1:

       while(y>x)             // 45°-90°,此段X值变化比Y

       {

              k=orig_x+x;  //orig_x原点坐标

              MoveToPosition(k,orig_y+y);  //移动电机至目标位置

    x+=DT; //   优先改变X  

    f=e(x,y); //   Y不变时 所得点距圆周偏差,

    g=e(x,y-DT); //   Y变时  所得点距圆周偏差,

    if(abs_16(f)>=abs_16(g)) y-=DT; // 如果变时偏差小,则取改变Y

              if(k>=end_x)goto Exit;  //如果到达终点,则跳出循环体 

       }

       while(x>=y)             //   0-45°,此段Y值变化比X

       {

              k=orig_y+y;

              MoveToPosition( orig_x+x,  k);  //移动电机至目标位置

    y-=DT; //   优先改变Y  

    f=e(x,y); //   X不变 所得点距圆周偏差,

    g=e(x+DT,y);         //   X改变,所得点距圆周偏差,

    if(abs_16(f)>=abs_16(g))x+=DT;       //   如果变时偏差小,则取改变X

              if(k<=end_y)goto Exit;  //如果到达终点,则跳出循环体 

       }

break;

 


文章评论3条评论)

登录后参与讨论

用户377235 2012-4-28 11:45

非常感谢,这篇文章太有用了!

用户1278632 2010-2-21 16:38

while(y>x) // 45°-90°,此段X值变化比Y快 { ....... if(k>=end_x)goto Exit; //如果到达终点,则跳出循环体 } 这里判断是否到达终点是判断的X轴,即插补主轴(我们称移动快的一轴叫插补主轴),这里会出现一们问题,X到达终点了,而Y没有到达终点,有文章说要判断Y轴,即非插补主轴,这样效果会好一些,欢迎大家测试。

用户214444 2010-1-26 08:12

终于找到了适合单片机的插补方法;其实就是根据勾股定理; 谢谢
相关推荐阅读
用户1278632 2011-09-15 12:49
解决FPGA配置成功,但不能初始化运行的BUG
摘要:    遇到两次FPGA配置完成,却不能正常运行的问题,一次是ALTERA的A1C3,另一次是XILINX的XC3S700A。两次都是DONE信号的问题。问题虽不大,但却很折腾人,今天在这里作下...
用户1278632 2011-09-15 12:41
Code Edit的神器UltraEdit
摘要:      我不是一个专职的程序员,但经常会要写一些单片机底层的code和hdl code,起初用UE,是因为查找和批量修改很方便,而且不会额外的生成一些“垃圾”文件;现在用UE三年多了,一直都...
用户1278632 2010-12-29 09:29
ISE与EDK联合设计报错 ERROR:NgdBuild:604 logical block
做一个很简单的测试在ISE的SCH里调用EDK的symbol,EDK的功能也很简单,就是CPU通过串品打印一串字符首先,我建一个ISE工程再建一source  sch类型,并设置为顶层,取名为top....
用户1278632 2010-12-22 14:49
EDK12.2中 mch_emc IP的时序问题
mch_emc IP可以将PLB总线时序转为inter 8080时序 下面是我用chipscope抓到的波形Mem_DQ_O_In :  数据输入 Mem_OEN:      读信号  Mem_A: ...
用户1278632 2010-12-22 14:29
xilinx FPGA的配制与应用程序引导-范例
两个Xilinx FPGA应用程序引导的范例1、run_in_flash是直接在NOR FLASH里运行程序2、spi_flash_boot是将BIT和bootloader和APP全部固化到SPI F...
用户1278632 2010-12-19 13:48
EDK下sram IP的使用
EDK软件的memory and memory controller中有一个xps multi-channel external memory controller(sram/flash)的IP,用来...
我要评论
3
11
关闭 站长推荐上一条 /2 下一条