Cpr out of range error with ODrive 3.4 + ABI Magnetic Rotary Position Sensor (AS5047P)

Hi guys,

I bought an ODrive V3.4 (a true masterpiece of electrical engieneering in my opinion!) and want to use it in combination with a bldc as replacement for a stepper motor.

I use an AS5047P as positioning sensor. It uses its ABI Incremental Interface (datasheet p.19) and and is configured with 4000 Steps Per Revolution / 1000 Pulses Per Revolution. The ABI interface is connected to M0 A/B/Z. 3.3V suppy is ok and I can see all signals at my oscilloscope.

I followed all steps in Github’s README.md.

My Firmware/tup.config is:


//M0 encoder
.encoder = {
.encoder_timer = &htim3,
.use_index = true,
.index_found = false,
.manually_calibrated = false,

make flash worked perfectly

I did following steps with explore_odrive.py:
my_odrive.motor0.encoder.config.cpr = 4000
my_odrive.motor0.config.pole_pairs = 20
my_odrive.config.brake_resistance = 0.47
my_odrive.motor0.config.motor_type = MOTOR_TYPE_HIGH_CURRENT
my_odrive.motor0.current_control.config.current_lim = 10
my_odrive.motor0.config.vel_limit = 1000

When I switch ODrive on it starts to spin motor 0 about 1/3rd revolutoion and stops than giving error 22 - ERROR_ENCODER_CPR_OUT_OF_RANGE. my_odrive.motor0.encoder.encoder_offset is 0 and my_odrive.motor0.encoder.motor_dir is permanent 1. my_odrive.motor0.pos_setpoint = 10000 does not work (of course). my_odrive.motor0.encoder.encoder_state is 4000 for one full revolution and counts up to infinity - at least I guess, couldn’t validate this.

Can you give me a hint what I am doing wrong? Google couldn’t help me and ODrive seems so simple to use, so the problem is definitely between screen an chair ;0)

Hi, thanks for the kind words about ODrive.

The first thing to double check is the CPR value by turning the motor by hand 1 revolution and check encoder_state: but you already did this, so that looks good.
The next thing to check is that the motor pole pairs is correct. You need to count the number of permanent magnets in the rotor, and then divide this number by two. This is the pole pair number. Just to help verify, if you have a link to the motor then I can see if I can help double check.


Thanks for the hint, Oskar!

Now it works!

I couldn’t verify the pole pair by looking into the Motor. It has a weather-sealed housing and I had no idea about the exact type (I just know some parameters). So I had no chance to find a data sheet and therefore I did the following to

find out the number of pole pairs of the unknown motor:

  • mark the rotor and make another mark on some fix part in line with the fist mark
  • apply some current to two wires, so that the motor is in a fixed position and you can feel the force when you try to turn it (I used 800mA)
  • turn the rotor one revolution (until the the marks are in line again) and count the resistances you can feel
  • the number or “ticks” (resistances) you can feel is equal to the pole pair number

In my case the correct number was 21. When I did this the first time I did not count the last “tick” when the marks aligned again. So I had 20. This was wrong and led to the error 22 - ERROR_ENCODER_CPR_OUT_OF_RANGE.

The pole pair setup was the problem. I did the setup with correct number and ODrive works like a charm

1 Like

I have a very similar issue. I have an AS5048 and a motor with a 24N22P configuration (so 11 pole pairs). However, correctly setting the pole pairs to 11 and the encoder CPR to 2048 did not solve the issue. After the calibration sequence it always reports CPR out of range. How can I debug?

Check that your encoder is well mounted.

I think that must have been the issue.

how did you interface the as5048 encoder, isn’t it SPI based? i’m trying to understand how to interface it with Odrive. Any help would be appreciated. I have a AS5048A

To whoever this may still be relevant:
I also had error ERROR_CPR_OUT_OF_RANGE with an AS5047P, with correct CPR and pole pairs set.
The solution that worked for me was to increase the calib_range:
.encoder.config.calib_range = 0.05
, as suggested in the documentation:

1 Like

Thanks for the share of
odrv0.axis0.encoder.config.calib_range = 0.05

I had turned my odrive on today and for some reason was getting stuck. Fixed it right up!

1 Like

Glad it worked!
Also double check your encoder CPR setting. In my case I had to set it to 4000, NOT 4096!

1 Like