3D Printer, 3D Bresenham's Line in SPIN.
davidsaunders
Posts: 1,559
Here:
Note that CX, CY, and CZ are the current X, Y, and Z positions.
VAR LONG CX LONG CY LONG CZ LONG DX LONG DY LONG DZ LONG SX LONG SY LONG SZ LONG ER LONG E LONG E2 LONG ER2 PUB LineTo3D(X,Y,Z) DX := UABS(CX - X) IF CX < X SX := 1 ELSE SX := -1 DY := UABS(CY - Y) IF CY < Y SY := 1 ELSE SY := -1 DZ := UABS(CZ - Z) IF CZ < Z SZ := 1 ELSE SZ := -1 IF DX > DY ER := DX / 2 IF DX > DZ ER2 := DX / 2 ELSE ER2 := -DZ / 2 ELSE IF DY > DZ ER2 := DY / 2 ELSE ER2 := -DZ / 2 ER := -DY / 2 REPEAT WHILE (TRUE) IF X == CX AND Y == CY QUIT E := ER E2 := ER2 IF E > (-DX) ER -= DY CX += SX MvX(SX) IF E < DY ER += DX CY += DY MvY(SY) IF DX > DY IF E2 > (-DX) ER2 -= DZ IF E2 < DZ ER2 += DX CZ += SZ MvZ(SZ) ELSE IF E2 > (-DY) ER2 -= DZ IF E2 < DZ ER2 += DY CZ += SZ MvZ(SZ)And the 2D version from which the 3D was derived (also mine):
VAR LONG CX LONG CY LONG DX LONG DY LONG SX LONG SY LONG ER LONG E PUB LineTo(X,Y) DX := UABS(CX - X) IF CX < X SX := 1 ELSE SX := -1 DY := UABS(CY - Y) IF CY < Y SY := 1 ELSE SY := -1 IF DX > DY ER := DX / 2 ELSE ER := -DY / 2 REPEAT WHILE (TRUE) IF X == CX AND Y == CY QUIT E := ER IF E > (-DX) ER -= DY CX += SX MvX(SX) IF E < DY ER += DX CY += DY MvY(SY)
Note that CX, CY, and CZ are the current X, Y, and Z positions.
Comments
x, y, z variables by steps of YZ, ZX, XY (where upper case X, Y, Z are the total steps in each axis), until
they all reach XYZ - whichever of x, y, z is smallest produces a step, then gets incremented, and the time
value is bressenham'd against this smallest value. Time goes T ticks as the x, y, z values go XYZ. Typically
64 bit arithmetic is needed for this.
This doesn't help with acceleration / deceleration ramps though, but that can be added as a more complex
bressenham style relationship between T and x,y,z I think.
[ by the way you have explicitly ignore axes with zero movement, otherwise the XYZ product falls to zero ]
Assuming the XYZ motors can start and accellerate at the same speed the longest line would determine the maximum starting speed and acceleration. The other axes would have have longer delta times based on it's length relative to that of the longest line. The rates of accelleration could also be calculated the same way.
Assuming that all steppers are of equal ability:
PSEUDOCODE: That is just off the top of my head, then have a separate loop watching the counter for when to step each. Is that the basic idea of what you are suggesting??
BTW, I'd forget about Bresenham. It's not suitable for motor control due to the jitter. The approach cited by Mark_T is much better.
-Phil
I have recently done something similar with my drivers, but they all run in different cogs and the speed is constant with no ramping. The longest axis is first determined and the total travel time is calculated. The other axes step pulse rate are determined by the total travel time of the longest axis.
Though I do thank you for your thoughts,.
Close, but not exactly what I had in mind. Sometimes I have a hard time putting what I visualize into words so I will try a simple example using motor steps instead of actual distances. No accelleration and maximum speed is 1000 steps/second for X, Y, and Z.
Lets say we want to move from X = 1, Y = 1, Z = 1 to X = 1001, Y = 501, Z = 251
The number of motor steps would be Xs = 1000, Ys = 500, Zs = 250
The delta time (in clks at 80MHz) would be Xd = 80_000, Yd = 160_000, Zd = 320_000
If each stepper is controlled by it's own cog and the 3 stepper cogs are synchronized all they need to “draw” or travel over that line is the number of steps to take and the delta time between each step.
Cog X would step the motor 1000 times with a delay of 80,000 clocks between each step.
Cog Y would step the motor 500 times with a delay of 160,000 clocks between each step.
Cog Z would step the motor 250 times with a delay of 320,000 clocks between each step.
Not much more difficult to have a pasm program running in a single cog do it either.
So Assuming a move from X,Y,Z to X1,Y1,Z1; if Cog X is the greatest distance, and X is to move with a delay of XDelay between stepps, then the speed for the other two would be:
YDelay := XDelay * (abs(x1-x) / abs(y1-y))
ZDelay := XDelay * (abs(x1-x) / abs(y1-y))
Is that what you are saying?
If I understand correctly I think I get the idea. I think it is time for me to write a little PASM (thankfully my preferred language on the propeller).
I give you many thank you's for the advice.
You mean something like:
Yes, that looks pretty much like what I had in mind. I have only taken the time to skim through your code, so I may be wrong.