INDEX PULSE, INPUT SCALE, and Cumulative Error

30 Dec 2012 21:22 - 30 Dec 2012 21:40 #28177
I have an encoder with a 25,000 count-per-revolution (100,000 pulses per rev in quadrature) that I want to affix directly to a rotary table, rather than to the motor driving the worm/gear. I mistakenly purchased this one and later realized I should have purchased one that evenly divides by 360 (e.g. 18000 CPR or 72000 ppr in quadrature.) Now I'm stuck with it.

The problem I see with this is in the division of the pulse count by the machine units. For example, on an ANGULAR axis with a 100000 PPR, dividing by 360 degrees yields 277.7777... counts per degree.

This means that with a precision of four decimal places, I will encounter a cumulative error of .0001 degrees per degree, and after one full rotation, an error of 0.036 degrees. After two full rotations, .072. By the tenth rotation, the axis will be misaligned by nearly half a degree.

The only way I can see to correct for this cumulative error is to "rewind" the table back to the beginning, otherwise this small error will eventually result in a much larger error affecting machining accuracy. However, due to the very slow rotation of this table, it is unacceptable to have to rotate my table in reverse after each full turn. Typically, a machining operation involves loading a part, rotating and drilling, then exchanging parts and repeating. The program could run all day this way - again, rotating the table back through 360 between parts is too slow and not at all acceptable.

So, I have a question: What is the behavior of the INDEX on an ANGULAR axis? Does it serve to reset the machine state to zero? Or, does Linux depend on the rotary pulse only to determine its current relative position?

Torin...
Last edit: 30 Dec 2012 21:40 by torinwalker.

30 Dec 2012 21:40 #28178
Looks like I found my answer shortly after I posted:

In the Linux CNC encoder (9) man page, one can set the "encoder.N.index-enable" flag to true which will cause the count and position to be reset upon each encounter of the a rising edge of an index pulse.

Looks like my error will not keep accumulating after all, but I still must deal with the perpetual psychological damage of knowing I'm +/- 0.0036 degrees out just before the pulse.

Don't laugh. On a 10" diameter, it corresponds to .1" of error which is appalling.

Torin...

30 Dec 2012 22:53 #28181 by BigJohnT
The scale can have a precision greater than 4 decimal places. I'm not exactly sure but I think it is... in the manual.

John

30 Dec 2012 23:04 - 30 Dec 2012 23:23 #28182 by PCW
Encoder scale is a 32 bit float so about 7 digits of accuracy

The error in not accumulative per degree but per turn.
For example, if you have a encoder count of 50000 this is divided by 277.7777
yielding 180.00005040001411200395. This error is much less than one encoder count
(.0036 degrees).

With ~7 decimal precision, you need to go about 30 turns to get off by
one encoder count equivalent.

BTW 277.7778 is about 3 times closer to 277.777777... than 277.7777
Last edit: 30 Dec 2012 23:23 by PCW.

31 Dec 2012 00:02 - 31 Dec 2012 01:15 #28184
I think I've found a way to solve it. It occurred over breakfast after the encoder(9) man page had a chance to sink in.

But first, there are a couple of responses here, so let me address each of them:

An encoder count of 50000 / 360 = 138.888...

The encoder manual suggests a 32-bit float, signed, so that gives me 31 bits of precision, 21 after the decimal. Using a 32-bit float converter, it appears I can get up to nearly 5 decimal places (i.e. 277.77776, 277.77777, 277.77778 are all equivalent with 277.77777 being the mean).

I started writing this post, calculating all the values, but then discovered I was off by an order of magnitude. The error is one order larger than I originally though. I finally broke down and wrote a program to confirm what I suspected:

Using 32 and 64-bit values side by each in the program, I used 64-bits as a reference and subtracted the 32-bit value to get the error. For a single count (277.77777) this works out to:

0.0000067817

Throwing this into excel, and calculating the error for a 10" diameter ring, I get:
(idx in degrees, error in degrees, error in inches at radius of part)

30 0.000203451 0.006391587
60 0.000406901 0.012783173
90 0.000610352 0.01917476
120 0.000813802 0.025566346
150 0.001017253 0.031957933
180 0.001220703 0.038349519
210 0.001424154 0.044741106
240 0.001627604 0.051132692
270 0.001831055 0.057524279
300 0.002034505 0.063915865
330 0.002237956 0.070307452

I thought the error would be cumulative, but it varies depending on the single precision rounding error (whether up or down), but the error is still very significant.
```        float sp_INPUT_SCALE = 277.77777f;
double dp_INPUT_SCALE = 277.7777777777778;

System.out.println("SP (32bit float) of 100k counts / 360 degrees (cast to float) = " + (100000f/360f));
System.out.println("SP (64bit float) of 100k counts / 360 degrees (cast to double) = " + (100000d/360d));
System.out.println("Difference (error) = " + ((100000d/360d) - (100000f/360f)) );

System.out.println("SP (32bit float) of value 277.77775 @ 5 places = " + 277.77775f);
System.out.println("SP (32bit float) of value 277.77776 @ 5 places = " + 277.77776f);
System.out.println("SP (32bit float) of value 277.77777 @ 5 places = " + 277.77777f);
System.out.println("SP (32bit float) of value 277.77778 @ 5 places = " + 277.77778f);
System.out.println("SP (32bit float) of value 277.77779 @ 5 places = " + 277.77779f);

for (int i = 0; i < 360; i+=30) {
System.out.println("At index of " + i + " degrees:");
System.out.println("  SP Degrees = " + i * sp_INPUT_SCALE);
System.out.println("  DP Degrees = " + i * dp_INPUT_SCALE);
double error = ((i * dp_INPUT_SCALE) - (i * sp_INPUT_SCALE));
System.out.println("  Error = " + error);
System.out.println("  Error (inches) @ 10\" diam = " + (double)(error * 31.415926) );
}```

