BLDC Hub motor is not running with oDrive Controller

I don’t have the right equipment to get the ‘detent’. Is there any service provider who can do it for me? Can you help me to figure it out for a service fee? @towen

Did you try this: Getting Started | ODrive

Connected to ODrive 2062356E5748 as odrv0
In [1]: odrv0.axis0.motor.error
Out[1]: 0

In [2]: odrv0.axis0.requested_state = AXIS_STATE_MOTOR_CALIBRATION^M
…:

In [3]: odrv0.axis0.motor.config.pre_calibrated = True^M
…:

In [4]: odrv0.save_configuration()
Oh no odrv0 disappeared

Reconnected to ODrive 2062356E5748 as odrv0
In [5]: odrv0.axis0.requested_state = AXIS_STATE_ENCODER_HALL_POLARITY_CALIBRATION^M
…:

In [6]: odrv0.axis0.encoder.error
Out[6]: 16

In [7]: odrv0.axis0.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION^M
…:

In [8]: odrv0.axis0.encoder.error
Out[8]: 528

In [9]:

This is my configuration after changing the Pole pairs to 20 according to the Motor but still the motor does not move. @towen

odrv0.axis0.motor.config.pole_pairs = 20

odrv0.axis0.motor.config.resistance_calib_max_voltage = 4
odrv0.axis0.motor.config.requested_current_range = 25
odrv0.axis0.motor.config.current_control_bandwidth = 100
odrv0.axis0.motor.config.torque_constant = 8.27 / 27.7
odrv0.axis0.encoder.config.mode = ENCODER_MODE_HALL
odrv0.axis0.encoder.config.cpr = 120
odrv0.axis0.encoder.config.calib_scan_distance = 200
!
odrv0.axis0.encoder.config.bandwidth = 100
odrv0.axis0.controller.config.pos_gain = 1
odrv0.axis0.controller.config.vel_gain = 0.02 * odrv0.axis0.motor.config.torque_constant * odrv0.axis0.encoder.config.cpr
odrv0.axis0.controller.config.vel_integrator_gain = 0.1 * odrv0.axis0.motor.config.torque_constant * odrv0.axis0.encoder.config.cpr
odrv0.axis0.controller.config.vel_limit = 36
odrv0.axis0.controller.config.control_mode = CONTROL_MODE_VELOCITY_CONTROL

after changing pole_pairs, you must run odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE
before you can set axis_state=AXIS_STATE_CLOSED_LOOP_CONTROL

Also, make sure to use dump_errors(odrv0, True) before and after - this shows active errors and then clears them.

Hi @towen I put that command but right after that I lost the communication from my Ubuntu laptop to the controller connected via the USB cable it came with it. I had to power recycle the controller to login again.

Reconnected to ODrive 2062356E5748 as odrv0
In [3]: odrv0.axis0.motor.config.pole_pairs = 20

In [4]: odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE

Oh no odrv0 disappeared

After reconnected though I did not power recycle yet

In [1]: odrv0.axis0.requested_state
Out[1]: 0

In [2]: odrv0.axis0.motor.config.pole_pairs
Out[2]: 20

In [3]: odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE

Oh no odrv0 disappeared
Reconnected to ODrive 2062356E5748 as odrv0
In [4]: odrv0.axis0.requested_state
Out[4]: 0

In [5]: odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE

Oh no odrv0 disappeared
In [6]: 23:17:39.881339498 [LEGACY_PROTOCOL] received unexpected ACK: 419

After a hard reset I got the following

eclbd@eclbd-laptop:~$ odrivetool
ODrive control utility v0.5.3.post0
Website: https://odriverobotics.com/
Docs: https://docs.odriverobotics.com/
Forums: https://discourse.odriverobotics.com/
Discord: ODrive
Github: GitHub - odriverobotics/ODrive: High performance motor control

Please connect your ODrive.
You can also type help() or quit().

Connected to ODrive 2062356E5748 as odrv0
In [1]: odrv0.axis0.requested_state
Out[1]: 0

In [2]: odrv0.axis0.motor.config.pole_pairs
Out[2]: 7

Connected to ODrive 2062356E5748 as odrv0
In [1]: dump_errors(odrv0, True)
system: no error
axis0
axis: no error
motor: no error
sensorless_estimator: no error
encoder: Error(s):
ENCODER_ERROR_CPR_POLEPAIRS_MISMATCH
controller: no error
axis1
axis: no error
motor: no error
sensorless_estimator: no error
encoder: no error
controller: no error

