Gcode Multi-Axis-Control in PASM
msrobots
Posts: 3,709
OK, I have to admit I had some very bad weeks at work. Besides doing my usual chores I am hunting a elusive bug. No correlation of OS/Browser/Computer of affected users. Sometimes it works, sometimes it does not. It is not a major thing, just one Text field not showing up with the correct value. It stays empty. Sometimes, for some user (less than 5%).
But it drains on me. I wrote all the code. There is no one to blame and sadly no one to ask, since I am the one and only programmer there. I was stuck. After weeks of staring and testing I gave up. I came to the conclusion that I am unworthy and not able to call myself a programmer anymore.
Before starting to drink and give up my beloved profession, I decided to "Something completely different" to ease my head off the problem.
If you loose the fun of programming, what can you do to rescue yourself? - Get the Propeller out and have some FUN programming!
And so I did. Inspired by @Idbruce I started to look at that multi-axis-thing. Just as challenge, I do not really need a stepper driver, I even do not own any stepper-motors to test it with.
So I build myself some spin test-bed to check out my idea of using a HUB-long as common tick-counter, driven by one controller-cog, read by the axis-cogs. First I planned to use CNT, but decided against because ramping is hopefully more easy when I can vary my step-speed.
As usual things got out of hand quite fast. To test my multi-axis-controller I had to feed it with data, so I needed a Gcode parser. After testing in Spin with - hmm - slow but promising results, I decided to do this in PASM. And the funny thing is, it was quite easy to port the spin to PASM, sometimes the PASM was even smaller!
And now all of it is PASM, even the starting SPIN cog gets used. No need for it anymore.
COG0 - runs SPIN first, then the Gcode Parser pasmgcode
COG1 - runs JDcogSerial a fullduplex serial driver with buffers in the COG. I really love that one, easy to use from other spin or PASM COGs
COG2 - runs the Multi-Axis-Controller pasmaxisctl, getting movements from the Gcode COG and dispatching them to the Axis-COGs.
COG3-COG7 (aka 5 of them) are available as Axis-COGS.
Since I wanted to test more then 5 axis, and the 1-axis COG is below 90 longs, I also build 2-axis, 3-axis and 4-axis COGs using jmpret. Once you get the schema done, that jmpret-multitasking is quite easy to use.
The current Demo uses 1-axis and 2-axis per COG driver. The 5 COGs are running 9 axis together, U,V,W,X,Y,Z,A,B,C.
To run this Demo you just need any propeller board you have with 5Mhz and a serial connection to P30/P31 at 115200 baud.
By now the drivers do not toggle any pins, you need to add that if you want to. For now this are just templates reporting that the step is done.
So ANY board you have will do, it does not use any pins except serial. Just run in RAM for testing.
After loading and opening your Terminal program (115200 baud), you have to press 'THE ANY KEY' on your keyboard. Any of the Any-Keys will do.
switch off local echo for nicer displays.
After pressing the Any-Key you will get a short status message from Spin, then Spin dies and the gcode parser takes over the serial line.
From now on you just can throw Gcode at it.
a simple 'X10' will do as example
The Parser starts up as command G00 (fast movement) and G90 (absolute positioning)
Currently supported commands are
G0 or G00 - linear interpolation - set speed to fast, 4 times normal speed
G1 or G01 - linear interpolation - set speed to normal
G90 - set absolute positioning for axis values
G91 - set relative position for axis values
Currently supported axis are
U,V,W,X,Y,Z,A,B,C
I am miss-using command "D" for output control, or debug level. It starts as "D1"
Debug level are
D0 - no output on serial
D1 - output positions and status after each completed movement. (standard at startup)
D2 - as above but gives you also used delay values and some timing information
D3 - as above but gives you positions for each step taken
I am also miss-using command "F"
At startup the step counter for movements is more or less free running. With the "F" command you can set a frequency in Hz for the fastest step.
a "F10" will try to do 10 steps per second on the fastest axis. Nice for debugging and watching steps.
a "F1000" will try to run the fastest axis at 1kHz.
a "F" or "F0" will switch off the choke and go back to free running again.
Enjoy!
Mike
But it drains on me. I wrote all the code. There is no one to blame and sadly no one to ask, since I am the one and only programmer there. I was stuck. After weeks of staring and testing I gave up. I came to the conclusion that I am unworthy and not able to call myself a programmer anymore.
Before starting to drink and give up my beloved profession, I decided to "Something completely different" to ease my head off the problem.
If you loose the fun of programming, what can you do to rescue yourself? - Get the Propeller out and have some FUN programming!
And so I did. Inspired by @Idbruce I started to look at that multi-axis-thing. Just as challenge, I do not really need a stepper driver, I even do not own any stepper-motors to test it with.
So I build myself some spin test-bed to check out my idea of using a HUB-long as common tick-counter, driven by one controller-cog, read by the axis-cogs. First I planned to use CNT, but decided against because ramping is hopefully more easy when I can vary my step-speed.
As usual things got out of hand quite fast. To test my multi-axis-controller I had to feed it with data, so I needed a Gcode parser. After testing in Spin with - hmm - slow but promising results, I decided to do this in PASM. And the funny thing is, it was quite easy to port the spin to PASM, sometimes the PASM was even smaller!
And now all of it is PASM, even the starting SPIN cog gets used. No need for it anymore.
COG0 - runs SPIN first, then the Gcode Parser pasmgcode
COG1 - runs JDcogSerial a fullduplex serial driver with buffers in the COG. I really love that one, easy to use from other spin or PASM COGs
COG2 - runs the Multi-Axis-Controller pasmaxisctl, getting movements from the Gcode COG and dispatching them to the Axis-COGs.
COG3-COG7 (aka 5 of them) are available as Axis-COGS.
Since I wanted to test more then 5 axis, and the 1-axis COG is below 90 longs, I also build 2-axis, 3-axis and 4-axis COGs using jmpret. Once you get the schema done, that jmpret-multitasking is quite easy to use.
The current Demo uses 1-axis and 2-axis per COG driver. The 5 COGs are running 9 axis together, U,V,W,X,Y,Z,A,B,C.
To run this Demo you just need any propeller board you have with 5Mhz and a serial connection to P30/P31 at 115200 baud.
By now the drivers do not toggle any pins, you need to add that if you want to. For now this are just templates reporting that the step is done.
So ANY board you have will do, it does not use any pins except serial. Just run in RAM for testing.
After loading and opening your Terminal program (115200 baud), you have to press 'THE ANY KEY' on your keyboard. Any of the Any-Keys will do.
switch off local echo for nicer displays.
After pressing the Any-Key you will get a short status message from Spin, then Spin dies and the gcode parser takes over the serial line.
From now on you just can throw Gcode at it.
a simple 'X10' will do as example
The Parser starts up as command G00 (fast movement) and G90 (absolute positioning)
Currently supported commands are
G0 or G00 - linear interpolation - set speed to fast, 4 times normal speed
G1 or G01 - linear interpolation - set speed to normal
G90 - set absolute positioning for axis values
G91 - set relative position for axis values
Currently supported axis are
U,V,W,X,Y,Z,A,B,C
I am miss-using command "D" for output control, or debug level. It starts as "D1"
Debug level are
D0 - no output on serial
D1 - output positions and status after each completed movement. (standard at startup)
D2 - as above but gives you also used delay values and some timing information
D3 - as above but gives you positions for each step taken
I am also miss-using command "F"
At startup the step counter for movements is more or less free running. With the "F" command you can set a frequency in Hz for the fastest step.
a "F10" will try to do 10 steps per second on the fastest axis. Nice for debugging and watching steps.
a "F1000" will try to run the fastest axis at 1kHz.
a "F" or "F0" will switch off the choke and go back to free running again.
Enjoy!
Mike
Comments
For now I am not there yet.
I need to decouple Gcode parsing (pasmgcode) from executing the Gcode (pasmaxisctl), not just for buffering, but to do effective ramping I will need to look ahead on incoming Gcode commands to decide how to ramp.
By now pasmgcode waits for pasmaxisctl to finish, not good.
The axis-COGs are fairly decoupled, pasmaxisctl provides the internal stepcounter and just waits until all axis-cogs report their complete movement done until accepting new commands from the gcode parser, good enough.
The whole SCALING thing is not in there. By now I use just integer positions and tread them as STEPS of the stepper.
Good enough for testing, but unusable with and real Gcode.
Besides accepting decimal values for axis-positions one would need to calculate step numbers out of inches/mm?
So a movement of 0.0023 on the X axis in Gcode is how much steps for the X stepper?
Same goes for the "F" command representing a feed of xxx inches(or mm) per minute?
Not easy, but I found some interesting link to study
here it is, http://www.cnccookbook.com/CCCNCGCodeCourse.htm You have to scroll down a lot until you find the real info
Anyways I have fun programming again
Enjoy!
Mike
LOL, the number of times that I have spent an entire day, looking for an elusive bug and then gone for a late dinner/ bottle of wine and then BAM! I figure the problem. No way can it wait until morning, I have to get back and fix it.
Nice work on the demo. Did you ever consider a pin as a master ticker/counter?
So a movement of 0.0023 on the X axis in Gcode is how much steps for the X stepper?
Machines vary in terms of how the steppers connect to real motion. For example some low cost bench tops may use acme threaded rod at 20 TPI. Then you'd have to know the stepper rate whether whole, half, quarter, /10 etc. If a 20TPI acme is driven direct from a stepper at whole steps ie 200 steps per rev, then 200 * 20 = 4000 steps per inch. 1/2 step is 8000 steps per inch.
One revolution at 1/2 step is 400 steps = 1/20th of an inch = .05". A half revolution is 200 steps = .025. 100 steps = .0125, 50 steps = .00625, 25 steps = .003125". Basically 1 step at half stepping with acme 20TPI = 1/8000 = .000125" per step. A lot of machines would not even have or need such precision higher than .001" or .0001". In my case running a pick and place app I created on the PC that drives the Propeller, as I recall I did some translation to take a decimal position from the PCB part location and converted it to integer based on the math I described. It was years ago so I'd have to dig that old code out to even begin to remember how it worked. I always considered that if I did a Gcode machine that required synchronized ramping I would use a cog that drives a pin for a master ticker, the clock on that pin would manage acceleration/ramping up, maximum run speed, then decel/ramping down. Each axis would look at the master ticker and move accordingly based on it's own distance requirement.
Some machines would use ball screws, usually much less than 20TPI ie 5 turns, 10 turns, etc. Some use rack and pinion with a belt drive to achieve some reduction off the stepper before hitting the pinion.
yes, I considered a Pin also as Master Tick, but decided against, since I needed HUB-access per step anyways to deliver the new position back to the master-axis-controller.
So I don't have a common tick pin but a common clock long in HUB.
And yes, I think once I have some buffering between Gcode reading and driving the axiscontroller I can figure out the need for ramping and run the master-clock at different speeds to archive sync ramping on all axis.
By now my internal clock runs 16 times the speed of the fastest axis (that one with the most steps for the movement), so the slower axis has 16 positions between the fastest steps to decouple the steps of the slower axis from the frequency of the faster one.
For example, if the fastest axis has to do 5 steps and the next axis has to do 4 steps, the 4 steps will be executed nicely between the 5 steps, not at the same time. That gives more smooth movements for all axis.
As for the scaling you just confirmed my worst thoughts.
To clear that up:
!. The numbers in the Gcode are either inch/minute or mm/minute for the feed rate.
That basically sais I need two different routines to read the numbers including decimals.
a) if in mm mode the 1 in X1.2345 is one mm and the 2345 are 0.2345 mm in decimal. as of ten-thousands of a mm.
easy to calculate, 1 multiplied by 10000 and 2345 added gives me the position in 1/10000 of a mm.
Now I need to multiply this by the number of steps this single axis needs to move for 1/10000 of a mm.
This is now my stepper resolution or step count, right?
b) in inch mode the 1 in X1.2345 is one inch and the 2345 are what exactly? 0.2345 in decimal as in ten-thousands of an inch OR is the number 12 involved there still? Sorry but after 10 years in the US of A I still have problems with imperial measurements.
I am still in need to multiply this number by the numbers of steps this single axis needs to move 1/10000 of a inch. (or isn't it a 10000 of a inch?)
This is now my stepper resolution or step count, right?
Am I near here or way off?
@Mikster,
programming is a weird profession. Sometimes I shut down things, fighting with a solution, go to bed and in the morning I have the solution and can just type it down.
Enjoy!
Mike
The P1 can do very precise WAITs, but on a one-per-COG basis, and it can also run NCOs, of 2 per COG, but not in quadrature.
Those HW abilities and limits, define what you might do in a Prop.
If you want 2 pin quad-encoded out, with full rate precision, that looks to me like one-axis-per COG.
If you can accept Step.Dirn out, then 2 x NCO can do 2 of those per COG.
Taking the NCO I get numbers like these for 1000 steps / sec example
F1=80M*round((1000/80M)*2^32)/2^32 F1 = 999.9983Hz
and the next-possible step-rate is
F2=80M*round(1+(1000/80M)*2^32)/2^32 F2 = 1000.016927Hz
F2-F1 = 18.626 millihertz step size.
This is the pasm1axis driver, the model I modelt the other drivers from. All other ones are just more of the same, nicely webbed together with jmpret's.
This one takes care of one axis, pasm2axis can handle two axis, pasm3axis can handle three axis and , pasm4axis can handle four axis.
As you can see, on the end of the code are two stubs you need to fill, "doSetup" and "doStep".
In "doSetup" you need to add code to set the pins needed for your stepper to output.
In "doStep" you need to add code to actual do one step.
Enjoy!
Mike
I think the secret is in the 'nicely between' - but with a 16x clock, that seems just too coarse to give the fine control needed ?
I just chose 16 as a starting value, I can easy change that, it is the constant "stdratioscale" in constants.spin. But this is in between the steps of the axis with most steps for that single move and seems to work quite fine by now.
Try it out.
Load the program in any P1 board you have, connect serial p30/31 at 115200 baud.
Hit the any Key. switch to debug level 3 by typing D3 [enter]
now type U1V2W3X4Y5Z6A7B8C9 [enter]
and you will see
the number on the left is the internal step count when that event occurred.
Seems to work fine
this are by now single stepper step positions, not mmm/inch or whatever
Enjoy!
Mike
You can see the coarse/granular effect I mention, on the C 9 column for example.
6 appears twice, and 3,5,7 appear 4 times.
That means a 2:1 span in Step rate being asked. ie The 6 step is much faster than 3,5,7
Z 5 has a shortest of 4 and a longest of 6, still a variance of 2, but a smaller % change.
Motors are good at averaging, so maybe real system can tolerate that variance in step-widths ?
It worked perfectly for years until I got the first Neoden, then later replaced that Neoden with the bigger model shown.
The most resolution most would ever need is 4 decimals. As I mentioned you need to know know how many steps that particular machine needs to move one inch. In my case it was 8000. So just multiply the entire number by 8000. IF the X position is 4.7895 then the prop receives 38,316, and in cases where there were decimal results I just ignored it.
First line comes from debug level 2 (D2) and gives the number of internal clock-ticks used for the movement and the delay values per axis used. I added the direction to the delay values, because they basically then represent the relative velocity of that running axis, a value I think I need to calculate if I need to ramp down between movements.
The next lines come with debug level 3 (D3) and show the steps taken for all axis. First number represents the clock-tick when step was performed, the next show the actual position of the last step finished for the axis represented.
The last line comes with debug level 2(D2) and shows a ruff calculation of max axis frequency including the serial output overhead, so just sensefull if you use bigger distances as 1-9 steps as in my example.
But running 3000 steps (like X3000) with debug level 3 (D3) fills up your screen quite fast.
So to have some meaningful answer out of the last line you should use debug level 2 (D2) and higher values for step count, like X0 [enter] and then X12345 [enter] then it shows a more useful result.
if you choke down the free running internal stepcounter to a base frequency like 10kHz by typing F10000 then the display will be 995x still including the overhead of the serial output, but it does not matter so much anymore.
Ahh - use G01 for normal speed, else you will get 4 times of the frequency since G0 runs by now 4 times faster as G1
Enjoy!
Mike
Yes it seems to be like that, but did you included the timong values on the left?
just seeing a value 6 times does not say it is 6 equal times repeated. A line gets send at time X when one or more values are changed.
C fires at - 11, 27, 43, 59, 75, 91, 107, 123 and 139 - evenly spaced by 16
B fires at - 11, 27, 47, ahh I see.
I guess it is a impact of the serial output, lets see. I do have the CNT value of the last step taken. Lets debug that out also to see the real timing of the step.
Gimmy a couple of minutes to display that value also.
soon,
Mike
lets look at it,
Enjoy!
Mike
Can you easily record smallest and largest actual steps, (perhaps ignoring the first and last ones) ?
ie if you have a 16x clock, varying /N or /(N+1) in some modulated manner, will average N.SomeDecimal
In this case your 16x limits the modulation effects, and as I said above, maybe that is good enough for motors ?
A motor probably does not really need it's steps to be matched within 12ns.
B steps at: -504765876, -500918948(3846928), -495700292(5218656), -490465316(5234976)
A steps at: -504765862, -499618630(5147232), -494391526(5227104), -489156006(5235520)
Z steps at: -503497542, -498317190 ,-490465350, -483897958
Y steps at: -503497512, -497009064, -489156008, -481264136
I can already see where this goes - the serial output slows down my step-counter, once in a while.
OK.
To eliminate the effect of debug output, I need to choke my stepclock.
After startup I will set F to 10 Hz so hopefully the serial debug output does not affect the result.
lets see soon.
lets try to make usable numbers out of this.
Sadly I forgot G01 so we are running fast mode with just 4 instead of 16 steps in between the fastest one.
so the fastest axis runs with 4Hz not 1Hz.
C steps are: -1087022016, -1067022048 (19999968), -1047022096 (19999952), -1027022032 (20000064),
---- -1007022096 (19999936), -987022000 (20000096), -967022064 (19999936), -947022096 (19999968), -927022032 (20000064)
B steps are: -1087022080, -1067022112 (19999968), -1042022064 (25000048), -1022022096 (19999968),
---- - 997022032 (25000064), -977022096 (19999936), - 952022032 (25000064), -932022064 (19999968)
A steps are: -1087022066, -1062022034 (25000032), -1037022002 (25000032), -1012022098 (24999904),
---- -987022066 (25000032), - 962022034 (25000032), - 937022114 (24999920)
Z steps are: -1082022034, -1052022034 (30000000), -1022022002 (30000032), - 992022098 (29999904),
---- - 962022098 (30000000), - 932022082 (30000016)
Y steps are: -1082022036, -1047022068 (34999968), -1012022036 (35000032), - 977022068 (34999968),
---- - 942022116 (34999952)
X steps are: -1077022100, -1032022100 (45000000), - 987022068 (45000032), - 942022052 (45000016)
W steps are: -1067022054, -1007022086 (59999968) , -947022086 (60000000)
V steps are: -1052022086, - 962022054 (90000032)
U steps are: -1007022120
the bold numbers are CNT differences between steps of that axis.
At 4Hz the delay-time between two steps of the fastest axis (in this case "C")
axis C should delay 20,000,000 sys clocks
the actual result shows 19,999,936-20,000,096 a difference of 160 sys clocks between the values or 0.000002 Hz?
axis B should delay 22,500,000 sys clocks
the actual result shows 19,999,936-25,000,064 a difference of 5,000,128 (?) sys clocks between the values or 0.0625016 Hz?
axis A should delay 25,714,285 sys clocks
the actual result shows 24,999,904-25,000,032 a difference of 128 sys clocks between the values or 0.0000016 Hz?
axis Z should delay 30,000,000 sys clocks
the actual result shows 29,999,904-30,000,032 a difference of 128 sys clocks between the values or 0.0000016 Hz?
axis Y should delay 36,000,000 sys clocks
the actual result shows 34,999,952-35,000,032 a difference of 80 sys clocks between the values or 0.000001 Hz?
axis X should delay 45,000,000 sys clocks
the actual result shows 45,000,000-45,000,032 a difference of 32 sys clocks between the values or 0.0000004 Hz?
axis W should delay 60,000,000 sys clocks
the actual result shows 59,999,968-60,000,000 a difference of 32 sys clocks between the values or 0.0000004 Hz?
axis V should delay 90,000,000 sys clocks
the actual result shows 90000032 a difference of 32 sys clocks between the values or 0.0000004 Hz?
So basically it looks fine to me, except the B value, somehow off limit...
I will do another try with G01 to prove how much influence steps between steps have.
this numbers are for 4 internal steps between the step of the main axis
will now try 16 steps, my current standard.
may take some time.
Enjoy!
Mike
That means V,W,X,Z,C are all quite close, but B is +10%,-11% and may be the correct average ?
However, Y seems always too low (~2.857%), and A is always too low (~2.857%), as the expected is outside the bounds.
Interesting those errors are quite similar, but maybe Y & A can be improved to average to the expected value ?.
Z is the first axis of the 4th stepper Cog.
A the second one
B is the first axis of the 5th stepper Cog.
C the second one
I see no explanation why the code behaves different. So it has to be the data.
I am calculating my delay value by ((steps master-axis)*16)/(steps axis I need delay for)
so in case of A (9*16)/7 = 20
so in case of B (9*16)/8 = 18
so in case of C (9*16)/9 = 16
then I wait half of the delay before the step and half of the delay after the step
A has to fire at 10, 30, 50, 70
B has to fire at 9, 27, 45, 63
C has to fire at 8, 24, 40, 56
dooh.
And I am stepping with G0 so 4 internal steps. so my step counter goes
0
.
.
.
4
.
.
.
8 C should and does (8)
. B should (9)
. A should (10)
.
12 but B does here (12 +3 off) and A does here (12 +2 off)
.
.
.
16
.
.
.
20
.
.
.
24 C should and does (24-8=16) => effective delay C 16 OK
.
.
. B should (27)
28 but B does here (28 +1 off) => effective delay B 28-12=16 wrong should be 18
.
. A should (30)
.
32 but A does here (32 +2 off) => effective delay A 32-12=20 OK but 2 internal steps late
.
.
.
36
.
.
.
40 C should and does (40-24=16) => effective delay C 16 OK
.
.
.
44
.B should
.
.
48 but B does here (48 +3 off) => effective delay B 48-28=20 wrong should be 18
.
. A should (50)
.
52 but A does here (52 +2 off) => effective delay A 52-32=20 but 2 internal steps late
.
.
.
56 C should and does
And there we go!
B delays 16,20,16,20 not 18,18,18,18
So this proves that @jmg was on the right track
I think the secret is in the 'nicely between' - but with a 16x clock, that seems just too coarse to give the fine control needed ?
we have the proof now that for sure a 4x clock is to coarse to give the fine control needed!
That leaves the question of T Chap - What is causing the deviations?
My initial tests did show that multiple cogs waiting on the same long in hub, get their result about 2 sys-clocks apart. That's hub access.
The Pasm-Axis-Cog has a wait loop that gets called to wait between steps
This loop checks if the desired step counter is reached and checks for a abort situation, if my clock adress gets set to zero I abort all steps and restart the COG from its start loop.
two rdlongs + 5 ins is ruffly between (8..23) +8+20+call = 40..55 sys clocks
then there are more rdlongs while executing a step, so some deviation seems normal to me.
Now I need to check with 16 steps, maybe even 32
Enjoy!
Mike
axis B should delay 22,500,000 sys clocks
the actual result shows 19,999,936-25,000,064 a difference of 5,000,128 (?) sys clocks between the values or 0.0625016 Hz?
19,999,936 is 16 steps instead of 18
25,000,064 is 20 steps instead of 18
lets do the numbers:
19,999,936 * 18 / 16 = 22,499,928
25,000,064 * 18 / 20 =22,500,057
makes a difference of 129 sys clocks between the values! Hah!
Enjoy!
Mike
now pull out the useful numbers ...
running a 1 Hz per step of fastest axle "C"
C steps are: -762070239, -682070271 (79999968), -602070303 (79999968), -522070239 (80000064),
---- -442070303 (79999936), -362070239 (80000064), -282070271 (79999968), -202070303 (79999968), -122070239(80000064)
B steps are: -757070303, -667070303 (90000000), -577070303 (90000000), -487070303 (90000000),
---- - 397070271 (90000032), -307070271 (90000000), - 217070271 (90000000), -127070271 (90000000)
A steps are: -752070273, -652070241 (100000032), -552070305 (99999936), -452070305 (100000000),
---- -352070273 (100000032), - 252070241 (100000032), - 152070225 (100000016)
Z steps are: -742070273, -622070273 (120000000), -502070273 (120000000), - 382070241(120000032),
---- - 262070241 (120000000), - 142070225 (120000016)
Y steps are: -732070275, -592070307 (139999968), -452070275 (140000032), - 312070307 (139999968),
---- - 172070243 (140000064)
X steps are: -712070243, -532070243 (180000000), - 352070307 (179999936), - 172070307 (180000000)
W steps are: -682070245, -442070277 (239999968) , -202070277 (240000000)
V steps are: -622070277 , - 262070245 (360000032)
U steps are: -442070295
the bold numbers are CNT differences between steps of that axis.
At 1Hz the delay-time between two steps of the fastest axis (in this case "C")
axis C should delay 80,000,000 sys clocks - does 80,000,000 sys clocks
the actual result shows 79,999,936-80,000,064 a difference of 128 sys clocks between the values or 0.0000016 Hz?
axis B should delay 90,000,000 sys clocks - does 90,000,000 sys clocks
the actual result shows 90,000,000-90,000,032 a difference of 32 sys clocks between the values or 0.0000004 Hz?
axis A should delay 102,857,142 sys clocks - does 100,000,000 sys clocks ! rounding errors!
the actual result shows 99,999,936-100,000,032 a difference of 96 sys clocks between the values or 0.0000012 Hz?
axis Z should delay 120,000,000 sys clocks - does 120,000,000 sys clocks
the actual result shows 120,000,000-120,000,032 a difference of 32 sys clocks between the values or 0.0000004 Hz?
axis Y should delay 144,000,000 sys clocks - does 140,000,000 sys clocks ! rounding errors!
the actual result shows 139,999,968-140,000,064 a difference of 96 sys clocks between the values or 0.0000012 Hz?
axis X should delay 180,000,000 sys clocks - does 180,000,000 sys clocks, almost
the actual result shows 179,999,936-180,000,000 a difference of 64 sys clocks between the values or 0.0000002 Hz?
axis W should delay 240,000,000 sys clocks - does 240,000,000 sys clocks, almost
the actual result shows 239,999,968-240,000,000 a difference of 32 sys clocks between the values or 0.0000004 Hz?
axis V should delay 360,000,000 sys clocks - does 360,000,000 sys clocks, almost
the actual result shows 360,000,032 a difference of 32 sys clocks between the values or 0.0000004 Hz?
I also can see now why some axis are to slow, delays to short, my integer math is not precise enough for the delays....
next test with 32 steps in between ...
Enjoy!
Mike
That shows B does average to the correct value, it just has some quanta of jitter on it, here that is 4 units.
That's ok, there will always be some quanta jitter in any digital system.
Which leaves
A = (9*16)/7 = 20.571428..
A simple 20 is not quite right, some means to choose /20, or /21, or /20, /24 if there is 4 quanta is needed.
In this case, you need a 20 applied 3 times, and 21 applied 4
(20*3+21*4)/7 = 20.571428..
or, if your quanta choices are 20 & 24, 20 applied 6 times and 24 applied once.
(20*6+24*1)/(6+1) = 20.571428...
you where right in the first place, because my "steps between max axle steps" currently 16 does not scale much with integer math.
16 barely make 1.5 decimals behind the integer.
But her comes the problem.
free running I can reach now around 28,378 Hz, for the fastest axis steps on the 2-axis COG and 60,929 Hz on a 1-axis COG, using 16 steps in between max axis steps.
2 times the amount of steps will slow this down. But gives us 2x resolution so 32 instead of 16
Lets try
MIke
What's wrong with simply establishing the vector position/accel/velocity/decel and dishing out the appropriate, calculated commands to each axis?
I understand the need to have one axis follow another when master/slaving but if an axis can faithfully follow its command, what's the point?
If an axis can faithfully follow its command, then you get axis synchronization.
The detail here is to try and remove all averaging errors from differing Step rates on differing axes at the core level, so that they can faithfully follow its command.
I think that should be possible, as it is similar to a Baud rate problem - tho there you only need to get inside a couple of % to be 'good enough'.
Motors can probably tolerate some jitter, so there is likely to be some % of rate jitter that is 'good enough', but absolute step rates are less tolerant of creeping errors.
Even with quanta that comes from a given code approach, it should be possible to dither that quanta, to get a better average.
Some would call that fractional support.
and as of your quanta thing, isn't that exacly what the "B" axis did, running out of precisition?
it applied16,20,16,20 instead of 18.
Right?
Mike
I think what needs attention, are the ones that are not averaging to the right values.
I am basing my calculations on the 16 steps between the fastest steps.
Thus ending up at 20 on A = (9*16)/7 = 20.571428
Then I use half of it to wait before and the rest of it to wait after the step and my delay time is always to short.
I did some tests, but have not really found a solution. Using 32 instead of 16 doubles the precisition but halves the reachable speed and halves the available number range of my integer positions.
How fast need a usable stepper driver to drive steps?
T Chap gave a example with 20TPI ending at 8000 (half?)-steps per inch, for a ACME thread if I followed the math.
60,929 Hz on the 1-axis COG gives around 7.61 inch/second with 16 step math
28,378 Hz on the 2-axis COG gives around 3.54 inch/second with 16 step math
The 3-axis COG might do around 13,000 Hz (guessed) as 1.62 inch/second
Doubling the math to 32 step precisition will half the values again. Still usable?
I am for sure able to optimize the PASM a bit, once I figured out if the concept itself is doable, but that will maybe amount to 10% or so.
So does it make sense to follow this path?
Mike