BLDC Hub motor is not running with oDrive Controller

@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