@towen I am kind of lost my mind because the error state is not consistence while the drive reconnected after a save_configuration() command

I got to know that the motor has 20 magnets so I devidied it by 2 as recommended, so the pole_pairs = 10 and I put the cpr = 8192 and that seems the Encoder error resolved at some points but I am exactly could track of that whether that was because the drive got reconnected or not.

I am getting other HALL error "ENCODER_ERROR_ILLEGAL_HALL_STATE "while adding encoder.config values. Do I need add an external Encoder like the one availavle in Odrive store?

here is some config attempts and their output. Sorry, its a big one.

In [24]: odrv0.axis0.motor
Out[24]: 
DC_calib_phA: 1.0643467903137207 (float)
DC_calib_phB: -0.30078402161598206 (float)
DC_calib_phC: -0.7636010050773621 (float)
I_bus: 0.0 (float)
config:
  I_bus_hard_max: inf (float)
  I_bus_hard_min: -inf (float)
  I_leak_max: 0.10000000149011612 (float)
  R_wL_FF_enable: False (bool)
  acim_autoflux_attack_gain: 10.0 (float)
  acim_autoflux_decay_gain: 1.0 (float)
  acim_autoflux_enable: False (bool)
  acim_autoflux_min_Id: 10.0 (float)
  acim_gain_min_flux: 10.0 (float)
  bEMF_FF_enable: False (bool)
  calibration_current: 10.0 (float)
  current_control_bandwidth: 100.0 (float)
  current_lim: 10.0 (float)
  current_lim_margin: 8.0 (float)
  dc_calib_tau: 0.20000000298023224 (float)
  inverter_temp_limit_lower: 100.0 (float)
  inverter_temp_limit_upper: 120.0 (float)
  motor_type: 0 (uint8)
  phase_inductance: 0.00027972811949439347 (float)
  phase_resistance: 0.19126087427139282 (float)
  pole_pairs: 10 (int32)
  pre_calibrated: False (bool)
  requested_current_range: 25.0 (float)
  resistance_calib_max_voltage: 4.0 (float)
  torque_constant: 0.30000001192092896 (float)
  torque_lim: inf (float)
current_control:
  I_measured_report_filter_k: 1.0 (float)
  Ialpha_measured: 0.0 (float)
  Ibeta_measured: 0.0 (float)
  Id_measured: 0.0 (float)
  Id_setpoint: 0.0 (float)
  Iq_measured: 0.0 (float)
  Iq_setpoint: 0.0 (float)
  Vd_setpoint: 0.0 (float)
  Vq_setpoint: 0.0 (float)
  final_v_alpha: 0.0 (float)
  final_v_beta: 0.0 (float)
  i_gain: 19.126087188720703 (float)
  p_gain: 0.027972811833024025 (float)
  phase: 0.0 (float)
  phase_vel: 0.0 (float)
  power: 0.0 (float)
  v_current_control_integral_d: 0.0 (float)
  v_current_control_integral_q: 0.0 (float)
current_meas_phB: 0.30271321535110474 (float)
effective_current_lim: 10.0 (float)
error: 0 (uint64)
  temperature: 31.108919143676758 (float)
is_armed: False (bool)
is_calibrated: True (bool)
last_error_time: 0.0 (float)
max_allowed_current: 30.375 (float)
max_dc_calib: 3.0375001430511475 (float)
motor_thermistor:
  config: ...
  temperature: 0.0 (float)
n_evt_current_measurement: 1571465 (uint32)
n_evt_pwm_update: 1571470 (uint32)
phase_current_rev_gain: 0.012500000186264515 (float)

In [25]: odrv0.axis0.motor.config.pre_calibrated = True

In [26]: odrv0.save_configuration()
Oh no odrv0 disappeared

Reconnected to ODrive 2062356E5748 as odrv0
In [27]: odrv0.axis0.requested_state = AXIS_STATE_ENCODER_HALL_POLARITY_CALIBRATION

Oh no odrv0 disappeared

In [29]: dump_errors(odrv0, True)
system: no error
axis0
  axis: no error
  motor: no error
  sensorless_estimator: no error
  encoder: Error(s):
    ENCODER_ERROR_ILLEGAL_HALL_STATE
  controller: no error
axis1
  axis: no error
  motor: no error
  sensorless_estimator: no error
  encoder: no error
  controller: no error

