Skip to main content
Edward1
Associate
May 14, 2021
Question

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

  • May 14, 2021
  • 3 replies
  • 1049 views

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?

This topic has been closed for replies.

3 replies

magene
Senior
May 17, 2021

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
Edward1Author
Associate
April 6, 2022

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

jartim
Associate III
September 27, 2022

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.