|
|
View previous topic :: View next topic |
Author |
Message |
john lee Guest
|
Bresenham algorithm in a Pic 16c73A |
Posted: Fri Nov 15, 2002 12:37 pm |
|
|
Hi, I have been using Pics for a few years now, has anyone written a useable interpretation of Jack Bresenham''s line algorithm for a Pic?I am using a 16c73a to drive a multi-axis machine, i.e to generate speed-ramped pulse trains in order to provide synchronised point-to-point moves, using a velocity profile.The move is not trapezoidal, but uses s-ramps to avoid the otherwise instantaneous torque foldback/windup at the turning-points. I am having problems with the interrupt latency.
System works, but, one of u has probably done it better!
Any contributions most welcome.
Regards,
Stigga the dump.
___________________________
This message was ported from CCS's old forum
Original Post ID: 9015 |
|
|
Doug Kennedy Guest
|
Re: Bresenham algorithm in a Pic 16c73A |
Posted: Fri Nov 15, 2002 1:52 pm |
|
|
This will draw a line between cartesian pts (x1,y1) (x2,y2)
plot (x,y,set) is a routine to turn on or off a pixel depending on the value of set.
Bresenham used the finite difference calculus to gain speed and avoid multipication. I have circle algorithms if you are interested
void line(long x1,long y1,long x2,long y2, int set)
{
long i,line_length,x,y;
signed long deltax,deltay,accm_error;
signed int xchange,ychange;
// bresenham algorithm for lines
disable_interrupts(GLOBAL);
X = x1 ;
Y = y1;
DeltaX = x2 - x1;
DeltaY = y2 - y1 ;
Ychange=1;
Xchange=1;
If (DeltaX < 0 )
{
XChange = -1 ;
DeltaX = -DeltaX ;
}
If (DeltaY < 0 )
{
YChange = -1;
DeltaY = -DeltaY ;
}
accm_error = 0;
i = 0 ;
If (DeltaX < DeltaY)
{
Line_Length = DeltaY + 1;
while (i < Line_Length)
{
Y =Y + YChange ;
accm_error = accm_error + DeltaX ;
IF (accm_error > DeltaY)
{
X = X + XChange ;
accm_error = accm_error - DeltaY ;
}
i = i + 1 ;
plot(x,y,set);
}
}
else
{
Line_Length = DeltaX + 1;
While (i < Line_Length)
{
X =X + XChange ;
accm_error = accm_error + DeltaY;
If (accm_error > DeltaX)
{
Y = Y + YChange;
accm_error= accm_error - DeltaX ;
}
i = i + 1;
plot(x,y,set);
}
}
enable_interrupts(GLOBAL);
}
___________________________
This message was ported from CCS's old forum
Original Post ID: 9022 |
|
|
john lee Guest
|
Re: Bresenham algorithm in a Pic 16c73A |
Posted: Sat Nov 16, 2002 8:30 am |
|
|
:=This will draw a line between cartesian pts (x1,y1) (x2,y2)
:=plot (x,y,set) is a routine to turn on or off a pixel depending on the value of set.
:=Bresenham used the finite difference calculus to gain speed and avoid multipication. I have circle algorithms if you are interested
:=
:=
:=
:=void line(long x1,long y1,long x2,long y2, int set)
:={
:=long i,line_length,x,y;
:=signed long deltax,deltay,accm_error;
:=signed int xchange,ychange;
:=// bresenham algorithm for lines
:=disable_interrupts(GLOBAL);
:= X = x1 ;
:= Y = y1;
:=
:=DeltaX = x2 - x1;
:=DeltaY = y2 - y1 ;
:=Ychange=1;
:=Xchange=1;
:=
:=If (DeltaX < 0 )
:= {
:= XChange = -1 ;
:= DeltaX = -DeltaX ;
:= }
:=
:=
:=
:=
:=If (DeltaY < 0 )
:= {
:= YChange = -1;
:= DeltaY = -DeltaY ;
:= }
:=
:=
:=
:=
:=accm_error = 0;
:=i = 0 ;
:=
:=If (DeltaX < DeltaY)
:= {
:= Line_Length = DeltaY + 1;
:=
:= while (i < Line_Length)
:= {
:= Y =Y + YChange ;
:= accm_error = accm_error + DeltaX ;
:=
:= IF (accm_error > DeltaY)
:= {
:= X = X + XChange ;
:= accm_error = accm_error - DeltaY ;
:=
:= }
:=
:= i = i + 1 ;
:= plot(x,y,set);
:= }
:= }
:=else
:= {
:= Line_Length = DeltaX + 1;
:=
:= While (i < Line_Length)
:= {
:= X =X + XChange ;
:= accm_error = accm_error + DeltaY;
:=
:= If (accm_error > DeltaX)
:= {
:= Y = Y + YChange;
:= accm_error= accm_error - DeltaX ;
:= }
:=
:= i = i + 1;
:= plot(x,y,set);
:= }
:= }
:=
:=
:=
:=
:=enable_interrupts(GLOBAL);
:=}
Hi, Doug.
Many thanks for your sample, I used a very watered-down version of the bresenham algorithm ,for octant(0) it looks like:
long int x,y,x_count; //x & y are the abs numbers of pulses to output,x_count is the current count in x//
int v_min,v_max,ramp_rate //parameters to the move func
//the move func generates 2 pulse trains to drive 2 machine axes//
//in a co-ordinated move with velocity ramps//
bres_line(x,y) //case for octant(0),where X>=Y
{
x_count=0 //init x_count
E=(2*y)-(2*x); //inital error(doubled to avoid floats)//
do
{
if E<0 then E=E+(2*y);
else E=E+(2*y)-(2*x);
pulse_x(); //pulse the major axis,X
if E>=0 then pulse_y();//pulse y if test true
x_count=x_count++; //increment x
}
while(x_count<=x);
}
//pulse_x()&pulse_y() are funcs to pulse the axes high for
//10usec. The move() func simply co-ordinates it all, and uses
the rtcc and ccp1 to generate pulses at a variable period, period is updated during the ccp1 interrupt. Works not bad, but
in the real version, I am counting x_pulses on the int_ext,and appear to be getting glitches in the write to the ccp1.
Basically I have been lazy in debugging it, and thought,"Why re-invent the wheel?" Someone somewhere has it all-singing already.
Many thanks for the code, would like to see your circles?
Regards,
John Lee.
___________________________
This message was ported from CCS's old forum
Original Post ID: 9033 |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|