Reconnected to ODrive 2062356E5748 as odrv0
In [28]: odrv0.axis0.encoder
Out[28]: 
calib_scan_response: 0.0 (float)
config:
  abs_spi_cs_gpio_pin: 1 (uint16)
  bandwidth: 100.0 (float)
  calib_range: 0.019999999552965164 (float)
  calib_scan_distance: 150.0 (float)
  calib_scan_omega: 12.566370964050293 (float)
  cpr: 8192 (int32)
  direction: -1 (int32)
  enable_phase_interpolation: True (bool)
  find_idx_on_lockin_only: False (bool)
  hall_polarity: 0 (uint8)
  hall_polarity_calibrated: False (bool)
  ignore_illegal_hall_state: False (bool)
  index_offset: 0.0 (float)
  mode: 1 (uint16)
  phase_offset: 0 (int32)
  phase_offset_float: 0.0 (float)
  pre_calibrated: False (bool)
  sincos_gpio_pin_cos: 4 (uint16)
  sincos_gpio_pin_sin: 3 (uint16)
  use_index: False (bool)
  use_index_offset: True (bool)
count_in_cpr: 0 (int32)
delta_pos_cpr_counts: 0.0 (float)
error: 16 (uint16)
hall_state: 5 (uint8)
index_found: False (bool)
interpolation: 0.5 (float)
is_ready: False (bool)
phase: 0.0 (float)
pos_abs: 0 (int32)
pos_circular: 0.0 (float)
pos_cpr_counts: 0.0 (float)
pos_estimate: 0.0 (float)
pos_estimate_counts: 0.0 (float)
set_linear_count(obj: object_ref, count: int32)
shadow_count: 0 (int32)
spi_error_rate: 0.0 (float)
vel_estimate: 0.0 (float)
vel_estimate_counts: 0.0 (float)

After a save_config, the error went away, probably the odrive got reconnected then

In [33]: odrv0.axis0.encoder
Out[33]: 
calib_scan_response: 0.0 (float)
config:
  abs_spi_cs_gpio_pin: 1 (uint16)
  bandwidth: 100.0 (float)
  calib_range: 0.019999999552965164 (float)
  calib_scan_distance: 150.0 (float)
  calib_scan_omega: 12.566370964050293 (float)
  cpr: 8192 (int32)
  direction: -1 (int32)
  enable_phase_interpolation: True (bool)
  find_idx_on_lockin_only: False (bool)
  hall_polarity: 0 (uint8)
  hall_polarity_calibrated: False (bool)
  ignore_illegal_hall_state: False (bool)
  index_offset: 0.0 (float)
  mode: 1 (uint16)
  phase_offset: 0 (int32)
  phase_offset_float: 0.0 (float)
  pre_calibrated: False (bool)
  sincos_gpio_pin_cos: 4 (uint16)
  sincos_gpio_pin_sin: 3 (uint16)
  use_index: False (bool)
  use_index_offset: True (bool)
count_in_cpr: 0 (int32)
error: 0 (uint16)
index_found: False (bool)
is_ready: False (bool)
pos_abs: 0 (int32)
pos_circular: 0.0 (float)
pos_cpr_counts: 0.0 (float)
pos_estimate: 0.0 (float)
pos_estimate_counts: 0.0 (float)
set_linear_count(obj: object_ref, count: int32)
shadow_count: 0 (int32)
spi_error_rate: 0.0 (float)
vel_estimate: 0.0 (float)
vel_estimate_counts: 0.0 (float)

In [34]: 

In [34]: odrv0.axis0.encoder.config.pre_calibrated = True

In [35]: odrv0.save_configuration()
Oh no odrv0 disappeared

Reconnected to ODrive 2062356E5748 as odrv0
In [36]: odrv0.reboot()
Oh no odrv0 disappeared

Reconnected to ODrive 2062356E5748 as odrv0
In [37]: odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL

In [38]: dump_errors(odrv0, True)
system: no error
axis0
  axis: no error
  motor: Error(s):
    MOTOR_ERROR_UNKNOWN_PHASE_ESTIMATE
  sensorless_estimator: no error
  encoder: no error
  controller: no error
axis1
  axis: no error
  motor: no error
  sensorless_estimator: no error
  encoder: no error
  controller: no error

In [39]: odrv0.axis0.controller.input_vel = 2

In [40]: dump_errors(odrv0, True)
system: no error
axis0
  axis: no error
  motor: no error
  sensorless_estimator: no error
  encoder: no error
  controller: no error
axis1
  axis: no error
  motor: no error
  sensorless_estimator: no error
  encoder: no error
  controller: no error

The behavior of he controller is unusual as below. What value should I expect from “odrv0.axis0.requested_state”

