Smoother (X,Y,Z) movement for 3D printers and CNC.
davidsaunders
Posts: 1,559
Firstly I must thank kwinn for the concept, for he solidified it in my mind.
This is a simple speed ratio based system for creating a linear movement in 3 dimentions, so long as the motors on all axises are equally capable under there respective loads. At present it does NOT have any acceleration, so it is still a bit limited.
I also need to write more of the Public methods for setting control parameters.
Though this is a quick response to the idea presented by kwin, and it takes a single cog. There is a slight delay between axis movements, though this is a lot better than using a modified form of Bresenham's Line Algorithm for the purpose, and this is also a lot smaller.
The best part is that this is mostly in PASM .
If you notice any errors or anything that could be done better please let me know.
This is a simple speed ratio based system for creating a linear movement in 3 dimentions, so long as the motors on all axises are equally capable under there respective loads. At present it does NOT have any acceleration, so it is still a bit limited.
I also need to write more of the Public methods for setting control parameters.
Though this is a quick response to the idea presented by kwin, and it takes a single cog. There is a slight delay between axis movements, though this is a lot better than using a modified form of Bresenham's Line Algorithm for the purpose, and this is also a lot smaller.
The best part is that this is mostly in PASM .
'This is a simple stepper motor controler for a three axis device like a 3D printer. 'We are only using full stepping for this one. CON xBase = 0 yBase = 4 zBase = 8 xPinM = $000F 'Pin Mask for X axis stepper. yPinM = $00F0 'Pin Mask for Y axis stepper. zPinM = $0F00 'Pin Mask for Z axis stepper. zrPin = 12 'Zeroing switch input. xMax = $7FFFFFFF 'Furthest from zero allowed for X axis. yMax = $7FFFFFFF 'Furthest from zero allowed for Y axis. zMax = $7FFFFFFF 'Furthest from zero allowed for Z axis. xDely = 156250 yDely = 156250 zDely = 156250 'The parameter offsets in the array that the cog reads: pCX = 0 pCY = 1 pCZ = 2 pNX = 3 pNY = 4 pNZ = 5 pDX = 6 pDY = 7 pDZ = 8 pGo = 9 VAR LONG DY, DX, DZ LONG PBLCK[12] LONG xDelay, yDelay, zDelay PUB MoveTo(ax, ay, az) DX := UABS(ax - PBLCK[pCX]) DY := UABS(ay - PBLCK[pCY]) DZ := UABS(az - PBLCK[pCZ]) IF DX > DY AND DX > DZ PBLCK[pDX] := xDelay PBLCK[pDy] := ((DX << 4) * ((DX / DY) << 4)) >> 4 PBLCK[pDz] := ((DX << 4) * ((DX / DZ) << 4)) >> 4 pBLCK[pNX] := ax pBLCK[pNY] := aY pBLCK[pNZ] := aZ PBLCK[pGo] := 1 PRI UABS(v) IF v < 0 v := -v RETURN v PUB Init COGNEW(Main, @PBLCK) xDelay := xDely yDelay := yDely zDelay := zDely DAT ORG Main MOV DIRA, Msk :Lp JMPRET GetP_R,GetP OR CG, CG WZ IF_NZ JMPRET DoLine_R, DoLine IF_Z JMP #:Lp '┌──────────────────────────────────────────────────────────────────┐ '│PROC: GetP │ '│ │ '│*DESCRIPTION: │ '│ Reads the parameter block from HUB RAM. Takes 432 to 446 clock │ '│ cycles. │ '│ │ '└──────────────────────────────────────────────────────────────────┘ GetP MOV Ptr, PAR 'PAR points at the Parameter block. MOV Lptr, #CurX 'COG Address of first parameter. MOV C, #12 :Lp MOVS :upd, ptr ADD LPtr, #4 :upd RDLONG Lptr, Ptr DJNZ C, #:Lp GetP_R RET '┌──────────────────────────────────────────────────────────────────┐ '│PROC: PutP │ '└──────────────────────────────────────────────────────────────────┘ PutP MOV Ptr, PAR 'PAR points at the Parameter block. MOV Lptr, #CurX 'COG Address of first parameter. MOV C, #12 :Lp MOVS :upd, ptr ADD LPtr, #4 :upd WRLONG Lptr, Ptr DJNZ C, #:Lp PutP_R RET '┌──────────────────────────────────────────────────────────────────┐ '│PROC: DoLine: │ '│ │ '│*DESCRIPTION: │ '│Moves X, Y, and Z based on the delays until the move is complete. │ '│ │ '│ │ '└──────────────────────────────────────────────────────────────────┘ DoLine MOV XT, CNT MOV YT, CNT MOV ZT, CNT ADD XT, XDly ADD YT, YDly ADD YT, YDly :Lp CMP XT, CNT WZ,WC IF_BE ADD XT, CNT IF_BE JMPRET MvX_R, MvX CMP YT, CNT WZ,WC IF_BE ADD YT, CNT IF_BE JMPRET MvY_R, MvY CMP YT, CNT WZ,WC IF_BE ADD YT, CNT IF_BE JMPRET MvY_R, MvY CMP CurX, X WZ,WC IF_BE CMP CurY, Y WZ,WC IF_BE CMP CurZ, Z IF_BE JMPRET PutP_R,PutP IF_BE RET JMP #:LP DoLine_R RET '┌──────────────────────────────────────────────────────────────────┐ '│PROC: MvX: │ '│ │ '└──────────────────────────────────────────────────────────────────┘ MvX SUB X, CurX NR,WC,WZ MOV T, Stps IF_Z JMP MvX_R IF_C SUB CurX, #1 IF_NC ADD CurX, #1 MOV T0, CurX AND T0, #$3 SHL T, XBase SHR T, T0 MOV T0, OUTA ANDN T0, XMsk JMP #Mv_T '┌──────────────────────────────────────────────────────────────────┐ '│PROC: MvY: │ '│ │ '└──────────────────────────────────────────────────────────────────┘ MvY SUB Y, CurY NR,WC,WZ MOV T, Stps IF_Z JMP MvX_R IF_C SUB CurY, #1 IF_NC ADD CurY, #1 MOV T0, CurY AND T0, #$3 SHL T, YBase SHR T, T0 MOV T0, OUTA ANDN T0, YMsk JMP #Mv_T '┌──────────────────────────────────────────────────────────────────┐ '│PROC: MvZ: │ '│ │ '└──────────────────────────────────────────────────────────────────┘ MvZ SUB Z, CurZ NR,WC,WZ MOV T, Stps IF_Z JMP MvX_R IF_C SUB CurZ, #1 IF_NC ADD CurZ, #1 MOV T0, CurZ AND T0, #$3 SHL T, ZBase SHR T, T0 MOV T0, OUTA ANDN T0, ZMsk Mv_T OR T0, T MOV OUTA, T0 MvX_R MvY_R MvZ_R RET CurX LONG 0 'The current X Position in steps. CurY LONG 0 'The current Y Position in steps. CurZ LONG 0 'The current Z Position in steps. X LONG 0 'The requested X position in steps. Y LONG 0 'The requested Y position in steps. Z LONG 0 'The requested Z position in steps. XDly LONG xDely 'The delay between X steps, in clock cycles. YDLY LONG yDely 'The delay between Y steps, in clock cycles. ZDLY LONG zDely 'The delay between Z steps, in clock cycles. CG LONG 0 'A flag to tell us when to go. C LONG 0 'Used in loops as an index. T LONG 0 'Used to store in process values. T0 LONG 0 XT LONG 0 YT LONG 0 ZT LONG 0 Stps LONG %0011_0110_1100_1001 'The step output values. Msk LONG (xPinM | yPinM | zPinM) XMsk LONG xPinM YMsk LONG yPinM ZMsk LONG zPinM Lptr LONG 0 Ptr LONG 0 'The states of a the four pins to control a steper in forward order. 'cStep BYTE %0011, %0110, %1100, %1001 {{ ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ TERMS OF USE: MIT License │ ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │ │files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │ │modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│ │is furnished to do so, subject to the following conditions: │ │ │ │The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│ │ │ │THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │ │WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │ │COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │ │ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ }}I caught a couple of errors in my code. They are corrected.
If you notice any errors or anything that could be done better please let me know.
Comments
IT IS NOW FIXED.
I again ask if anyone notices any errors, or has any suggestions on how to do it better, please let me know.
As always I know that I make mistakes, so if you notice any please point it out.
If anyone can see a way to make this a bit smaller it would be appreciated, I would like to get this spin module under 128 longs (0.5KB).
I still need to add code for detecting the zero switch, though that is not a huge issue (manual zeroing works well).
I did not know that SPIN had an absolute value of operator, thank you for that.
I will be adding provisions to change the delay values, so that it can support user specified speeds provided in GCode (I forget the command at the moment). I will also be adding some code to make sure that the speeds are with in the limits of all axises, for devices that have differing limits for each axis.
I have also made some simple changes to the code to improve it.
In order to maintain values in the tenths with integers I pass all values in from G-Code as value << 10
Please point out any errors you may see, as well as any improvements you can see possible. Thank you all.
Looks good. I'm really happy to see you doing something with this idea. I've often thought a lot of the current programs for controlling 3D motion were more complicated than they needed to be but never had the time or hardware to test things on. Great work so far, and hope it proves to be a useful idea and driver code.
I will let yo know how it goes once I have tested it on real Hardware. Thank you for the suggestion.
I agree that much of the driver code seems way to complex for what does. I have always subscribed to the KISS school of thought on such things.
This may apply: Simple speed profiles in real time, fixed point math only
For my ramping I was thinking something like taking the inner loop: And modifying it so as to take a small ramping delta, for a number of steps, and just adjust the delay accordingly. The delta would be calculated before passing the parameters to the assembly code, as would the number of steps for each axis to keep everything in step.
So the inner loop would end up looking something like: With additional provisions for ramping down of course, though that should do the ramp up part.
New delta time = old delta time - (old delta time ramping function * ramp factor)
The ramping function would subtract a fraction of the delta time from the current delta time to generate the new delta time. For example the current delta time could be shifted right 10 bits and multiplied by the ramp factor (lets say 7) to decrease the new delta time by 7/1024ths of the current delta time. This would increase the speed of the stepper by approximately 0.7% every step. The same calculation could be used to ramp up speed by subtracting from the delta time, and ramp down by adding to the delta time.
I try to compile the code from post #7 (http://forums.parallax.com/showthread.php/160860-Smoother-%28X-Y-Z%29-movement-for-3D-printers-and-CNC.?p=1327408&viewfull=1#post1327408) in PropellerTool and I get errors in lines 42, 43 & 44, about missing parenthesis at the end of each line.
This would be the correct code? The ">> 10" at the end of DZ is correct?
Antonio
Thanks for the clarification. Now it seems more logical.
Is this a typo error too?
Do you have a demo or explanation how to use this? I have tried the following code, but running in GEAR Emulator It can't worked yet:
I did have the filament feed stepper control there as well, and moved that out to a seperate file, so it used to be correct.
Easy to correct, the af parameter used to be to set the feedrate for the filamant.