The result came out as follows:
```SP (32bit float) of 100k counts / 360 degrees (cast to float) = 277.77777
SP (64bit float) of 100k counts / 360 degrees (cast to double) = 277.77777777777777
Difference (error) = 6.781684021461842E-6
SP (32bit float) of value 277.77775 @ 5 places = 277.77774
SP (32bit float) of value 277.77776 @ 5 places = 277.77777
SP (32bit float) of value 277.77777 @ 5 places = 277.77777
SP (32bit float) of value 277.77778 @ 5 places = 277.77777
SP (32bit float) of value 277.77779 @ 5 places = 277.7778
At index of 0 degrees:
SP Degrees = 0.0
DP Degrees = 0.0
Error = 0.0
Error (inches) @ 10" diam = 0.0
At index of 30 degrees:
SP Degrees = 8333.333
DP Degrees = 8333.333333333336
Error = 3.2552083575865254E-4
Error (inches) @ 10" diam = 0.010226538487651982
At index of 60 degrees:
SP Degrees = 16666.666
DP Degrees = 16666.66666666667
Error = 6.510416715173051E-4
Error (inches) @ 10" diam = 0.020453076975303963
At index of 90 degrees:
SP Degrees = 25000.0
DP Degrees = 25000.000000000004
Error = 3.637978807091713E-12
Error (inches) @ 10" diam = 1.1429047299316153E-10
At index of 120 degrees:
SP Degrees = 33333.332
DP Degrees = 33333.33333333334
Error = 0.0013020833430346102
Error (inches) @ 10" diam = 0.040906153950607926
At index of 150 degrees:
SP Degrees = 41666.664
DP Degrees = 41666.66666666667
Error = 0.002604166671517305
Error (inches) @ 10" diam = 0.08181230744405396
At index of 180 degrees:
SP Degrees = 50000.0
DP Degrees = 50000.00000000001
Error = 7.275957614183426E-12
Error (inches) @ 10" diam = 2.2858094598632305E-10
At index of 210 degrees:
SP Degrees = 58333.332
DP Degrees = 58333.33333333334
Error = 0.0013020833430346102
Error (inches) @ 10" diam = 0.040906153950607926
At index of 240 degrees:
SP Degrees = 66666.664
DP Degrees = 66666.66666666669
Error = 0.0026041666860692203
Error (inches) @ 10" diam = 0.08181230790121585
At index of 270 degrees:
SP Degrees = 75000.0
DP Degrees = 75000.00000000001
Error = 1.4551915228366852E-11
Error (inches) @ 10" diam = 4.571618919726461E-10
At index of 300 degrees:
SP Degrees = 83333.33
DP Degrees = 83333.33333333334
Error = 0.00520833334303461
Error (inches) @ 10" diam = 0.16362461488810792
At index of 330 degrees:
SP Degrees = 91666.664
DP Degrees = 91666.66666666669
Error = 0.0026041666860692203
Error (inches) @ 10" diam = 0.08181230790121585```

But wait... it gets better. Over breakfast, I remembered something I read in the integrator's manual and it occurred to me that Linux CNC can also express ANGULAR machine units in "Gradians" (400 per full turn), so I can eliminate this error altogether by expressing encoder counts in Gradians instead of degrees, and use 250 counts per gradian. This way, the error is eliminated, and since machine units are independent of GCode values, I can still express GCode in degrees.

I believe with this, I can rotate my table in one direction forever and no error will accumulate. I just hope the Linux CNC team doesn't deprecate Gradians... ever.

Torin...
Last edit: 31 Dec 2012 01:15 by torinwalker.

31 Dec 2012 00:40 #28187 by PCW
The error is _not_ accumulated per pulse count, the raw (integer) encoder count is multiplied
by the inverse of the scale factor in the encoder component.
The internal scaling math done in double precision but accuracy is limited to about
7 decimal places (24 bits) due to the scale factor being a single precision
IEEE754 floating point number.

So even using degrees will not cause a significant error unless you have a larger (>100) number of turns

31 Dec 2012 01:21 - 31 Dec 2012 06:29 #28191
PCW,

Ah... I get it now. I was thinking in terms of calculating the pulse count to arrive at a distance to travel, not as a means of determining distance already traveled from home/index

Plugging the encoder counts into excel, deriving the nearest whole encoder count, I get the following error then:
```Degrees	 Closest   Actual	Degrees      Distance
Integer   Degrees       Error       Error
Pulse                               (10" diam)

30       8333     29.99880084   0.001199     0.000105
60       16667    60.00120168   -0.001202    -0.000105
90       25000    90.00000252   -0.000003    0.000000
120      33333    119.9988034   0.001197     0.000104
150      41667    150.0012042   -0.001204    -0.000105
180      50000    180.000005    -0.000005    0.000000
210      58333    209.9988059   0.001194     0.000104
240      66667    240.0012067   -0.001207    -0.000105
270      75000    270.0000076   -0.000008    -0.000001
300      83333    299.9988084   0.001192     0.000104
330      91667    330.0012092   -0.001209    -0.000106```

(I had to edit this - I forgot to divide by 360 degrees)

This turns out to be not too bad after all.

PCM, thanks for correcting my understanding.

Torin...
Last edit: 31 Dec 2012 06:29 by torinwalker. Reason: Corrected some calculation errors