Connected to ODrive 2062356E5748 as odrv0
In [1]: odrv0.axis0.encoder.config.cpr
Out[1]: 8192

In [2]: odrv0.axis0.motor.config.pole_pairs
Out[2]: 10

In [3]: odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE

Oh no odrv0 disappeared
Reconnected to ODrive 2062356E5748 as odrv0
In [4]: odrv0.save_configuration()
Oh no odrv0 disappeared

Reconnected to ODrive 2062356E5748 as odrv0
In [5]: dump_errors(odrv0, True)
system: no error
axis0
axis: no error
motor: no error
sensorless_estimator: no error
encoder: no error
controller: no error
axis1
axis: no error
motor: no error
sensorless_estimator: no error
encoder: no error
controller: no error

In [6]: odrv0.axis0.requested_state
Out[6]: 0

@towen I manually rotate the motor 1 full cycle and got
odrv0.axis0.encoder.shadow_count = 80

What could be my CPR value if the pole_pairs = 20/2

Saving configuration implicitly causes the drive to reboot, so that is why it is resetting errors.

This isn’t good, it shouldn’t lose communication when you do a calibration. Do you have any ferrite rings?
Is your power supply stable? Maybe you are running on too low a current limit for the calibration.

In theory, if your motor uses Hall sensors, you should see a CPR of 6 * pole_pairs i.e. 60 counts per rev if you have a 10 pole pair motor.

Thanks for your reply once again @towen

I am using a Lithium-Ion battery with 40V and 5Ah from https://www.lowes.com/pd/SKIL-40V-5-0Ah-Battery/5000214253?cm_mmc=shp--c--prd--sol--bng--LIA_SOL_239_Battery-Ope--5000214253--0--0-_-0&msclkid=739f5537e46f1e80fc3c34637172f98f&gclid=739f5537e46f1e80fc3c34637172f98f&gclsrc=3p.ds

I ordered the Ferrite Ring. I will use it when it arrives. What should be the best Power sources for the controller and the Wheels? The wheel is 36v & 350W. I have 2 of them.

@towen

I found this info for the motor as max. Can you help me with the correct input values?

@towen
I used the Ferrite Ring now and the driver is not disconnecting after running the calibration command but I am getting errors.

Reconnected to ODrive 2062356E5748 as odrv0
In [10]: odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE

Could you please suggest a solution?

In [11]: dump_errors(odrv0, True)
system: no error
axis0
axis: no error
motor: no error
sensorless_estimator: no error
encoder: Error(s):
ENCODER_ERROR_CPR_POLEPAIRS_MISMATCH
controller: no error
axis1
axis: no error
motor: no error
sensorless_estimator: no error
encoder: no error
controller: no error

Please check that your encoder cpr is set to 60.
If it is, then perhaps use odrivetool liveplotter and turn the motor by hand, noting how many counts per turn it shows. If it looks strange, post it here.

Hi @towen Please look at my initial configuration

In [16]: odrv0.axis0.motor.config.pole_pairs = 10
…: odrv0.axis0.encoder.config.cpr = 60
…: odrv0.axis0.motor.config.resistance_calib_max_voltage = 4
…: odrv0.axis0.motor.config.requested_current_range = 36
…: odrv0.save_configuration()
…:
Oh no odrv0 disappeared

Reconnected to ODrive 2062356E5748 as odrv0
In [17]: odrv0.reboot()
Oh no odrv0 disappeared

Reconnected to ODrive 2062356E5748 as odrv0
In [18]: odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE

In [19]: dump_errors(odrv0, True)
system: no error
axis0
axis: no error
motor: no error
sensorless_estimator: no error
encoder: Error(s):
ENCODER_ERROR_CPR_POLEPAIRS_MISMATCH
controller: no error
axis1
axis: no error
motor: no error
sensorless_estimator: no error
encoder: no error
controller: no error

Figure_1

Hi @towen I added the liveplotter graphical chart in my previous chart. Any suggestions on that? It is counting from 6-8 per rotation of the wheel.

Do you offer any professional services that I can take? Please let me know.

It should register 1 per turn. If it doesn’t, the cpr is wrong, or maybe you have a geared motor.

I had the same error(CPR_MISMATCH) with a hoverboard motor. I fixed it by having the right number of poles and CPR value at pole*6 as per the documentation and was able to calibrate the motor. From the picture you posted, the poles value should be 20 and cpr should be 120.

see if changing the below values will work for you.

odrv0.axis0.motor.config.pole_pairs = 20
odrv0.axis0.encoder.config.cpr = 120
2 Likes