Successfull Calibration; But Motor Won't Turn; Intermittent CPR_POLEPAIRS_MISMATCH error

I am able to do a Full motor calibration where the motor spins in one direction then reverses with no issue and no errors. However when I attempt to run closed loop control I can’t get the motor to move on its own accord except for sudden runaway events. I followed the getting started guide and have previously set up a different motor with a different encoder which run fine.

I have verified current is being applied to the motor by plotting Iq_measured and Iq_setpoint and when I attempt to rotate the motor by hand (under current control of a few amps) I feel resistance to movement (which scales with the current setpoint) but am able to turn it manually. I am suspicious of some commutation issue but don’t know how to troubleshoot further. Below is a list of what I have tried:

  • Checked shadow counts after rotating motor a full rotation. I’ve verified as close as 9999 counts and figure that’s good enough to verify that it’s not missing counts.
  • Plotted the current control parameters as described above to verify current is getting to the coils
  • Attempted to do velocity control of 0.1 Turns/sec and 1.0 Turns/sec by setting the velocity gain to ~0 and velocity integrator gain 0.01 to see the current climb until there’s movement. When doing this it will start with no movement at all and at some point it will jump really quickly (fraction of a second) then hit a current limit and stop
  • Tried a different ODrive with factory firmware v3.6 56V
  • Tried ODrive firmware devel branch sha: a406aa06
  • Checked the encoder quadrature using a logic analyzer, parsed data from the logic analyzer shows the correct number of counts and no illegal transitions

I have a 20 pole pair KV90 R100 motor from T-Motor and am using a US digital 10,000 CPR encoder mounted on the motor shaft for commutation (haven’t tried the motor halls yet). Any ideas what might be going wrong here or any steps to help troubleshoot?


Make sure controller.config.input_mode is set to INPUT_MODE_PASSTHROUGH or something other than INPUT_MODE_NONE.

Just verified; it is set to INPUT_MODE_PASSTHROUGH. Thanks for the suggestion though.

After having a number of successful full calibrations I was able to get an “AXIS_ERROR_ENCODER_FAILED”; “ENCODER_ERROR_CPR_POLEPAIRS_MISMATCH” error. The encoder wire is already shielded, I will try to shorten the length and see if that helps at all.

In general though is 500 cpr/pole pair (10,000/20) a suitable encoder resolution to pole pair ratio or does that seem like it’s cutting it a little close?

500cpr/pole pair shouldn’t cause issues like this…
Are you quite sure it’s 20 pole pairs and not 21? (ok you linked the specs, it should be right… but worth checking anyway :slight_smile: ) Some of T-Motor’s motors are 21 pole pairs.

I’m just going off the spec sheet. Although it is curious that the motor’s smaller cousin (R80) has 21 pole pairs. I tried 21 pole-pairs and it is now failing consistently with the ENCODER_ERROR_CPR_POLEPAIRS_MISMATCH so it seems to check out that 20 is the right count which gives more consistent passing calibration.

Is the encoder set up to use the index signal?
If use_index=True and zero_count_on_index_pulse=True, then you could have a noise transient that resets your encoder and screws your calibration

Here’s my encoder config

mode = 0 (int)
use_index = False (bool)
find_idx_on_lockin_only = False (bool)
abs_spi_cs_gpio_pin = 1 (int)
zero_count_on_find_idx = True (bool)
cpr = 10000 (int)
offset = 23279 (int)
pre_calibrated = False (bool)
offset_float = 0.5311093926429749 (float)
enable_phase_interpolation = True (bool)
bandwidth = 1000.0 (float)
calib_range = 0.019999999552965164 (float)
calib_scan_distance = 50.26548385620117 (float)
calib_scan_omega = 12.566370964050293 (float)
idx_search_unidirectional = False (bool)
ignore_illegal_hall_state = False (bool)
sincos_gpio_pin_sin = 3 (int)
sincos_gpio_pin_cos = 4 (int)

and motor config:

In [34]: odrv0.axis0.motor.config
pre_calibrated = False (bool)
pole_pairs = 20 (int)
calibration_current = 10.0 (float)
resistance_calib_max_voltage = 2.0 (float)
phase_inductance = 1.840209006331861e-05 (float)
phase_resistance = 0.04901665076613426 (float)
torque_constant = 1.0 (float)
direction = 1 (int)
motor_type = 0 (int)
current_lim = 20.0 (float)
current_lim_margin = 8.0 (float)
torque_lim = inf (float)
inverter_temp_limit_lower = 100.0 (float)
inverter_temp_limit_upper = 120.0 (float)
requested_current_range = 60.0 (float)
current_control_bandwidth = 1000.0 (float)
acim_slip_velocity = 14.706000328063965 (float)
acim_gain_min_flux = 10.0 (float)
acim_autoflux_min_Id = 10.0 (float)
acim_autoflux_enable = False (bool)
acim_autoflux_attack_gain = 10.0 (float)
acim_autoflux_decay_gain = 1.0 (float)

Upon occasion I can get the motor to spin briefly when transitioning the current setpoint. For example I had it in closed loop control and gave it 1A, the motor moved quickly then stopped (I should mention the setup has ~ no load on it currently). I then bumped it to 1.5A and it spinned quickly one way, then reversed quickly then stopped. Changing the current to -1.5A gave me no movement. I feel like this validates suspicions of some flawed commutation issue.

Here is some of the behavior I’m experiencing. This is a plot of “shadow counts” and occurred after transitioning from -1.5A to -2A. As you can see there’s no acceleration or movement in general at steady state current control but setpoint changes create some strange behavior. Here the motor quickly jumps one way, then reverses quickly and ends up back at the same place as before.

This was after remaking the shielded encoder cable to be a total of 4" long, w/ the shield connected to ground, and the index pin disconnected from the ODrive.

So I seem to have under-estimated the amount of load on the system. I had received the motor pre-built attached to a shaft but removed the load from the shaft. After exhaustively troubleshooting I pulled the motor completely off the shaft and now am able to get it to move reliably. The bearing alone has quite a lot more resistance than I was expecting. I am guessing the motor wasn’t getting the correct commutation due to the load on the shaft. Thanks for the help towen!

That is weird, the motor shoud be able to produce the commanded torque even at stall. It sholdn’t be the case that excessive load causes a commutation failure, unless you’re in sensorless mode.
On that note, please check that axis.config.enable_sensorless_estimator is set to False!