逐点比较法第一象限直线圆弧插补.docx
《逐点比较法第一象限直线圆弧插补.docx》由会员分享,可在线阅读,更多相关《逐点比较法第一象限直线圆弧插补.docx(19页珍藏版)》请在冰豆网上搜索。
![逐点比较法第一象限直线圆弧插补.docx](https://file1.bdocx.com/fileroot1/2023-1/3/05d6fa23-a727-4f56-899e-2d43801dce14/05d6fa23-a727-4f56-899e-2d43801dce141.gif)
逐点比较法第一象限直线圆弧插补
逐点比较法第一象限直线,圆弧插补编程
逐点比较法是以折线来逼近给定的轨迹,就是每走一步控制系统都要将加工点与给定的图形轨迹相比较,以决定下一步进给的方向,使之逼近加工轨迹。
逐点比较法以折线来逼近直线或圆弧,其最大的偏差不超过一个最小设定单位。
只要将脉冲当量取得足够小,就可以达到精度要求。
逐点比较插补法在脉冲当量为0.01mm,系统进给速度小于3000mm/min时,能很好的满足要求。
一、逐点比较法直线插补
如下图所示设直线oA为第一象限的直线,起点为坐标原点o(0,0),终点坐标为,A(
),P(
)为加工点。
若P点正好处在直线oA上,由相似三角形关系则有
即
点在直线oA上方(严格为直线oA与y轴正向所包围的区域),则有
即
若P点在直线oA下方(严格为直线oA与x轴正向所包围的区域),则有图3—1逐点比较法第一象限直线插补
即
令
则有:
①如
,则点P在直线oA上,既可向+x方向进给一步,也可向+y方向进给一步;
②如
,则点P在直线oA上方,应向+x方向进给一步,以逼近oA直线;
③如
,则点P在直线oA下方,应向+y方向进给一步,以逼近oA直线一般将
及
视为一类情况,
即
时,都向+x方向进给一步。
当两方向所走的步数与终点坐标相等时,停止插补。
这即逐点比较法直线插补的原理。
对第一象限直线oA从起点(即坐标原点)出发,当F
时,+x向走一步;当F<0时,y向走一步。
特点:
每一步都需计算偏差,这样的计算比较麻烦。
递推的方法计算偏差:
每走一步后新的加工点的偏差用前一点的加工偏差递推出来。
采用递推方法,必须知道开始加工点的偏差,而开始加工点正是直线的起点,故
。
下面推导其递推公式。
设在加工点P(
)处,
,则应沿+x方向进给一步,此时新加工点的坐标值为
新加工点的偏差为
即
若在加工点P(
)处,
,则应沿+y方向进给一步,此时新加工点的坐标值为
,
新加工点的偏差为
即
综上所述,逐点比较法直线插补每走一步都要完成四个步骤(节拍),即:
(1)位置判别根据偏差值
大于零、等于零、小于零确定当前加工点的位置。
(2)坐标进给根据偏差值
大于零、等于零、小于零确定沿哪个方向进给一步。
(3)偏差计算根据递推公式算出新加工点的偏差值。
(4)终点判别用来确定加工点是否到达终点。
若已到达,则应发出停机或转换新程序段信号。
一般用x和y坐标所要走的总步数J来判别。
令J=
,每走一步则J减1,直至J=0。
上图为第一象限直线插补程序框图
二、逐点比较法插补程序
#include"conio.h"
#include"graphics.h"
#include"process.h"
#defineNi_circle0
#defineShun_circle1
voidinit_graph();
voiddraw_Base_circle();
voiddraw_cabu_circle();
voidclose_graph();
voidacrroods();
staticfloatx0,y0;
voidline_cabu(),draw_line(),draw_line_cabu();
voidline_cabu()/*此函数控制直线插步两次*/
{
inti;
init_graph();
sleep
(1);
for(i=0;i<2;i++)
{
line(0,120,300,120);outtextxy(310,120,"Z");
line(100,10,100,300);outtextxy(110,300,"X");
outtextxy(90,130,"O");
draw_line();
if(i==0)
draw_line_cabu(6);
elsedraw_line_cabu
(2);
gotoxy(50,5);
getch();
cleardevice();
setcolor(WHITE);
}
}
voiddraw_line()/*画直线*/
{
line(100,120,600,450);
textcolor(YELLOW);
directvideo=0;
gotoxy(45,5);cprintf("Linefrom:
X0Y0Z0");
gotoxy(45,6);cprintf("Lineto:
X500Y0Z330");
gotoxy(45,7);cprintf("Units:
Pixel");
gotoxy(45,8);cprintf("Linenow:
");
}
voiddraw_line_cabu(intstep)/*关键的直线插补函数*/
{
intXe=600,Ye=450;
floatFm,Xm=100,Ym=120;
setcolor(RED);
moveto(Xm,Ym);
while(Xm<=Xe&&Ym<=Ye)
{
Fm=(Ym-120)*(Xe-100)-(Xm-100)*(Ye-120);
if(Fm>=0)
Xm=Xm+step;
else
Ym=Ym+step;
lineto(Xm,Ym);
gotoxy(55,8);printf("X%3.0fY0Z%3.0f",Xm-100,Ym-120);
delay(1100);
}
}
/*圆插补部分的函数区*/
voidinit_graph()/*图形系统初始化*/
{
intgdrive=DETECT,gmode;
initgraph(&gdrive,&gmode,"");
cleardevice();
}
voidacrroods()/*屏幕中心坐标*/
{
x0=getmaxx()/2;
y0=getmaxy()/2;
}
voiddraw_Base_circle()/*画圆及写参数*/
{
line(x0-200,y0,x0+200,y0);outtextxy(x0+220,y0,"Z");
line(x0,y0-180,x0,y0+180);outtextxy(x0+10,y0+180,"X");
outtextxy(x0-10,y0+10,"O");
circle(x0,y0,150);
textcolor(YELLOW);
directvideo=0;
gotoxy(46,2);cprintf("Circlestart:
X0Y0Z150");
gotoxy(46,3);cprintf("Circleend:
X0Y0Z150");
gotoxy(46,4);cprintf("Units:
Pixel");
gotoxy(46,5);cprintf("Circlenow:
");
}
voidclose_graph()/*关图形系统*/
{
closegraph();
}
voiddraw_cabu_circle(intsstep,intDirectory)/*关键的圆插补函数*/
{
intflag=0;
floatFm,Xm,Ym;
Xm=x0+150;Ym=y0;
moveto(Xm,Ym);
setcolor(RED);
while
(1)/*分象限,顺圆和逆圆讨论*/
{
Fm=(Xm-x0)*(Xm-x0)+(Ym-y0)*(Ym-y0)-150*150;/*圆判断公式*/
if(Fm>=0){
if(!
Directory){/*逆圆判断*/
if(Xm>=x0&&Ym<=y0)
{
if(flag)break;/*if语句判断象限,以下一样*/
elseXm=Xm-sstep;
}
if(Xm<=x0&&Ym<=y0)
{
flag=1;Ym=Ym+sstep;
}
if(Xm<=x0&&Ym>=y0)
Xm=Xm+sstep;
if(Xm>=x0&&Ym>=y0)
Ym=Ym-sstep;
}
else{/*itisDirectory'selse*/
if(Xm>x0&&YmYm=Ym+sstep;
if(Xm<=x0&&Ym<=y0)
Xm=Xm+sstep;
if(Xmy0){
flag=1;Ym=Ym-sstep;}
if(Xm>=x0&&Ym>=y0){
if(flag)break;
Xm=Xm-sstep;}
}
}
else{/*itisFm'selse*/
if(!
Directory){
if(Xm>x0&&Ym{
if(flag)break;
elseYm=Ym-sstep;
}
if(Xm<=x0&&Ym<=y0)
{
flag=1;Xm=Xm-sstep;
}
if(Xm<=x0&&Ym>=y0)
Ym=Ym+sstep;
if(Xm>=x0&&Ym>=y0)
Xm=Xm+sstep;
}
else{
if(Xm>x0&&YmXm=Xm+sstep;
if(Xm<=x0&&Ym<=y0)
Ym=Ym-sstep;
if(Xm<=x0&&Ym>=y0){
flag=1;Xm=Xm-sstep;}
if(Xm>=x0&&Ym>=y0){
if(flag)break;
elseYm=Ym+sstep;}
}
}
lineto(Xm,Ym);
gotoxy(58,5);printf("X%3.0fY0Z%3.0f",Ym-y0,Xm-x0);
delay(800);
}
}
voidcircle_demo(intDirectory)/*控制圆插补两次*/
{
inti=0,sstep;
init_graph();
sleep
(2);
acrroods(&x0,&y0);
for(i=0;i<2;i++)
{
draw_Base_circle(150);
if(i==0){
sstep=6;
draw_cabu_circle(sstep,Directory);}
else{
sstep=1;
draw_cabu_circle(sstep,Directory);}
getch();
cleardevice();
setcolor(WHITE);
}
}
/*圆插补部分的函数区结束*/
main()/*主函数负责写封面和函数调用*/
{
intchoice=0;
init_graph();
while(choice!
=4)
{
setfillstyle(1,RED);
bar(200,30,400,80);
setcolor(GREEN);
settextstyle(3,0,10);
outtextxy(220,50,"DEMOPROGRAMBYP.Y.F");
setcolor(WHITE);
settextstyle(0,0,1);
outtextxy(200,120,"1.Linedemo.");
outtextxy(200,140,"2.Shun_Circledemo.");
outtextxy(200,160,"3.Ni_Circledemo.");
outtextxy(200,180,"4.Quittheprogram.");
outtextxy(160,200,"Pleaseenteryourchoice:
");gotoxy(46,13);
scanf("%d",&choice);
switch(choice)
{
case1:
line_cabu();break;
case2:
circle_demo(Ni_circle);break;
case3:
circle_demo(Shun_circle);break;
case4:
break;
default:
printf("\nChoicewrong,tryagain!
");
}
}
close_graph();
}
三、逐点比较法圆弧插补
圆弧插补加工:
是将加工点到圆心的距离与被加工圆弧的名义半径相比较,并根据偏差大小确定坐标进给方向,以逼近被加工圆弧。
下面以第一象限逆圆弧为例,讨论圆弧的插补方法。
如下图所示,设要加工圆弧为第一象限逆圆弧AB,原点为圆心o,起点为A(
),终点为B(
),半径为R。
瞬时加工点为P(
),点P到圆心距离为
。
若点P正好在圆弧上,则有
图逐点比较法第一象限圆弧插补即
若点P在圆弧外侧,则有
即
若点P在圆弧内侧,则有
即
显然,若令
(3—4)
则有:
①
,则点P在圆弧上;
②
,则点P在圆弧外侧;
③
,则点P在圆弧内侧。
当
时,为逼近圆弧,应向--X方向进给一步;当
时,应向+y方向进给一步。
这样,就可获得逼近圆弧的折线图。
与直线插补偏差计算公式相似,圆弧插补的偏差计算也采用递推的方法以简化计算。
若加工点
在圆弧外或圆弧上,则有
为逼近该圆需沿--X方向进给一步,移到新加工点
,此时新加工点的坐标值为
新加工点的偏差为
即
若加工点
在圆弧内,则有
为逼近该圆需沿十y方向进给一步,移到新加工点
,此时新加工点的坐标值为
新加工点的偏差为
即
从以上两式可知,递推偏差计算仅为加法(或减法)运算,大大降低了计算的复杂程度。
由于采用递推方法,必须知道开始加工点的偏差,而开始加工点正是圆弧的起点,故
。
除偏差计算外,还要进行终点判别。
一般用x、y坐标所要走的总步数来判别。
令
,每走一步则J减l,直至J=0到达终点停止插补。
综上所述,逐点比较法圆弧插补与直线插补一样,每走一步都要完成位置判别、坐标进给、偏差计算、终点判别四个步骤(节拍)。
下图所示为第一象限逆圆弧逐点比较法插补的程序框图
逐点比较法圆弧插补汇编语言程序(MCS-8031)
RP:
MOV SP,#60H
MOV 4AH,#00HF单元清零
MOV 49H,#00H
MOV 48H,#01H X电动机初始化
MOV 47H,#02H Y电动机初始化
MOV DPTR,#0030H
MOV A,#03H XY电动机上电
MOVX @DPTR,A
CLR C 计算终判值
MOV A,52H 低位X、Xe相减,得a
SUBB A,4EH
MOV 54H,A 保存结果于终判值单元低位字节
MOV A,51H 高位X、Xe相减,得b
SUBB A,4DH
MOV 53H,A 保存结果于终判值单元高位字节
CLR C 低位Ye、Y相减,得c
MOV A,4CH
SUBB A,50H
MOV 20H,C 暂存Ye、Y低位相减产生的借位位
ADD A,54H 计算d=a+c,d为低位终判值
MOV 54H,A 保存d于终判值单元低位字节
MOV 21H,C 暂存d=a+c产生的进位位
MOV A,4BH
MOV C,20H 恢复Ye、Y低位相减产生的借位位
SUBB A,4FH 高位Ye、Y相减,得e
MOV C,21H 恢复d=a+c产生的进位位
ADDC A,53H 计算f=b+e,f为高位终判值
MOV 53H,A 保存f于终判值单元高位字节
RP2:
ACALL DL0 延时子程序
MOV A,49H 取F高位字节
JB ACC.7,RP6 高位=1,F<0,去RP6
ACALL XMM 高位=0,F>0,X反转一步
CLR C 计算新偏差F=F-2X+1
MOV A,4AH 计算g=F-X低位
SUBB A,52H
XCH A,B g存入B寄存器
MOV A,49H 计算h=F-X高位
SUBB A,51H
XCH A,B低位存A,高位存B。
BA内容为F-
CLR C 计算i=g-X=F-2X低位
SUBB A,52H
XCH A,B B内容为F-2X低位,A内容为F-X高位
SUBB A,51H A内容为F-2X高位
XCH A,B BA内容为F-2X
ADD A,#01H 计算F-2X+1
MOV 4AH,A 4A内容为F-2X+1低位
XCH A,B B内容为F-2X+1低位,A内容为F-2X高位
ADDC A,#00H 考虑F-2X+1的进位
MOV 49H,A 49H的内容为F-2X+1高位
CLR C 计算X=X-1
MOV A,52H低位
SUBB A,#01H
MOV 52H,A
MOV A,51H高位
SUBB A,#00H
MOV 51H,A
RP4:
CLR C 终判值减1
MOV A,54H
SUBB A,#01H
MOV 54H,A
MOV A,53H
SUBB A,#00H
MOV 53H,A
ORL A,54H
JNZ RP2 插补没结束,转至RP2
LJMP 0000H
RP6:
ACALL YMP Y电动机正转
MOV R6,#02H 此处“2”,为“F+2Y+1”的“2”
RP7:
MOV A,4AH F+2Y+1
ADD A,50H
MOV 4AH,A
MOV A,49H
ADDC A,4FH
MOV 49H,A
DJNZ R6,RP7
MOV A,4AH
ADD A,#01H
MOV 4AH,A
MOV A,49H
ADDC A,#00H
MOV A,50H
ADD A,#01H
MOV 50H,A
MOV A,4FH
ADDC A,#00H
MOV 4FH,A
AJMP RP4