#emc-devel | Logs for 2006-11-30

Back
[00:17:34] <cradek> SWPadnos: do you have a devel machine again?
[00:41:24] <SWPadnos> sort of
[00:41:58] <SWPadnos> my opteron can be used for sim, I still have the touchscreen, but I haven't updated it to Ubuntu. I also have ubuntu installs on my laptop, but it's not suited for RT (though it can be used for dev still)
[00:43:47] <cradek> not sure if sim is good enough for working on stepgen - you'd have to trick it into to building
[00:48:31] <jepler> you just have to rip out all the references to parport in configs/stepper/xxx_pinout.hal .. then it works fine
[00:48:52] <cradek> oh, I was thinking about it wrong
[00:50:17] <jepler> hm halscope is useless for reading out numbers less than .01 or so
[00:51:03] <cradek> I thought it had scales in the pico/nano per div
[00:51:41] <jepler> the ferror graph is sure interesting. http://emergent.unpy.net/index.cgi-files/sandbox/stepgen-with-ferror.png
[00:51:54] <jepler> cradek: yes it does but the readout at the bottom doesn't go to scientific notation
[00:52:08] <cradek> oh that, right, I noticed it too
[00:52:13] <cradek> you can still read off the divs though
[00:53:02] <jepler> true but I'm bad at that
[00:53:45] <cradek> it would be interesting to see ferror when you catch the reversing bug
[00:55:46] <jepler> the reverse at the start of that move is the only reversing bug I've seen so far
[00:56:17] <cradek> oh I see it, the purple is position
[00:56:46] <jepler> right
[00:56:49] <jepler> green is ferror
[00:56:58] <jepler> and the top are step and direction
[00:57:11] <cradek> I agree with jmk that this is probably unrelated to Ed's problem
[00:57:39] <cradek> oh I didn't see the top ones (800x600)
[00:57:54] <jepler> I should probably make smaller screenshots for you mere mortals
[00:58:09] <cradek> nah it's fine
[00:58:16] <cradek> very nice to have the detail
[00:58:55] <cradek> is this an arc?
[01:02:12] <jepler> no it's a line
[01:02:14] <jepler> g0x-.01
[01:02:19] <jepler> or maybe x-.005
[01:02:23] <jepler> it's a very short straight move
[01:03:18] <jepler> new traces at the bottom of the image: http://emergent.unpy.net/index.cgi-files/sandbox/stepgen-internals.png
[01:03:43] <jepler> blue is "accum"; green is "newaddval"; orange is "addval"
[01:04:02] <jepler> so newaddval is surprisingly negative
[01:05:11] <cradek> it's neat but it doesn't mean much to me without studying stepgen
[01:05:57] <jepler> the pulse generation is all about figuring out when to issue the next pulse
[01:06:16] <jepler> "addval" is added repeatedly to "accum" and when it overflows a step in the proper direction is issued
[01:06:25] <jepler> when "addval"'s absolute value is larger, steps are more frequent
[01:06:36] <cradek> ok
[01:06:54] <jepler> "newaddval" is the target acceleration, "addval" trends towards it over the course of each base_period
[01:07:19] <jepler> er, the target *velocity*
[01:07:44] <cradek> ok so that's where you get accel limiting
[01:08:37] <cradek> those are definitely big numbers
[01:11:46] <jepler> it's fixed-point math with 30 bits in the fractional part
[01:12:34] <cradek> and the integer part's range being sort of like +-1?
[01:13:15] <cradek> or there really is no integer part, it just overflows
[01:13:50] <jepler> right
[01:14:11] <jepler> there's the sign (direction) bit, the step bit, then 30 fraction bits
[01:14:33] <jepler> when a 1 gets in the step bit a step is issued, and the bit is stripped off before it's stored in "accum"
[01:15:51] <jepler> I am a bit surprised at the way the velocity is not monotonic
[01:16:09] <jepler> "slow down! no wait! speed up!"
[01:16:31] <cradek> the direction is coming from addval's sign, not accum
[01:17:27] <jepler> my understanding must not be quite right, the way you get a step when crossing 0 too
[01:18:43] <jepler> I guess that bit 31 of a signed number will change then too
[01:18:52] <jepler> er, bit 30
[01:18:56] <jepler> depending how you prefer to count bits
[01:28:44] <cradek> I don't see what causes dir to change long after it's done issuing steps
[01:28:50] <cradek> didn't we see that a lot?
[01:46:45] <jepler> not today
[01:46:49] <jepler> do you mean sometime in the past?
[01:48:22] <cradek> no I thought today
[01:48:33] <cradek> I just had a new? realization
[01:48:53] <cradek> I think on your plot it's the first pulse, not the second one, that is wrong
[01:48:59] <cradek> s/pulse/step/
[01:50:29] <cradek> no, I'm wrong, the positions are just one period behind
[01:51:19] <cradek> does this ever happen if you move in the + direction instead?
[01:51:32] <cradek> the thing that's unusual about the first move is the accum starts at 0
[02:58:39] <jepler> I wonder what happens if you start accum at any other value than 0
[02:59:18] <cradek> if you use step type 1, it works fine
[02:59:40] <cradek> I think it gets behind because of the dir_setup time, and the step_needed logic is screwy or something
[02:59:56] <cradek> I kind of get lost but I'm pretty sure it's step-dir specific
[03:05:37] <jepler> I bet it will be negative-move specific because dir seems to go back to 0 whenever it can
[03:05:48] <cradek> yes I think it is too
[03:05:51] <cradek> I even tested a bit
[03:06:08] <cradek> but I still don't see why dir does that
[03:07:59] <jepler> I am surprised to see that the value need_step goes to is 16777216
[03:08:33] <jepler> oh, it's an 'unsigned char', I guess I created the parameter wrong
[03:09:51] <jepler> nevermind
[03:12:10] <cradek> priming accum doesn't fix it
[03:12:54] <cradek> I'm not going to stare any more - I'm clueless and jmk will figure it right out
[03:13:02] <jepler> priming it to -1 does
[03:13:22] <cradek> oh, hmm
[03:14:19] <jepler> actually it makes the problem appear if the first move is towards +
[03:14:47] <cradek> does the dir bit still start low?
[03:15:06] <jepler> yes, but it goes high for a short time
[03:15:38] <jepler> http://emergent.unpy.net/index.cgi-files/sandbox/stepgen-internals-4.png
[03:16:37] <cradek> so it's not dir_hold that causes it, because you don't need one before the first step anymore
[03:18:53] <jepler> g0x[1/9000] makes it step once and then step back
[03:19:04] <cradek> that newaddvel is sure screwy on your plot
[03:19:05] <jepler> (with priming to -1; I assume -1/9000 would do it with vanilla)
[03:19:36] <cradek> what's addvel?
[03:19:42] <cradek> I mean in the 1/9000 case
[03:20:23] <jepler> huh look at this
[03:21:06] <jepler> I don't understand need_step
[03:21:20] <jepler> I figured it stayed high until the step could be issued
[03:21:25] <cradek> I don't either
[03:21:27] <cradek> it does, doesn't it?
[03:21:56] <jepler> http://emergent.unpy.net/index.cgi-files/sandbox/stepgen-internals-6.png
[03:22:13] <jepler> the bottommost is need_step
[03:22:21] <cradek> that |= is very strange...
[03:22:43] <jepler> oh maybe I porked mine up
[03:22:53] <jepler> I was looking at the |= too but I changed it
[03:23:11] <cradek> oh yeah I guess you dont want it to be =
[03:25:02] <jmkasunich> hi guys
[03:25:09] <cradek> hey
[03:25:31] <jepler> hi jmkasunich
[03:25:35] <jmkasunich> hi
[03:25:40] <jmkasunich> you've been busy
[03:25:47] <jepler> I've now lost track of what I've tweaked trying to figure things out
[03:25:49] <cradek> and we blame you, you know
[03:25:52] <jepler> I guess I should revert the file or at least diff...
[03:25:54] <jmkasunich> sorry
[03:25:55] <cradek> jepler: cvs diff!
[03:26:00] <cradek> jmkasunich: :-)
[03:26:15] <jmkasunich> I know ;-)
[03:26:22] <cradek> jmkasunich: good thing I've never written a bug, so I can say that
[03:26:33] <cradek> hi swp
[03:26:35] <SWPLinux> hi from LinuxLand :)
[03:26:45] <SWPLinux> (sadly next to WindowsLand)
[03:27:03] <jmkasunich> you were wondering abou the |= on need step?
[03:27:35] <cradek> I see it now, but can't you need several steps by the time your setup times run out?
[03:27:46] <jmkasunich> thats possible
[03:27:52] <jmkasunich> unlikely but possible
[03:27:57] <jmkasunich> thats why there is feedback
[03:28:29] <jmkasunich> if you lose a step because of one of the delays, the error will show up and be corrected
[03:28:48] <cradek> if you don't FE first
[03:29:18] <cradek> have I said lately I hate step/dir?
[03:29:34] <jmkasunich> well, unless you have a _really_ long setup time, and a _really_ radical accel, you are extremely unlikely to lose more than one
[03:29:38] <cradek> I'm not sure there's a dumber way to use two wires for two directions
[03:29:42] <jmkasunich> FE is probably several
[03:29:45] <jmkasunich> I agree
[03:29:50] <SWPLinux> some pathological setup time might cause more than 1 step error, but I suspect that in the general case, setup times will be less than 1 step
[03:30:04] <cradek> yes I bet you're right
[03:30:05] <jmkasunich> note the amount of code needed for steptype 0 compared to the others
[03:30:15] <cradek> you're not going very fast when you are changing directions
[03:30:18] <jepler> I get the "goes a step and comes back" behavior with quadrature
[03:30:18] <jmkasunich> that too
[03:30:27] <jepler> for 'g0x[-1/9000]'
[03:30:28] <cradek> jepler: oh!
[03:30:47] <cradek> cmd pos is right?
[03:30:49] <SWPLinux> that makes sense -lots of the direction code is shared
[03:30:55] <jmkasunich> jepler: I think you hit it on the head when you noted that the initial condition of the accumulator matters
[03:31:13] <jmkasunich> it generates a step whenever the accum over or underflows
[03:31:26] <jmkasunich> (overflow if addval is positive, underflow if negative)
[03:31:51] <jmkasunich> if you start at zero, then _any_ negative addval will result in an immediate step
[03:32:10] <SWPLinux> that shouldn't cause the next step to be positive though
[03:32:18] <jmkasunich> even if you really only want to have moved 1/1000th of a step
[03:32:35] <cradek> yeah, I'm with swp on this one
[03:32:36] <jmkasunich> so, on the next servo period, the error is 999/1000 of a step, and it corrects positive
[03:33:09] <jmkasunich> ideally it wouldn't step until commanded pos has reached 0.5 of a step
[03:33:31] <jmkasunich> and if the initial value was half of the rollover value, thats exactly what would happen
[03:33:36] <cradek> I don't understand "corrects positive"
[03:33:54] <SWPLinux> hmmm - to get rid of that type of error, I usually preload the accumulator with 1/2 the target value
[03:34:01] <SWPLinux> I'm not sure what that would be in this case though
[03:34:10] <jmkasunich> the same code at in update_freq that notices if you lose a step because of setup time, also notices if you take a step too early
[03:34:11] <cradek> but the accum can be wherever for the next move
[03:34:24] <SWPLinux> it sees that the new position (-1 step) is > 0.5 steps away from the target position, so it moevs back to 0
[03:35:00] <jmkasunich> cradek: that is true - you can have this problem anywhere - the 0 initial value just makes it a lot more likely on the very first move
[03:35:36] <jmkasunich> think of accum as position as the fractional part of a 64 bit fixed point position value
[03:35:45] <SWPLinux> do we need to keep track of the fractional step between direction changes?
[03:36:12] <jmkasunich> I think so
[03:36:25] <SWPLinux> I agree it's "better", but I'm wondering if it's necessary
[03:36:27] <jmkasunich> lemme finish my thought tho....
[03:37:26] <jmkasunich> if it wasn't for the stupid setup time, etc, possibly causing missed steps, I'd just have a 64 bit accumulator... addval would be added to the low half, and rawcounts would be the high half
[03:37:52] <jmkasunich> whenever the high half changes up or down, you generate a step
[03:38:16] <jmkasunich> its basically bresenham (sp?)
[03:38:38] <SWPLinux> (correct, except for capitalization ;) )
[03:39:41] <jepler> but this isn't specific to step+direction
[03:39:46] <jmkasunich> right
[03:40:03] <jmkasunich> I _could_ have used the method I just described for the other step types
[03:40:41] <SWPLinux> it's a fine method - the only difference is the max_freq and dir_{setup,hold} issues
[03:40:56] <SWPLinux> difference between type 0 and 2+
[03:41:18] <jmkasunich> but you do get into weirdness, when the accum has rolled over, but rawcounts hasn't been updated yet because of setup time or whatever
[03:41:50] <SWPLinux> I think the problem may be trying to do pesudo-feedback on a step generation algorithm
[03:42:14] <jmkasunich> instead of doing it completely open loop?
[03:42:39] <SWPLinux> yes
[03:43:04] <SWPLinux> I guess something like that is needed, but it sure complicates things :)
[03:43:28] <SWPLinux> as far as setup and hold are concerned, there can be a pause in the step pulse train during that time - jus tstop adding to the accumulator
[03:43:31] <jmkasunich> open loop can get complicated too - there is no rule that update-freq and make-pulses are an integer ratio, and fractional pulses can get lost or added
[03:44:04] <jmkasunich> if you stop adding to the accum, all subsequent pulses are delayed as well
[03:44:14] <jmkasunich> (whether that is better or worse might be open to debate)
[03:44:22] <SWPLinux> that doesn't matter, since this only happens at direction reversal (?)
[03:45:03] <SWPLinux> also, when does the "saved" step get output?
[03:45:17] <jmkasunich> I just noticed another bug, but its one that probably could never happen in a real usage
[03:45:20] <SWPLinux> you violate accel and/or vel limits if you issue the extra step too soon
[03:45:33] <jmkasunich> sorry, I was wrong - forget the 2nd bug
[03:46:32] <jepler> - addr->accum = 0;
[03:46:32] <jepler> + addr->accum = (1<<30)-1;
[03:46:54] <jmkasunich> that will eliminate the reversal at the start of the very first move
[03:46:55] <jepler> this "fixes" the first move problem -- both a move to + and a move to - are OK
[03:47:07] <cradek> can you do that at every dir change?
[03:47:12] <jmkasunich> the same kind of thing can still happen if you get just the right pattern
[03:47:20] <jmkasunich> cradek: I'd rather not
[03:47:20] <SWPLinux> no - that loses the fractional step info
[03:47:48] <SWPLinux> maybe the code that corrects position should have a higher threshold if the direction needs to change
[03:47:59] <SWPLinux> like a full step instead of 0/5 steps
[03:48:03] <SWPLinux> 0.5
[03:48:17] <jepler> I think this is a perfect time to use my excuse for the evening: "I have to go wash the dishes now"
[03:48:28] <SWPLinux> oooh - sounds fun
[03:48:33] <SWPLinux> maybe I'll do that too
[03:48:43] <jmkasunich> damn
[03:48:42] <cradek> sneaky waiting until right before 10
[03:48:46] <SWPLinux> heh
[03:48:59] <SWPLinux> it's just before 11, I'll have you know
[03:49:31] <SWPLinux> just kidding about leaving. but maybe I should nuke some soup or something
[03:50:02] <cradek> http://timeguy.com/cradek-files/emc/g76pass.png
[03:50:15] <cradek> on a happier note, look at my lathe track the spindle
[03:50:34] <cradek> the belt has teeth on the inside - I think you could count them
[03:51:17] <SWPLinux> is the weirdness on the right side an image artifact or was that actually on halscope?
[03:51:19] <jmkasunich> cradek: is that image messed up, or is it my browser?
[03:51:23] <SWPLinux> heh
[03:51:25] <cradek> it's the image
[03:51:36] <cradek> probably part of it was obscured when I grabbed it
[03:52:11] <SWPLinux> hmmm - how do you grab a single window? (I always use the full screen capture and edit)
[03:52:18] <jmkasunich> gimp does it quite nicely
[03:52:32] <jmkasunich> File->Acquire IIRC
[03:52:39] <SWPLinux> cool
[03:52:50] <jmkasunich> it has options to acquire from a scanner, etc, and one option is screengrab
[03:52:52] <cradek> bind a key to "take a screenshot of a window" in gnome
[03:52:58] <cradek> keyboard shortcuts
[03:53:04] <SWPLinux> ok
[03:53:08] <cradek> it's very quick and it writes png just like you want
[03:53:12] <SWPLinux> thanks for both
[03:53:16] <jmkasunich> pops a dialog, you can select hole screen or window, tell it to wait a few seconds before snapping so you can uncover the window, then click in it
[03:53:38] <cradek> I put the mouse in the window and hit alt-printscreen
[03:53:38] <jmkasunich> whole screen even
[03:53:49] <SWPLinux> ok - alt-printscreen, like I'm used to
[03:54:22] <cradek> wow look at the accel on this thing
[03:54:54] <cradek> sorry I didn't mean to destroy the stepgen talk
[03:54:55] <jmkasunich> you mean the nearly vertical lines
[03:55:17] <cradek> yes
[03:55:41] <jmkasunich> 500mS per div - hard to say how fast that really is
[03:55:47] <jmkasunich> zoom in and tell us
[03:55:55] <cradek> I know it's 1000mm/s2
[03:56:39] <jmkasunich> back when I was playing with the engineering week servodrive, I was doing a 180 degree move of the motor shaft (from standstill to standstill) in about 40mS
[03:57:06] <cradek> pid works, doesn't it
[03:57:12] <jmkasunich> yep
[03:57:20] <cradek> this actually does reverse the motor to stop now
[03:57:23] <jmkasunich> PID and lots of current
[03:57:46] <jmkasunich> you mean the PWM goes the other way?
[03:57:52] <cradek> yes
[03:58:00] <cradek> just a bit
[03:58:01] <jmkasunich> not too surprised
[03:58:34] <jmkasunich> does it go negative during the entire accel, or only at the end?
[03:58:32] <skunkworks> still can't believe your getting that kind of following with 5 levels
[03:58:42] <cradek> let me plot one
[04:01:30] <jmkasunich> skunkworks: there are more than five levels I bet
[04:02:00] <jmkasunich> (depends on base period, servo period, and how pwmgen is configured)
[04:02:16] <cradek> 8kHz pwm frequency, no dither, 25usec period
[04:02:25] <cradek> I think that makes it +-5 levels
[04:02:29] <jmkasunich> wow
[04:02:32] <skunkworks> :)
[04:02:50] <SWPLinux> is the output 1 bit or 2?
[04:02:52] <jmkasunich> you still have dithering, it just happens every millisecond instead
[04:03:05] <jmkasunich> SWPLinux: 2
[04:03:08] <jmkasunich> up and down
[04:03:13] <cradek> SWPLinux: up/down
[04:03:14] <SWPLinux> ok, so FWD/REV outputs
[04:03:47] <jmkasunich> so 11 levels total (5 negative, zero, and 5 positive
[04:04:39] <skunkworks> unreal
[04:05:03] <cradek> http://timeguy.com/cradek-files/emc/fe-pidout.png
[04:05:17] <cradek> fe on top, pid output on the bottom
[04:05:43] <jmkasunich> so the PID is railed during accel
[04:05:55] <cradek> yeah I must have it too high
[04:05:57] <jmkasunich> then during steady state its dithering around
[04:06:00] <cradek> didn't think it was doing that the other day
[04:06:35] <cradek> FE is .01mm/div pid is 1/div of course
[04:06:43] <jmkasunich> well, as long as its not falling behind thats ok, but any additional load, or acceling to a higher speed, and you might start building up error
[04:06:57] <cradek> yeah I'll slow it down
[04:07:06] <jmkasunich> what is your scaling (how many mm per count)
[04:07:19] <cradek> 1/375
[04:07:36] <jmkasunich> so 3.75 counts per division
[04:07:49] <jmkasunich> the steps in the ferror trace are individual counts
[04:08:00] <cradek> cool
[04:08:30] <jmkasunich> and its hunting back and forth around the ideal value, about twice per div, thats 40Hz
[04:08:57] <cradek> but only by .005 mm at top speed
[04:09:01] <jmkasunich> its basically only hunting +/- 1 count
[04:09:30] <skunkworks> I really can't believe how well this _simple_ setup seems to work.
[04:09:51] <jmkasunich> cradek: have you observed it when load changes?
[04:09:52] <cradek> I'd agree it's simple if not for the quadrature divider...
[04:10:08] <cradek> jmkasunich: if I shove the axis while it's going, it doesn't really change the FE
[04:10:09] <jmkasunich> either add some weight to the carriage, or capture it actually starting a cut
[04:10:34] <jmkasunich> thats good
[04:10:41] <skunkworks> jmkasunich: btw I found a 3 phase transformer for a supply. :)
[04:10:54] <jmkasunich> but a shove from your hand probably has very little energy content at or above 40Hz
[04:11:10] <cradek> I actually don't think I can stall it by pushing the axis
[04:11:13] <jmkasunich> skunkworks: nice. got 3-phase power to plug it into?
[04:11:15] <cradek> don't want to try too much
[04:11:36] <skunkworks> jmkasunich: yes the shop is 3 phase
[04:11:42] <jmkasunich> even nicer
[04:12:02] <jmkasunich> ok, back to stepgen!
[04:12:34] <skunkworks> on that note - how does the emc1 stepgen work (the better one) don't remember the name of it.
[04:12:50] <jmkasunich> I could never make sense of the code
[04:13:01] <skunkworks> :)
[04:13:45] <jmkasunich> I'm also strongly biased in favor of the DDS method as used in freqgen/stepgen, so I wasn't too motivated to figure it out
[04:14:16] <skunkworks> ok bed time - you guys don't work so hard.
[04:15:13] <jmkasunich> SWPLinux: I keep thinking about what you said about quasi-feedback
[04:15:38] <jmkasunich> I gotta admit that http://emergent.unpy.net/index.cgi-files/sandbox/stepgen-internals-4.png has issues
[04:18:15] <SWPadnos> I suspect that the better solution is to just increase the error required to reverse direction
[04:18:37] <jmkasunich> that may be, but it offends me
[04:18:58] <jmkasunich> the whole point of doing this fractional step accumulator is to make the system linear
[04:19:21] <jmkasunich> putting a discontinuity in it at the zero crossing seems wrong
[04:19:34] <SWPLinux> sure, but there are already discontinuities introduced at a direction change
[04:19:44] <SWPLinux> like dir_setup and hold
[04:20:07] <jmkasunich> not for the other 13 stepping types
[04:20:32] <jmkasunich> I'd like to keep the step type 0 ugliness out of the higher level (servo thread) code
[04:20:40] <SWPLinux> there's still a hold time, isn't there?
[04:20:49] <SWPLinux> ie, step duration?
[04:21:08] <SWPLinux> (or state duration for the others)
[04:21:11] <cradek> for type 1 (up/down) probably
[04:21:30] <jmkasunich> not really
[04:21:43] <SWPLinux> hmmm - there probably should be (I think)
[04:21:45] <jmkasunich> the only limit is that you have to stay in a state for 1 period (for 2+)
[04:22:06] <SWPLinux> sure, and the max_vel will limit the state change rate
[04:22:07] <cradek> SWPLinux: that's easy to adjust with your base period...?
[04:22:17] <SWPLinux> that's not ideal though
[04:22:25] <jmkasunich> for 1, to ensure pulses and not just a steady high level, the max freq is limited to 1/2 of the base period
[04:22:34] <jmkasunich> for 2 and up, the max freq is limited to the base period
[04:22:54] <SWPLinux> consider that a primary reason for using hardware step generation is that the frequency changes and step spacing is "smoother"
[04:23:28] <SWPLinux> that's because there's a much faster timebase, and the usable step frequencies are some large number of base clock ticks (like 10-100 or more)
[04:23:39] <jmkasunich> exactly
[04:23:55] <SWPLinux> so having a fast BASE_PERIOD and a separate limit on the step rate is very useful
[04:24:07] <jmkasunich> IMO, the best hardware step generator is an implementation of stepgen where the accumulator is clocked at 50MHz instead of 50KHz
[04:24:20] <SWPLinux> like jepler's thiingie :)
[04:24:24] <jmkasunich> SWPLinux: stepgen _does_ allow you to set a lower limit
[04:24:43] <jmkasunich> it just won't let you set a higher one (one that could result in skipped states)
[04:24:54] <SWPLinux> that's the step duration and spacing parameters
[04:24:58] <jmkasunich> no
[04:25:03] <jmkasunich> max vel
[04:25:26] <SWPLinux> sure
[04:25:35] <jmkasunich> for the moment lets assume that scale is 1.0, so we can consider velocity and frequency as the same
[04:26:08] <jmkasunich> if the base period is 20uS (50KHz), the absolute max freq for type 2+ is 50KHz
[04:26:21] <jmkasunich> if you set max_vel to 60KHz, stepgen will reset it to 50
[04:26:22] <SWPLinux> actually, the max_freq is calculated as 1/period for all types 2+, there is no hold time
[04:26:33] <jmkasunich> if you set it to 20, stepgen will leave it alone
[04:26:48] <SWPLinux> ok
[04:27:30] <cradek> so is there a fix for our glitch?
[04:27:40] <jmkasunich> yes and no
[04:27:56] <SWPLinux> probably - I hink we're trying to figure out how and where to apply one
[04:27:59] <jmkasunich> we can make it very much less frequent by setting the initial value to half the rollover point
[04:28:01] <SWPLinux> then there's the actual fix :)
[04:28:18] <SWPLinux> I think there needs to be "de-glitching" for all step types
[04:28:31] <cradek> will it really be less frequent or will we just hide it by not having it on the first move?
[04:28:58] <cradek> seems to me like it will be equally frequent still, but unreproducable
[04:29:11] <jmkasunich> but you can potentially get a "glitch" whenever you reverse direction, if you stop and reverse with the accumulator just a tiny tiny bit past the point at which it generates a step
[04:29:37] <SWPLinux> I think it's a mask, not a fix
[04:29:50] <jmkasunich> cradek: today, we get it on 50% of the first moves (based on direction) and some very small percent of subsequent reversals
[04:30:09] <jmkasunich> if we eliminate that initial glitch, and don't tough the others, we have reduced the problem
[04:30:17] <jmkasunich> I agree its a mask
[04:30:43] <SWPLinux> are you pretty sure that the multi-millisecond glitches are actually a single step glitch?
[04:30:55] <jmkasunich> huh?
[04:31:18] <SWPLinux> the direction glitches were more than a millisecond in the scope images I saw
[04:31:26] <jmkasunich> oh that
[04:31:32] <SWPLinux> not a few BASE_PERIODS, but a few SERVO_PERIODs
[04:31:33] <cradek> I was also seeing a bogus dir change with no step in it - is that explained by this find?
[04:31:46] <SWPLinux> possibly
[04:31:49] <jmkasunich> to be honest, I didn't care about the direction changes, unless a step was generated in the wrong direction
[04:32:02] <SWPLinux> ok - that's fair
[04:32:32] <cradek> ok so that's known, just checking
[04:32:38] <jmkasunich> the dir bit is controlled by the sign of addval, and its possible to have addval go positive, negative, positive many times without ever moving a whole step
[04:33:06] <jmkasunich> should we make dir change state each time addval changes sign? dunno
[04:33:26] <jmkasunich> by doing so, we reduce the chance of wanting a step and having to wait because setup time hasn't been satisified
[04:33:59] <jmkasunich> this way, as soon as there is even a tiny positive addval, we set dir positive, so when the accum eventually overflows we're ready to send the step without waiting for setup time
[04:34:16] <cradek> that sounds wise
[04:34:28] <jmkasunich> we could wait until we actually need to send a step, that would eliminate the "stepless dir changes"
[04:35:59] <jmkasunich> this is another case where if I was working with the benefit of hindsight, I would have done the update-freq part of stepgen completely differently
[04:36:06] <SWPLinux> the main difference between the Bresenham algorithm and this one is that Bresenham has additional information that remains in the accumulator after a "step" is taken
[04:36:14] <jmkasunich> this one does too
[04:36:38] <SWPLinux> you still have the fraction, but you lose the integer part
[04:36:45] <jmkasunich> I don't lose it
[04:36:48] <SWPLinux> that appears to be significant when the direction changes
[04:37:01] <jmkasunich> when the accume rolls over, the resulting step increments (or decrements) rawcounts
[04:37:04] <SWPLinux> sure - you generate a step, and keep it in rawcounts
[04:37:09] <cradek> the integer part is a step
[04:37:08] <jmkasunich> ;-)
[04:37:35] <jmkasunich> I think if I was doing it again, I'd be seriously tempted to implement a 64 bit accum
[04:37:53] <SWPLinux> I don't think there's a need - it jus makes the numbers bigger :)
[04:38:01] <jmkasunich> not really
[04:38:15] <jmkasunich> it would just be a concatenation of rawcounts and accum into one number
[04:38:31] <jmkasunich> whenever the high part (rawcounts) changes, I output a step
[04:38:51] <SWPLinux> ok - that I can agree with :)
[04:39:08] <jmkasunich> gotta deal with the setup ugliness is all
[04:39:51] <SWPLinux> well, there should be some hysteresis around 0, I think - even though it's non-linear
[04:40:48] <jmkasunich> you're a genius
[04:40:52] <jmkasunich> ;-)
[04:40:54] <SWPLinux> heh
[04:41:08] <SWPLinux> thank you thank you. no autographs, please :)
[04:41:15] <jmkasunich> I've always been bothered by a thing that can happen with this method
[04:41:30] <SWPLinux> steps in the wrong direction? ;)
[04:41:37] <jmkasunich> an example is the best way to splain it, lets assume for sanity sake that the accum is only 8 bits
[04:42:32] <jmkasunich> if the threshold for generating a step is 0/FF, and the velocity is reversing, you might have addval start at +4, then become -4, and the result could be:
[04:43:04] <jmkasunich> F2, F6, FA, FD, 02, 06, 02, FD, FA, F6, etc
[04:43:20] <jmkasunich> note a pair of steps separated by only 3 clocks
[04:43:33] <SWPLinux> off by 1, but OK :)
[04:43:52] <jmkasunich> no, first step while counting from FD to 02
[04:44:03] <SWPLinux> FD to 01 :)
[04:44:07] <SWPLinux> FD FE FF 00 01
[04:44:23] <jmkasunich> actually, FD was wrong
[04:44:23] <cradek> and a+4 != d
[04:44:32] <jmkasunich> FA FE 02
[04:44:33] <SWPLinux> heh
[04:44:42] <jmkasunich> I was testing you ;-)
[04:44:46] <SWPLinux> of course
[04:44:47] <jmkasunich> (not)
[04:44:54] <jmkasunich> anyway, we digress
[04:44:57] <cradek> ok ... the accumulator is 3 bits
[04:44:58] <cradek> :-)
[04:45:15] <jmkasunich> the desired frequency is one step every 4/256 clocks
[04:45:32] <jmkasunich> I mean every 256/4 clocks
[04:45:33] <SWPLinux> or 256/4
[04:45:39] <SWPLinux> :)
[04:45:50] <jmkasunich> but we get one fwd and one rev separated by only 3 (or 4) clocks
[04:45:52] <SWPLinux> we regress
[04:46:22] <jmkasunich> so, I thought "use 7F->80 for forward steps, and 00->FF for reverse ones"
[04:46:28] <jmkasunich> but that can accumulate errors
[04:46:43] <jmkasunich> suppose you go fwd, reverse for less than one step, then fwd again
[04:47:13] <cradek> you have to step at the same place in the cycle, like my quadrature problem
[04:47:18] <jmkasunich> F2 F6 FA FE (step) 02 06 02 FE FA FE (step) 02
[04:47:20] <jmkasunich> right
[04:47:36] <SWPLinux> I wonder if it would work if the accumulator always counts up (and steps on 0xFF->0x00), but you negate the accumulator whenever you change direction
[04:47:38] <jmkasunich> I was trying to introduce hystersis with my split thresholds
[04:47:52] <jmkasunich> but I didn't think of it as hystersis, and thats why it wouldn't work
[04:47:57] <SWPLinux> of course, I don't know that that would help wother
[04:48:11] <SWPLinux> either
[04:48:17] <jmkasunich> hystersis doesn't work by having two thresholds, it has one, that changes based on the output state
[04:48:58] <SWPLinux> look at it as noise margin then - that's probably closer anyway
[04:49:15] <jmkasunich> ok, my brain just froze up
[04:49:21] <SWPLinux> heh
[04:49:31] <SWPLinux> so close to midnight - how convenient ;)
[04:49:39] <jmkasunich> I thought I was visulizing how the hystersis thing could work, but then I lost it
[04:50:14] <jmkasunich> the idea is if you have F2 F6 FA FE 02 06 02 FE FA FE 02 06
[04:51:09] <SWPLinux> that sequence just toggles every 3 cycles, not 4
[04:51:28] <jmkasunich> you want to make a fwd step the first time you cross from FE to 02, you _don't want to make a down step when you cross down from 02 to FE, you don't want a down step unless you get all the way down to 7F, but in the example above, when you go back up above 00 the second time, you need to ignore it
[04:52:12] <SWPLinux> so maybe bit 30 (ciounting from 0) needs to be the step bit
[04:52:13] <jmkasunich> if the addval remained at +4, it would toggle every _64_ , not 4
[04:52:32] <SWPLinux> that's correct - you use 64 to toggle every 4th cycle
[04:52:56] <jmkasunich> so going from "up once every 64" to "alternating every 3" is a bad thing
[04:53:00] <SWPLinux> but you still lose 1/256 of the steps due to accumulator size
[04:53:12] <SWPLinux> why would it alternate though?
[04:53:26] <SWPLinux> what would cause the addval to toggle like that?
[04:53:38] <jmkasunich> a perverse g-code program?
[04:53:42] <SWPLinux> oh :)
[04:53:59] <SWPLinux> there are a couple of things going on here
[04:54:23] <jmkasunich> if you issue a string of moves in opposite directions that are each less than one step, the result should be no movement
[04:54:42] <jmkasunich> bouncing back and forth is technically correct, but ugly
[04:54:42] <SWPLinux> 1) the step generator must comply with setup and hold times. this introduces a non-linearity at direction changes
[04:54:50] <jmkasunich> accumulating error is evil
[04:55:34] <SWPLinux> that depends - the problem is that keeping track of the step fraction causes the step threshold to change
[04:55:43] <jmkasunich> yes, but in many cases the non-linearity can be (is) hidden
[04:56:11] <SWPLinux> if the accumulator happens to be at 1, then any negative move >1 (absolute value) will cause a step
[04:56:23] <jmkasunich> using the 8 bit example, suppose you pass 0 heading up, but you don't reverse until you hit say 0x60
[04:56:41] <SWPLinux> in the general case, if |acc| is < |addval| then a step will be issued immediately
[04:56:50] <jmkasunich> the dir bit will change state when you reverse, and you have a fairly long time before it gets back down again and passed thru zero to demand a step
[04:57:03] <SWPLinux> yes
[04:57:37] <jmkasunich> so there is no nonlinearity in that case
[04:57:58] <SWPLinux> true
[04:58:18] <jmkasunich> if you were plotting "position" as a 64 bit variable (integer plus fraction) you'd see it rising, turn around, and falling perfectly linearly
[04:58:41] <jmkasunich> and the integer part (the steps) would be a perfect quantization of that perfect high resolution falue
[04:58:40] <jmkasunich> value
[04:58:55] <SWPLinux> yes, but the constraint around 0 is that there be some minimum time between zero crossings
[04:59:02] <jmkasunich> right
[04:59:14] <SWPLinux> and that blows linearity out of the water
[04:59:26] <jmkasunich> if the perfect linear value just barely breaks zero before turning around, you get two steps that are too close togehter
[04:59:28] <jmkasunich> together
[04:59:58] <SWPLinux> well, there is a possibility that may work, but could be "icky"
[05:00:38] <SWPLinux> the minimum reversal time is known (some combination of dirhold and setup ...)
[05:01:32] <SWPLinux> when the direction is changed, insure that the accumulator will need at least that much added to it before a driection change can occur
[05:02:00] <SWPLinux> so use a temp_acc, which is max(acc, acc+reversal_time)
[05:02:09] <SWPLinux> or min, depending on direction
[05:02:52] <jmkasunich> maybe simpler than that
[05:02:52] <SWPLinux> I'm not sure exactly when to stop using the temp and go back to the official accumulator (which still has the correct fraction)
[05:03:28] <jmkasunich> if ( just changed from up to down) && ( acc < mindelay ) acc += mindelay;
[05:04:01] <SWPLinux> yes, but that changes the actual step fraction (which is position)
[05:04:14] <jmkasunich> if (just changed from down to up) && ( acc > 0-mindelay ) acc -= mindelay
[05:04:18] <SWPLinux> also, if you overflow with that calc, there's a problem
[05:04:56] <jmkasunich> the second issue can be prevented, as long as mindelay is less than half the accumulator rollover value
[05:05:19] <SWPLinux> what if the acc is at MAXINT-3?
[05:05:42] <jmkasunich> which direction change, up to down, or down to up?
[05:06:20] <SWPLinux> either - it's just MAXINT-(small n) or MININT+(small n)
[05:06:34] <jmkasunich> no
[05:06:50] <SWPLinux> the addition/subtraction has to be saturated to the max value the accumulator can usefully hold
[05:07:06] <jmkasunich> if you were going up, and are now going down, and you reversed at MAXINT-3, you have a huge time until you will generate the first "down" step
[05:07:45] <SWPLinux> my point was that there is a zone for either direction where you may overflow/underflow the accumulator if you add/subtract some constant
[05:07:55] <jmkasunich> if you were going down, and just underflowed (generating a down step), and then you reverse at MAXINT-3, you are gonna overflow and generate an up pulse pretty darned quick, and need to adjust
[05:08:02] <jmkasunich> right
[05:08:52] <jmkasunich> but I had two terms in my if, and the second one handles that, as long as mindelay is less than half of MAXINT
[05:09:19] <SWPLinux> truew
[05:09:24] <SWPLinux> -w
[05:09:38] <jmkasunich> actually, this is all details
[05:09:44] <SWPLinux> yes
[05:09:47] <jmkasunich> there are really only two approaches
[05:10:24] <jmkasunich> 1) defer the step, while keeping the accumulator accurate
[05:10:50] <jmkasunich> 2) delay the accumulator itself, and rely on an outer feedback loop to get back on track
[05:11:20] <jmkasunich> today I'm using 2
[05:11:37] <SWPLinux> I think I have a possibility for option 1
[05:11:47] <jmkasunich> and I'm also using a very complex outer loop to try to avoid breaking velocity or accel contstraints regardless of the inptu signal
[05:12:12] <SWPLinux> that's still needed, unless you want to go to PID (or quickstep)
[05:12:50] <jmkasunich> actually, I could do something like limit3 upstream, to deal with the limits, and then use a much simpler "loop closer" afterwards
[05:13:02] <SWPLinux> the idea for an option 1 solution is to introduce a new variable, which gets reset on direction cahnge
[05:13:16] <SWPLinux> possibly to different values depending on the direction
[05:13:56] <SWPLinux> this becomes the "added mindelay" in the accumulator, it's just kept track of separately
[05:14:12] <jmkasunich> not sure I follow
[05:14:17] <SWPLinux> if this var is nonzero, then you add/subtract addval to both this and the accumulator
[05:14:23] <jmkasunich> also just realized that mindelay is not a constant
[05:14:51] <SWPLinux> it is, if setu[/hold times don't change
[05:14:55] <SWPLinux> setup
[05:15:01] <jmkasunich> nope
[05:15:26] <jmkasunich> as addval changes, mindelay (if thinking of it as a value accumulator units) changes
[05:15:42] <SWPLinux> ok - sure
[05:15:44] <jmkasunich> if you want to delay 5 periods, and addval is 20, then mindelay is 100
[05:15:53] <jmkasunich> if addval is 3, mindelay is 15
[05:16:21] <SWPLinux> sure
[05:16:40] <SWPLinux> ok - lemme do some pseudocode for my idea - see if this makes sense:
[05:17:30] <SWPLinux> int step_acc=0x3FFF (assuming positive direction for now)
[05:17:56] <SWPLinux> oops - if (dir_change) step_acc=0x3FFF (1/2 step)
[05:19:14] <SWPLinux> if (!step_acc) {do what's done now with accum, and generate steps normally}
[05:20:17] <SWPLinux> argh -damned editor keeps losing my line
[05:20:22] <SWPLinux> one sec - let me put this on pastebin
[05:20:34] <jmkasunich> ok
[05:23:51] <SWPLinux> hmm - actually, this algorithm doesn't help with hold time issues - it just adds some hysteresis (requiring 1/2 step of accumulation before allowing a step to be issued)
[05:24:27] <jmkasunich> properly functioning hystersis might be all we need
[05:25:11] <SWPLinux> it boils down to something like the algorithm we were discussing, but keeps the hysteresis value in a separate variable
[05:25:22] <jmkasunich> usually speed near a direction reversal is quite slow, so half a step can be many periods - more than the setup time
[05:26:50] <SWPLinux> true enough
[05:27:09] <jmkasunich> my head hurts
[05:27:25] <jmkasunich> to be honest, we're attacking a non-problem
[05:27:56] <jmkasunich> we have _not_ identified any circumstances under which the existing code will violate setup or hold times
[05:28:16] <SWPLinux> true
[05:28:17] <jmkasunich> changes of direction with no step are _not_ a violation)
[05:28:56] <jmkasunich> we have _not_ identifed any situation in which the position will be more than one step away from the ideal position even when apparently "illegal" steps are issued
[05:29:04] <SWPLinux> http://pastebin.ca/262144
[05:29:11] <SWPLinux> simple pseudocode there
[05:29:45] <SWPLinux> heh - maybe C highlighting wasn't the best idea :)
[05:31:15] <SWPLinux> so this keeps track of the fractional position in accum as normal, but also tracks a 1/2 step fudge factor at reversals, and can only issue steps when outside that fudge area
[05:31:19] <jmkasunich> I think an implementation of hystersis can be done a little cleanr than that
[05:31:25] <SWPLinux> probably :)
[05:31:49] <SWPLinux> this has the advantage of not modifying the accum though, which eliminates some tracking issues
[05:31:50] <jmkasunich> what really matters is the direction of the last step issued
[05:31:55] <SWPLinux> true
[05:32:23] <jmkasunich> so - we remember "last_step_dir"
[05:33:40] <jmkasunich> when it changes from up to down we add some value to the accum, when it changes from down to up we subtract the same value
[05:34:01] <jmkasunich> net change is guaranteed to be zero, you can't change from up to down more times than you changed from down to up
[05:34:10] <SWPLinux> but that doesn't solve the glitch problem
[05:34:27] <SWPLinux> err - it may not solve the glitch problem at least
[05:34:32] <jmkasunich> you are right
[05:34:35] <SWPLinux> it shifts it
[05:34:57] <jmkasunich> we need different thresholds for up and down to solve it, but they need to be done in a way that prevents accumulation of error
[05:35:06] <jmkasunich> "last step dir" is still the key variable though
[05:35:42] <SWPLinux> that's where I came up with the idea for a separate cariable that tracks alongside the normal accumulator
[05:35:46] <SWPLinux> variable
[05:36:48] <jmkasunich> I can't see how that code works
[05:37:11] <jmkasunich> line 2 - that half step can be positive or negative, depending on the direction, right?
[05:37:30] <SWPLinux> it's basically the same as adding/subtracting from the accum, but it uses a separate variable to do it
[05:37:34] <SWPLinux> yes
[05:37:36] <jmkasunich> if so, then line 6 needs to use either absolute values (maybe) or two conditions, one for each sign
[05:37:45] <SWPLinux> yes - like I said, it's pseudocode ;)
[05:38:27] <SWPLinux> that's one reason why I like the idea of inverting the accumulator if needed, and always using addition in the algorithm
[05:38:41] <jmkasunich> eww
[05:38:42] <SWPLinux> he
[05:38:44] <SWPLinux> heh
[05:38:49] <jmkasunich> I think of the accum as position
[05:38:58] <jmkasunich> inverting it just seems wrong
[05:38:58] <SWPLinux> sure
[05:39:25] <SWPLinux> but it does make limit checking easier
[05:41:36] <SWPLinux> actually, the step_acc can always be a positive number - it just has to represent some fraction of a step
[05:42:09] <jmkasunich> that gets really messy on direction changes
[05:42:30] <SWPLinux> and it may make sense to only set it if accum is below some threshold - like the code you posted here
[05:42:57] <jmkasunich> say addval is positive 1/30th of a step, and accum is positive 3/4 of a step
[05:43:16] <jmkasunich> now the command reverses, and addval becomes -1/50th of a step
[05:43:30] <jmkasunich> how do you handle that in the always positive mode?
[05:43:50] <jmkasunich> accum needs to become 1-old_accum, and addval becomes abs(addval)
[05:44:13] <SWPLinux> 1-old_accum? why not just -old_accum ?
[05:44:32] <jmkasunich> because you were at 3/4 of a positive step when you reversed
[05:44:42] <SWPLinux> ah - you're in fractionspeak ;)
[05:44:50] <jmkasunich> if you leave it at 3/4 and add abs(addval), you'll generate a negative step after only 1/4
[05:44:53] <SWPLinux> so 1/4 in this case
[05:45:06] <jmkasunich> instead of having to back out the whole 3/4 which is the correct result
[05:45:23] <SWPLinux> I didn't say that accum should always be positiove - I said that step_acc (the extra accumulator) can always be used in a positive mode
[05:45:32] <jmkasunich> oh
[05:46:00] <jmkasunich> I think I figured out another approach....
[05:46:12] <SWPLinux> ok - I'm not sure I like mine :)
[05:46:26] <jmkasunich> this one is best visualised graphically (which actually is a good way to show the problem too)
[05:46:37] <jmkasunich> gotta pencil? ;-)
[05:46:49] <SWPLinux> sure - want me to draw something? ;)
[05:46:56] <jmkasunich> draw some solid horizontal lines maybe an inch apart
[05:47:06] <jmkasunich> those are accumulator rollover points
[05:47:21] <jmkasunich> draw a line coming in from the left and angling up - that is the accumilator
[05:47:45] <jmkasunich> just after it crosses a horizontal line, arc it over to angle down
[05:47:57] <jmkasunich> it passes the rollover point again - too soon
[05:48:10] <jmkasunich> thats the problem
[05:48:23] <jmkasunich> now draw dashed horizontal lines half way between the solid ones
[05:48:48] <jmkasunich> that was my original hystersis idea - use the dashed lines for down steps and the solid ones for up steps
[05:48:55] <jmkasunich> am I making sense?
[05:49:00] <SWPLinux> mostly
[05:49:45] <jmkasunich> if the line comes in from the left and up, arcs over just above a solid line, and angles down after that, there is a half step delay before it crosses a dotted line and makes a down step
[05:49:53] <jmkasunich> which seems good
[05:50:42] <jmkasunich> but if the line comes in from the left and up, arcs over just above a solid, then arcs back up again as soon as it goes below the solid, it winds up crossing the solid going up twice - that would generate two up steps - bad
[05:50:43] <SWPLinux> sure, but if it ping-pongs across the up (or down) threshold, you end up with several steps in the same direction, not necessarily meeting the timing constraints
[05:50:51] <jmkasunich> exactly
[05:51:11] <SWPLinux> ah - you said that :)
[05:51:23] <jmkasunich> if you use only the solid lines and it ping pongs, you may violate timing but at least they don't accumulate
[05:51:29] <jmkasunich> up down up down, etc
[05:51:36] <jmkasunich> now the idea
[05:51:58] <jmkasunich> whenever you cross the solid line in either direction, you set a "want to step" bit to either up or down
[05:52:44] <jmkasunich> whenever you cross a dotted line, if the direction you are crossing the line is the same as the "want to step" bit, send the step
[05:53:05] <jmkasunich> and clear the "want to step" bit
[05:53:49] <jmkasunich> actually, the direction will always be the same as the want to step bit
[05:54:14] <SWPLinux> ok - that's noise margin :)
[05:54:26] <jmkasunich> if you last crossed a solid line going down, the only thing you can do next is cross a dotted going down (send down) or cross the same solid going up (set up wanted)
[05:54:36] <jmkasunich> right
[05:54:52] <jmkasunich> but unlike regular logic, this noise margin repeats itself
[05:55:02] <jmkasunich> I needed to draw the picture to visualize it
[05:55:31] <SWPLinux> basically it's this:
[05:55:46] <jmkasunich> so - when crossing solid, set request, when crossing dotted, send requested, and clear request
[05:56:10] <SWPLinux> if (going up) && (crossed low threshold) { issue down step and change to going_down }
[05:56:30] <SWPLinux> if (going down) && (crossed high threshold) { issue up step and change to going_up }
[05:57:23] <SWPLinux> note that going_{up,down} is not the same as the addval sign (maybe I should have chosen a different name)
[05:57:42] <jmkasunich> understood (it confused me for a moment or two)
[05:57:57] <SWPLinux> s/going/was/g
[05:59:47] <jmkasunich> bah, my idea still doesn't work
[06:00:13] <SWPLinux> which?
[06:00:22] <jmkasunich> the dashed/solid line thing
[06:00:27] <SWPLinux> heh
[06:00:56] <jmkasunich> the lines are a good visualisation tool - they let me see what pattern would break the method
[06:01:01] <SWPLinux> yep
[06:01:34] <jmkasunich> actually don't need two diffenet kinds of lines I think
[06:01:44] <jmkasunich> assume they;re all solid
[06:01:51] <SWPLinux> right now, there's a fixed comparison, which causes several complications
[06:02:03] <SWPLinux> (ie, the use of bit 31 as the step flag)
[06:02:08] <jmkasunich> every time you cross a line in ether direction, perform the following:
[06:02:30] <jmkasunich> if (this crossing dir == last crossing dir ) issue step in this crossing dir
[06:03:02] <jmkasunich> (and of course, update last crossing dir for the next time)
[06:03:02] <SWPLinux> that needs an extra full step at direction changes
[06:03:26] <jmkasunich> a deadband of one step
[06:03:33] <SWPLinux> yep
[06:03:42] <SWPLinux> that may be fine, just thought I should point it out
[06:04:11] <jmkasunich> I think that means the quantized output will always be within +/-1 step of the accumulator
[06:04:30] <jmkasunich> ideal quantization would mean the output is always within +/- 1/2 step
[06:04:37] <SWPLinux> +- 2, I think
[06:05:16] <SWPLinux> example: you're going positive, and the accum is just under the threshold for a new step
[06:05:41] <SWPLinux> reverse, and now it has to count down just under 2 steps to get one step output
[06:06:04] <SWPLinux> since the first 0.999* will be ignored
[06:06:22] <SWPLinux> that may still be within 1 step of ideal - I'm not sure at this hour :)
[06:06:51] <jmkasunich> but if its just under the threshold, then the desired position was .999 past the actual output, so as you come back the first .999, you are getting closer
[06:07:02] <SWPLinux> yeah - that's true
[06:07:22] <jmkasunich> I drew it with the accum and the quantized values on the paper
[06:07:23] <SWPLinux> I think this will bias the output 1 step in whatever direction the first command goes
[06:07:30] <jmkasunich> so far I can't find a pattern that breaks it
[06:07:43] <SWPLinux> I don't think you will
[06:07:54] <jmkasunich> the bias can be handled by choice of initial values
[06:08:27] <SWPLinux> it has 2 problems: bias from the first direction command issued, and a margin of +/- 1 full step instead of the ideal +/- 1/2 step
[06:08:50] <jmkasunich> set the initial accum value to half a step, and set the initial value of "last crossing dir" the same direction
[06:09:20] <SWPLinux> opposite direction
[06:09:27] <jmkasunich> whatever ;-)
[06:09:35] <SWPLinux> no - maybe same direction - I'm not sure
[06:10:01] <jmkasunich> duh, theres an easier way to implement this (same net result)
[06:10:05] <SWPLinux> yes - same dir - that way a single step in the same dir will go forward, adn you need 2 in reverse to go backward
[06:10:08] <jmkasunich> accum += addval
[06:10:28] <jmkasunich> if ) accum > step ) accum -= step
[06:10:35] <jmkasunich> else if (accum < -step ) accum -= step
[06:10:44] <jmkasunich> oops, += on that last one
[06:11:21] <jmkasunich> no memory of last step is even needed this way
[06:11:36] <SWPLinux> and step is?
[06:11:39] <jmkasunich> accum is no longer position, its the difference between the ideal position and the actual one
[06:11:46] <jmkasunich> step = size of a step
[06:11:48] <SWPLinux> ok
[06:11:53] <SWPLinux> step/2 maybe
[06:11:57] <jmkasunich> probably 1/2 of MAXNUM
[06:12:15] <jmkasunich> we no longer permit the accum to overflow
[06:12:34] <SWPLinux> if you're gonna do that, then there are other simplifications to do
[06:12:59] <jmkasunich> use fixed point, so that the accum range is +/- 1.0001 steps
[06:13:04] <SWPLinux> make it a real Bresenham algorithm ;)
[06:13:24] <jmkasunich> I think thats what its evolving into
[06:13:49] <jmkasunich> bresenham with hystersis
[06:14:03] <jmkasunich> or maybe deadband is more accurate
[06:14:06] <SWPLinux> the only downside is the appearance of more difficulty in determining when a step is needed
[06:14:14] <jmkasunich> not really
[06:14:19] <jmkasunich> actual code:
[06:14:27] <SWPLinux> actually, usually tou preload the accumulator with half the threshold for Bresenham - it makes the line symmetric
[06:14:32] <SWPLinux> s/tou/you
[06:14:34] <SWPLinux> /
[06:15:03] <SWPLinux> but there are no direction changes ;)
[06:15:03] <jmkasunich> signed int accum
[06:15:21] <jmkasunich> eh, I'll pastebin it
[06:15:26] <SWPLinux> heh
[06:16:44] <SWPLinux> the main change is that the freq becomes a period, and you add the thread period to accum until it's > step_period, then subtract step_period and issue a step
[06:17:19] <jmkasunich> heh, this method lets you set the hystersis to any value you want, even more than one step
[06:18:00] <SWPLinux> with 32-bit numbers and nanoseconds for step period, you can't go slower than 1 step every 4 seconds (or 2, if you need the sign bit)
[06:18:26] <jmkasunich> ;-)
[06:18:42] <jmkasunich> thats fine - remember, this is applied one mS at a time
[06:18:55] <jmkasunich> and 0 is a perfectly valid addval
[06:18:58] <SWPLinux> yep
[06:20:18] <SWPLinux> this is getting supiciously close to the Bresenham-based circle algorithm I saw years ago (with the accel and all)
[06:20:39] <SWPLinux> let's hope we don't need to make it like my integer ellipses :)
[06:21:14] <SWPLinux> speaking of integer ellipses, I think it's time for bed
[06:21:34] <SWPLinux> are you still planning to pastebin some code?
[06:21:37] <jmkasunich> yeah
[06:21:44] <jmkasunich> just a sec
[06:21:46] <SWPLinux> ok. I'll wait
[06:21:58] <jmkasunich> http://pastebin.ca/262172
[06:23:10] <jmkasunich> if HYST = 0, you get perfect quantization, always within 1/2 step of target
[06:23:25] <jmkasunich> if HYST = STEP, you get +/- 1 step of target
[06:23:25] <jmkasunich> etc
[06:23:46] <SWPLinux> was STEP supposed to be 1<<27 or 1<<31?
[06:23:58] <jmkasunich> 1<<31
[06:24:10] <SWPLinux> ok - maybe 1<<27 would be better ;)
[06:24:33] <jmkasunich> it could even be 0xC0000000
[06:24:41] <SWPLinux> 0x80000000 is effectively -INF. when you subtract from it, you end up with a positive number
[06:24:47] <jmkasunich> as long as you use the same value when computing addval
[06:24:52] <SWPLinux> no, because there's no -C0000000
[06:24:54] <jmkasunich> opps, right
[06:25:11] <jmkasunich> it could be 0x70000000
[06:25:30] <jmkasunich> my point was that it didn't have to be 1<<something
[06:25:46] <SWPLinux> the sum of STEP and HYST (or HALF_STEP and HALF_HYST) needs to be < 0x80000000
[06:25:46] <SWPLinux> sure
[06:26:17] <jmkasunich> sum of the halfs I believe
[06:26:24] <SWPLinux> I think so
[06:27:26] <jmkasunich> if STEP and HYST are both under 0x80000000, then the sum of their halves is also under
[06:27:45] <SWPLinux> yes, but STEP == 80000000 is a problem
[06:28:07] <jmkasunich> yeah
[06:28:08] <SWPLinux> because -80000000 deosn't exist (it's sort of 0)
[06:28:23] <jmkasunich> no, its 80000000
[06:28:30] <SWPLinux> right ;)
[06:28:33] <SWPLinux> x==-x
[06:29:14] <jmkasunich> exact limitations on step and hyst aren't that important
[06:29:20] <SWPLinux> nope
[06:29:46] <SWPLinux> but, if you're going to use a comparison to determine when to take a step, why not just use a DDS algorithm
[06:30:01] <jmkasunich> this _IS_ a DDS algorithm
[06:30:43] <jmkasunich> as was the original
[06:30:43] <SWPLinux> well, you're using a fixed limit and variable adder - it's easier to use a variable limit and fixed adder
[06:30:59] <jmkasunich> no
[06:31:08] <jmkasunich> well, dunno about easier or not
[06:31:13] <jmkasunich> but its not as nice
[06:31:19] <SWPLinux> if you're already using a comparison, then it's easier
[06:31:22] <jmkasunich> the variable adder has the dimensions of a frequency
[06:31:33] <jmkasunich> the variable limit has the dimensions of a period
[06:31:35] <SWPLinux> you have to use a fixed limit if you want to use overflow to generate steps
[06:31:44] <SWPLinux> yes
[06:32:05] <jmkasunich> using period gives me messy granularity - extremely fine steps near 1 Hz, and very coarse ones at the maximum step rate
[06:32:39] <jmkasunich> after all, variable limit and fixed adder is just a divide by N
[06:32:39] <SWPLinux> ok - sure
[06:32:50] <jmkasunich> (when the adder is 1)
[06:32:55] <SWPLinux> vs. coarse granularity at the minimum step rate
[06:33:14] <jmkasunich> with a fixed limit and variable adder, granularity is constant
[06:33:44] <jmkasunich> if the min frequency is 1 pulse in 4 seconds, then the granularity is 1/4 Hz, all the way from min to max
[06:33:55] <SWPLinux> at some point, there's a 2x change between adjacent attainable frequencies for either algorithm
[06:34:08] <SWPLinux> for one it's on the top and for the other it's on the bottom
[06:34:27] <jmkasunich> sure, if you are thinking in terms of percentage change
[06:34:41] <SWPLinux> but you're right - the "adjustment" is constant
[06:34:45] <SWPLinux> vs. 1/x
[06:35:03] <jmkasunich> and the 1/x approach treats zero Hz as a special case
[06:35:26] <SWPLinux> no- it's still a 0 adder, which will never generate an overflow
[06:35:45] <jmkasunich> you were talking about variable limit and fixed adder
[06:35:46] <SWPLinux> err - nevermind ;)
[06:35:51] <jmkasunich> ;-)
[06:35:57] <SWPLinux> I think it's too late for me to have ameaningful conversation
[06:36:04] <SWPLinux> in the daytime I know all this stuff :)
[06:36:05] <jmkasunich> it is getting there isn't it
[06:36:10] <SWPLinux> yes
[06:36:36] <jmkasunich> you know, the existing algorithm is just a special case of the one I put in the pastebin
[06:36:51] <SWPLinux> yes
[06:37:06] <jmkasunich> where I eliminate the "accum -= STEP" by making STEP = 1<<32 and using the overflow
[06:37:22] <SWPLinux> it doesn't give you the opportunity to decide when to add/subtract STEP
[06:37:39] <SWPLinux> and it forces HYST==0
[06:37:41] <jmkasunich> that is because I based it on a hardware DDS, where the comparison and the subtract are both expensive, and the bit manipulation to detect overflow is cheap
[06:37:49] <SWPLinux> yes
[06:38:11] <jmkasunich> I think this is a win
[06:38:13] <SWPLinux> that's the "extra information" I was talking about before
[06:38:15] <SWPLinux> yep, I think so
[06:38:26] <SWPLinux> I wonder if it will solve the problem(s) ;)
[06:39:02] <jmkasunich> well thats the thing... the "turns half a rev backwards" problem that started this is still completely unknown
[06:39:30] <jmkasunich> and the existing code doesn't actually do anything that terrible, it just looks scary with the dir line flopping around at times
[06:39:39] <SWPLinux> yep
[06:39:46] <jmkasunich> but it obeys setup and hold, and it stays within +/- 1 of the target
[06:40:43] <SWPLinux> well, I guess the real question is "what's the problem"
[06:40:54] <SWPLinux> hard to fix if you don't know what's wrong
[06:41:01] <jmkasunich> Ed's problem is half a turn backwards
[06:41:24] <jmkasunich> but when he (and skunkworks and jepler) started investigating it, they found this bouncing dir line
[06:41:34] <jmkasunich> and that diverted them from the real issue
[06:41:43] <jmkasunich> which so far I think only ed has
[06:41:54] <SWPLinux> actually, his original problem was excessive drift on long programs
[06:42:09] <SWPLinux> so he started looking at the dir line, and saw weirdness
[06:42:24] <SWPLinux> the ha;f turn thing came up later in the discussion
[06:42:27] <SWPLinux> half
[06:42:53] <jmkasunich> I think he just wasn't clear
[06:42:59] <SWPLinux> could be
[06:42:59] <jmkasunich> from the very first message:
[06:43:03] <jmkasunich> The failures are similar, but not identical: the XY position
[06:43:03] <jmkasunich> gradually drifts in off into the +X/-Y quadrant and the Z
[06:43:03] <jmkasunich> position drifts downward. The final G0 move away from the
[06:43:03] <jmkasunich> (ruined) blank should be vertically upward, but typically
[06:43:03] <jmkasunich> goes vertically downward and thunks the fixture.
[06:43:15] <jmkasunich> that last sentence is _not_ about a drift issue
[06:43:32] <jmkasunich> if its supposed to move up, drifting just changes where the up move is, it doesn't turn up into down
[06:43:32] <SWPLinux> no
[06:43:41] <SWPLinux> (no - not drift)
[06:44:25] <jmkasunich> anyway, we now know a lot more about _some_ things that are going on
[06:44:32] <SWPLinux> I was thinking that thinge are fine until something convinces stepgen that it's at the wrong height, so it moves down to get to the new height
[06:44:37] <jmkasunich> maybe Ed will have more info about the other things that are happening to him
[06:44:39] <jmkasunich> tomorrow
[06:44:43] <SWPLinux> yes
[06:44:45] <SWPLinux> err - today
[06:44:51] <jmkasunich> yeah
[06:44:56] <SWPLinux> see you later - it's definitely time for bed now :)
[06:44:56] <jmkasunich> on that note - goodnight
[06:45:29] <SWPLinux> night
[13:47:36] <jepler> wow you guys went late
[13:53:15] <rayh> Yes they did. If only I could understand.
[14:04:25] <skunkworks> I love waking up in the morning having great reading material. I may be odd though.
[14:05:30] <rayh> Was there ever a question about odd? We probably all qualify.
[14:05:57] <rayh> The talk about setup and hold -- is that stepgen params dirsetup and dirhold?
[14:13:15] <jepler> rayh: yes, that discussion was all about stepgen
[14:13:52] <jepler> there's a case where stepgen can go backwards by one step
[14:14:21] <jepler> this was prompted by Ed Nisley's problem report, though I think by the end they were convinced it wasn't a cause of the problem
[14:15:40] <rayh> I need to set up a stepper machine and try it.
[14:17:50] <skunkworks> I have been running with this 'bug' with no issues.
[14:18:14] <skunkworks> recently running a pretty complicated circuit board with no issues.
[14:18:35] <rayh> Loosing steps is my only concern.
[14:19:38] <jepler> the position counter seemed always to be correct -- so as long as the reversal doesn't stall the motor (we only saw it happen at low speeds) you don't loose position
[14:19:53] <cradek> there's no evidence that any position is lost
[14:20:36] <cradek> (but I wish I had handwheels on the mill anyway)
[14:20:41] <rayh> That is good to know.
[14:21:10] <cradek> I still think Ed's problem will go away when he tries a different machine...
[14:21:15] <rayh> say jepler nice page that BeyondWiki.
[14:23:01] <jepler> rayh: thanks, I've tried to make some improvements to that page recently
[14:23:39] <jepler> in fact I see one more edit I need to make
[14:24:25] <rayh> If I weren't running flat out and still falling behind, I'd volunteer.
[14:29:11] <jepler> I know the feeling
[14:35:36] <rayh> I see that Matt and my original work with Sherline required
[14:35:51] <rayh> SETUP_TIME = 2
[14:35:52] <rayh> HOLD_TIME =3
[14:36:19] <cradek> those are how long before and after step pulses direction must be held?
[14:36:32] <rayh> I wonder if that is still true.
[14:36:37] <cradek> yeah, that seems like a long time
[14:37:12] <jepler> at 20uS base_period?
[14:37:19] <rayh> There is a bug in the micro code and hardware on the Sherline drive.
[14:37:35] <cradek> yikes
[14:37:51] <rayh> step is read at a different time than direction.
[14:38:39] <rayh> BrianM and I found it to late to fix the board.
[14:39:40] <rayh> We spent a couple of 24 hour days at his place figuring out what was wrong.
[14:39:57] <rayh> Then Matt created setup and hold to get us around it.
[14:40:20] <rayh> I'll have to test when I get a day.
[16:08:56] <alex_jon1> alex_jon1 is now known as alex_joni
[17:36:02] <skunkworks> and paul_c swoops in for the kill ;)
[17:40:51] <jepler> yeah whatever
[17:41:04] <jepler> for all we know he was playing both sides of that conversation
[17:41:08] <jepler> it wouldn't be the first time :-P
[17:41:21] <Guest705> :)
[17:44:04] <Guest705> * Guest705 is wating for skunkworks to time out.
[17:45:13] <Lerneaen_Hydra> logger_dev: bookmark
[17:45:13] <Lerneaen_Hydra> Just this once .. here's the log: http://www.linuxcnc.org/irc/irc.freenode.net:6667/emcdevel/2006-11-30.txt
[17:57:34] <Guest705> Guest705 is now known as skunkworks