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

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

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

单片机平台的最小偏差圆弧插补算法_第1张图片

 

一、判断圆弧所在象限

        在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;


你可能感兴趣的:(单片机平台的最小偏差圆弧插补算法)