Help with setting up ODrive

Hello there! I recently bought three ODrives for my robotic arm project, and now I need to set them up for with some generic incremental encoder with a CPR of 2400.

So sensorless mode works perfectly. Motor turns smooth, I can adjust the speed, no problems at all. Then I set the encoder CPR and the fact that it does not use an index pulse. All without problems. Then I try to set the requested_state to AXIS_STATE_ENCODER_OFFSET_CALIBRATION. The motor starts doing something but the calibration process ends with an error. axis0 has the error ‘0x101’ and the encoder has the error ‘0x0002’ and the motor has the error ‘0x0400’.

I triple checked the wiring. I am sure that there is no slippage in the encoder assembly, the encoder is fully working when I attach it to an Arduino. I tried setting it up from a clean configuration, I even tried reflashing the firmware…

One thing that I notice and that I find somewhat weird, is the fact that when I try to calibrate the encoder, the motor spins very slowly and in little bumps. During calibration it only moves a quarter of a revolution. Perhaps that has something to do with it? So what could be wrong? Any help is much appreciated!

Dumps of axis0, encoder and motor respectively:

In [351]: odrv0.axis0
Out[351]:
error = 0x0101 (int)
step_dir_active = False (bool)
current_state = 1 (int)
requested_state = 0 (int)
loop_counter = 9363605 (int)
config:
  startup_motor_calibration = True (bool)
  startup_encoder_index_search = False (bool)
  startup_encoder_offset_calibration = False (bool)
  startup_closed_loop_control = False (bool)
  startup_sensorless_control = True (bool)
  enable_step_dir = False (bool)
  counts_per_step = 2.0 (float)
  step_gpio_pin = 1 (int)
  dir_gpio_pin = 2 (int)
  ramp_up_time = 0.4000000059604645 (float)
  ramp_up_distance = 12.566370964050293 (float)
  spin_up_current = 10.0 (float)
  spin_up_acceleration = 400.0 (float)
  spin_up_target_vel = 400.0 (float)
get_temp()
motor:
  error = 0x0400 (int)
  armed_state = 0 (int)
  is_calibrated = True (bool)
  current_meas_phB = 0.028710246086120605 (float)
  current_meas_phC = -0.18042337894439697 (float)
  DC_calib_phB = -2.002312183380127 (float)
  DC_calib_phC = -1.672202706336975 (float)
  phase_current_rev_gain = 0.02500000037252903 (float)
  current_control: ...
  gate_driver: ...
  timing_log: ...
  config: ...
controller:
  error = 0x0000 (int)
  pos_setpoint = 0.0 (float)
  vel_setpoint = 0.0 (float)
  vel_integrator_current = 0.0 (float)
  current_setpoint = 0.0 (float)
  vel_ramp_target = 0.0 (float)
  vel_ramp_enable = False (bool)
  config: ...
  set_pos_setpoint(pos_setpoint: float, vel_feed_forward: float, current_feed_forward: float)
  set_vel_setpoint(vel_setpoint: float, current_feed_forward: float)
  set_current_setpoint(current_setpoint: float)
  move_to_pos(goal_point: float)
  start_anticogging_calibration()
encoder:
  error = 0x0002 (int)
  is_ready = False (bool)
  index_found = False (bool)
  shadow_count = 11918 (int)
  count_in_cpr = 2318 (int)
  interpolation = 0.5 (float)
  phase = -2.987128257751465 (float)
  pos_estimate = 11918.234375 (float)
  pos_cpr = 2318.243408203125 (float)
  hall_state = 7 (int)
  vel_estimate = 0.0 (float)
  config: ...
sensorless_estimator:
  error = 0x0000 (int)
  phase = 1.0721758604049683 (float)
  pll_pos = 1.0748748779296875 (float)
  vel_estimate = 3.046116828918457 (float)
  config: ...
trap_traj:
  config: ...

In [352]: odrv0.axis0.encoder
Out[352]:
error = 0x0002 (int)
is_ready = False (bool)
index_found = False (bool)
shadow_count = 11918 (int)
count_in_cpr = 2318 (int)
interpolation = 0.5 (float)
phase = -2.987128257751465 (float)
pos_estimate = 11918.234375 (float)
pos_cpr = 2318.243408203125 (float)
hall_state = 7 (int)
vel_estimate = 0.0 (float)
config:
  mode = 0 (int)
  use_index = False (bool)
  pre_calibrated = False (bool)
  idx_search_speed = 10.0 (float)
  zero_count_on_find_idx = True (bool)
  cpr = 2400 (int)
  offset = 0 (int)
  offset_float = 0.0 (float)
  bandwidth = 1000.0 (float)
  calib_range = 0.019999999552965164 (float)

In [353]: odrv0.axis0.motor
Out[353]:
error = 0x0400 (int)
armed_state = 0 (int)
is_calibrated = True (bool)
current_meas_phB = -0.04319643974304199 (float)
current_meas_phC = -0.010598301887512207 (float)
DC_calib_phB = -2.011108875274658 (float)
DC_calib_phC = -1.681341290473938 (float)
phase_current_rev_gain = 0.02500000037252903 (float)
current_control:
  p_gain = 0.006497671362012625 (float)
  i_gain = 41.0604248046875 (float)
  v_current_control_integral_d = 0.0 (float)
  v_current_control_integral_q = 0.0 (float)
  Ibus = 4.842089310841402e-06 (float)
  final_v_alpha = -0.0007847443339414895 (float)
  final_v_beta = 0.002696799347177148 (float)
  Iq_setpoint = 0.07600197196006775 (float)
  Iq_measured = 0.03078344464302063 (float)
  max_allowed_current = 60.75 (float)
  overcurrent_trip_level = 67.5 (float)
gate_driver:
  drv_fault = 0 (int)
timing_log:
  TIMING_LOG_GENERAL = 0 (int)
  TIMING_LOG_ADC_CB_I = 2670 (int)
  TIMING_LOG_ADC_CB_DC = 12890 (int)
  TIMING_LOG_MEAS_R = 7410 (int)
  TIMING_LOG_MEAS_L = 7434 (int)
  TIMING_LOG_ENC_CALIB = 7610 (int)
  TIMING_LOG_IDX_SEARCH = 0 (int)
  TIMING_LOG_FOC_VOLTAGE = 7558 (int)
  TIMING_LOG_FOC_CURRENT = 7746 (int)
config:
  pre_calibrated = True (bool)
  pole_pairs = 14 (int)
  calibration_current = 10.0 (float)
  resistance_calib_max_voltage = 2.0 (float)
  phase_inductance = 6.497671165561769e-06 (float)
  phase_resistance = 0.0410604253411293 (float)
  direction = 1 (int)
  motor_type = 0 (int)
  current_lim = 38.0 (float)
  requested_current_range = 60.0 (float)
  current_control_bandwidth = 1000.0 (float)

In [354]:

Ok, problem solved!

I still don’t know exactly why, but I ran a setup using a python program and now it works, even in odrivetool

Uhh ok strange. Did you have your Pole-pairs value set correctly? Encoder error 2 is “wrong cpr, but it could also mean wrong # of pole pairs due to how the calibration works

It probably has something to do with the pole-pairs value being wrong or the CPR value that wasn’t set correctly. Perhaps it was never saved correctly because of that bug that only allows one save of the configuration per boot.