cancel
Showing results for 
Search instead for 
Did you mean: 

What is the best way to integrate a high-precision encoder (> 2^14 PPR or > 2^16 CPR)?

Edward1
Associate

My company produces systems that use very high resolution optical encoders, with over 2^16 quadrature counts per rev (over 2^14 PPR). We are looking to modernize our positioner electronics and have been prototyping with a NUCLEO-G431RB and an IHM07M1 in 3-shunt mode.

When entering our motor parameters into the MCSDK, I can enter e.g. 20,000 for "pulses per mechanical revolution". In the generated code, M1_ENCODER_PPR holds this value. However, ENCODER_M1.PulseNumber, which is a uint16_t, is set to 4*M1_ENCODER_PPR (presumably this is CPR and the 4x comes from quadrature decoding). This value will be truncated when M1_ENCODER_PPR is greater than 16,383. All of our systems exceed this PPR threshold, so we can't use the MCSDK as-is.

So to summarize, there are a few directly related issues:

  1. The code generated by the MCSDK does not directly support high-resolution encoders with over 16,383 PPR
    1. ENCODER_Mx.PulseNumber is a uint16 despite e.g. SpeednPosFdBk.wMecAngle being an int32_t
    2. Other related calculations explicitly cast results to uint16 and/or explicitly force results to be in the range [0-65535]
    3. S16Degrees is more than sufficient for FOC but falls short for high-precision positioners
  2. The MCSDK allows entering a PPR greater than 16,383 which results in generated code that will produce truncation warnings and (presumably) does not work as expected

I was actually able to overcome this limitation somewhat by dividing the pole count and PPR by e.g. 2 in the MCSDK, then also dividing the reported angle (wMecAngle, which is an int32_t) by 2 before it is fed into the position controller. This isn't really ideal, however; is there a better supported/recommended way to do this?

3 REPLIES 3
magene
Senior II

High resolution encoders are pretty common these days and your control algorithm has to use the appropriate variable type. I'm not sure why the MCSDK would use a uint16_t (maybe it was written for an 8 bit device?), seems like all the math should be done with unit32_t and if you're doing positioning loops where the encoder counts accumulate, you might need uint64_t. If it was me, I'd just make all the integer types in the control algorithm uint64_t if I could.

Edward1
Associate

I was disappointed to see that version 6.0 of the MCSDK is still using uint16_t.

jartim
Associate III

I've experienced the same issue and ended up having to truncate the 2^19 bit position down to 14 bits to ensure it fits in the 16-bit registers. I looked at changing the 16-bit variables to 32-bit values but the entire SDK is just a complete mess and the inter-dependence between variables is all mostly undocumented so the attempt failed miserably. Just a gripe but I've been trying to get a high-res encoder running for a month now with no luck, there's just too many bugs in the SDK to make it reliable. Just my penny's worth, sorry.