- Posts: 972
- Thank you received: 0
Encoder velocities and index signal reading
I'm going to whip up a block diagram for it. One thing I'm not certain of is I like to deal with everything as positions rather than counts. In order to apply a modulus operation it must be done on an integer right? Thinking the component is going to have to accept a position as float input and a "requested position" as float input (the expected remainder of the modulus which will behave similar to a comparator. Assuming that's the case it's going to require 2 float to integer conversions. Curious if that's any sort of a performance hit I should be concerned about. I wouldn't think it's something I'd worry about since I have all sorts of that going on in the current hal file anyway.
Please Log in to join the conversation.
HAL float pins are double precision, approx 15 decimal places resolution, and that means that 100000000000000 == 100000000000001
If there is no chance of getting that far then it's OK.
(The actual maths is more complicated than I describe here, see for example stackoverflow.com/questions/9999221/doub...ision-decimal-places )
If you work in 64-but int there is really no danger of this sort of problem.
Please Log in to join the conversation.
Please Log in to join the conversation.
andypugh wrote: You can work in float if you want, but be careful that you don't run out of numerical resolution. How long does your encoder run for between resets?
HAL float pins are double precision, approx 15 decimal places resolution, and that means that 100000000000000 == 100000000000001
If there is no chance of getting that far then it's OK.
(The actual maths is more complicated than I describe here, see for example stackoverflow.com/questions/9999221/doub...ision-decimal-places )
If you work in 64-but int there is really no danger of this sort of problem.
Is it a thing to impose limits on hal input pins? I don't expect to count past 280.000 with only 3 digit precision being necessary. The divisor pin would be a max of 10 in real use. If possible I'd limit the pin "event-position" pin to 99.999 and the Repeat-multiple pin to 99 then the max length possible for the encoder to run off and count positions to would convert to 9899901 I suppose. The encoder position is to be reset when the trigger pin is output.
Makes more sense looking at this, or maybe not. I'll have to stare at this for an hour tomorrow to see if I didn't go overboard with this, but at the moment I gave myself a headache. Besides the fact that the float-int conversions may not all be necessary which I'm sure my friend can figure out, I think I've considered everything. It seemed easier, then I got to it and it got a bit more complicated than I expected.
Attachment not found
Please Log in to join the conversation.
It has just occurred to me that you might be able to mis-use the "bldc" component for this purpose. (in "qiB" mode. linuxcnc.org/docs/2.7/html/man/man9/bldc.9.html )
But a custom component seems more elegant and adaptable.
Please Log in to join the conversation.
Please Log in to join the conversation.
Generally coding puzzles are always bigger than expected, but with a good spec from you this probably is only a dozen lines of code.
Tips for your coder friend:
Your code will be called automatically ever 1mS. It can't wait, it has to run straight through ever time.
static state variables are a good way to handle waiting, and context-dependent behaviour. Many comps use a state machine structure.
The comp file format plays strange games with macros. You might be surprised by the bracket styles needed.
Please Log in to join the conversation.
you can just use the fmod(a,b) function to calculate the modulus of two floating point numbers (where a is divided by b in the example)
This will result in a floating point number though. If you wanted a whole number there are two options:
Round up or down to the nearest whole number using round() or;
truncate to the whole number value (eg always round down) with trunc()
The only thing you need to be careful of is that you can't really test for equality with any floating point number. Instead you test for precision. Something like this:
It depends how precise you want to be but there is no point testing for a value that is smaller than the machine's resolution.
Finally, let me say inputting a value in nano seconds makes no sense when the servo thread generally only fires every millisecond so LinuxCNC can't see time periods below 1 millisecond. You can run a faster servo thread if your PC hardware is good enough but I thought that going past 4 kHz was problematic.
So once your friend gets to code this, it will keep getting simpler..
PS What would Gutenberg say if he saw this. Can you imagine inventing a technology today that remained unchanged for 350 years like he did!
Please Log in to join the conversation.
rodw wrote: Finally, let me say inputting a value in nano seconds makes no sense when the servo thread generally only fires every millisecond so LinuxCNC can't see time periods below 1 millisecond. You can run a faster servo thread if your PC hardware is good enough but I thought that going past 4 kHz was problematic.
You're right, It did seem necessary to add a width though since otherwise the pin would only hold a true value for one servo period, msec float would probably be more appropriate. The integer conversions were there just in case it is what was necessary, not that it really is. Kind of a moot point because this is what he came back with:
Lol now I'm a bit miffed, I can't find any reason why that won't work other than maybe some LinuxCNC semantics and it probably should have the output-width pin. I feel like it shouldn't be this easy but it looks like it probably is.
Please Log in to join the conversation.
C is a typed language so it is not usually valid to mix types (unsigned and double) in a calculation so you need to use a cast to explicitly tell C to convert that number to a double before using it.
EDIT: So the code will compile but I would expect to generate a compiler warning and one should always treat warnings as if it was an error if you are programming defensively.
Please Log in to join the conversation.
