Troubleshooting sensorless mode

Hi, I’m running some BLDC motors (1kW running at around 20V) sensorlessly with an ODrive v5.6. The motors are part of a mowing system and they have blades attached to them (one motor has larger blades attached than the other).

I’ve followed ODrive’s guide as well as other forum posts to get my motors running, and I have them sort of running, but not reliably. Here are the issues I’m facing:

  1. Half the time during ramp-up the motor seems to “miss” the ODrive’s commutation and starts to spin in the wrong direction at a very low speed. This problem is avoided if I give the blades attached to the rotor an initial push in the correct direction, but obviously this isn’t a realistic solution for production. How can I fix this?

  2. When I first setup the controller I was getting the MOTOR_ERROR_DC_BUS_OVER_REGEN_CURRENT error (note that I am not using a brake resistor), which I solved by fiddling with the dc_mac_negative_current and max_regen_current parameters. I had to set both of them very high (greater than abs(150)) for the ramp up to succeed without cutting out. 150A seems like a rediculous number to me - are these numbers to be expected?

  3. When I try to run the motor with the larger blade connected, I can’t get it to ramp up to the speed I want no matter how much I raide the parameters listed in ^2. I’d like to have sensorless_ramp.vel reach 1500, but the most I can reliably achieve is 500 before the power cuts off due to some setting. Increasing motor.config.requested_current_range and motor.config.current_lim seemed to help somewhat (not sure if one or both had an effect).


Errors:

There are the errors I’m seeing when trying to run the motor with the larger blades:

dump_errors(odrv0)
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: Error(s):
    MOTOR_ERROR_CURRENT_SENSE_SATURATION
    MOTOR_ERROR_CURRENT_LIMIT_VIOLATION
    MOTOR_ERROR_UNKNOWN_CURRENT_MEASUREMENT
  sensorless_estimator: no error
  encoder: no error
  controller: no error

General config

In [122]: odrv0.axis1.config
Out[122]: 
calibration_lockin:
  accel: 20.0 (float)
  current: 10.0 (float)
  ramp_distance: 3.1415927410125732 (float)
  ramp_time: 0.4000000059604645 (float)
  vel: 40.0 (float)
can:
  encoder_rate_ms: 10 (uint32)
  heartbeat_rate_ms: 100 (uint32)
  is_extended: False (bool)
  node_id: 1 (uint32)
dir_gpio_pin: 8 (uint16)
enable_sensorless_mode: True (bool)
enable_step_dir: False (bool)
enable_watchdog: False (bool)
general_lockin:
  accel: 20.0 (float)
  current: 10.0 (float)
  finish_distance: 100.0 (float)
  finish_on_distance: False (bool)
  finish_on_enc_idx: False (bool)
  finish_on_vel: False (bool)
  ramp_distance: 3.1415927410125732 (float)
  ramp_time: 0.4000000059604645 (float)
  vel: 40.0 (float)
sensorless_ramp:
  accel: 200.0 (float)
  current: 10.0 (float)
  finish_distance: 100.0 (float)
  finish_on_distance: False (bool)
  finish_on_enc_idx: False (bool)
  finish_on_vel: True (bool)
  ramp_distance: 3.1415927410125732 (float)
  ramp_time: 0.4000000059604645 (float)
  vel: 800.0 (float)
startup_closed_loop_control: False (bool)
startup_encoder_index_search: False (bool)
startup_encoder_offset_calibration: False (bool)
startup_homing: False (bool)
startup_motor_calibration: False (bool)
step_dir_always_on: False (bool)
step_gpio_pin: 7 (uint16)
watchdog_timeout: 0.0 (float)

Controller config

In [124]: odrv0.axis1.controller.config
Out[124]: 
anticogging:
  anticogging_enabled: True (bool)
  calib_anticogging: False (bool)
  calib_pos_threshold: 1.0 (float)
  calib_vel_threshold: 1.0 (float)
  cogging_ratio: 1.0 (float)
  index: 0 (uint32)
  pre_calibrated: False (bool)
axis_to_mirror: 255 (uint8)
circular_setpoint_range: 1.0 (float)
circular_setpoints: False (bool)
control_mode: 2 (uint8)
electrical_power_bandwidth: 20.0 (float)
enable_gain_scheduling: False (bool)
enable_overspeed_error: True (bool)
enable_torque_mode_vel_limit: True (bool)
enable_vel_limit: True (bool)
gain_scheduling_width: 10.0 (float)
homing_speed: 0.25 (float)
inertia: 0.0 (float)
input_filter_bandwidth: 2.0 (float)
input_mode: 1 (uint8)
load_encoder_axis: 1 (uint8)
mechanical_power_bandwidth: 20.0 (float)
mirror_ratio: 1.0 (float)
pos_gain: 20.0 (float)
spinout_electrical_power_threshold: 10.0 (float)
spinout_mechanical_power_threshold: -10.0 (float)
steps_per_circular_range: 1024 (int32)
torque_mirror_ratio: 0.0 (float)
torque_ramp_rate: 0.009999999776482582 (float)
vel_gain: 0.009999999776482582 (float)
vel_integrator_gain: 0.05000000074505806 (float)
vel_integrator_limit: inf (float)
vel_limit: 1000.0 (float)
vel_limit_tolerance: 1.2000000476837158 (float)
vel_ramp_rate: 1.0 (float)

Motor config

In [123]: odrv0.axis1.motor.config
Out[123]: 
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: 1000.0 (float)
current_lim: 100.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: 2.147314080502838e-05 (float)
phase_resistance: 0.024812055751681328 (float)
pole_pairs: 7 (int32)
pre_calibrated: False (bool)
requested_current_range: 60.0 (float)
resistance_calib_max_voltage: 2.0 (float)
torque_constant: 0.03999999910593033 (float)
torque_lim: inf (float)

Happy to provide any additional info!
Thanks in advance.

Hi @abrown

  1. Increase the sensorless ramp lockin current, and decrease the lockin velocity ramp rate.
  2. No. Try setting the max_regen_current to 0, then the dc_max_negative_current to something your battery can support (maybe -20 or so?)
  3. Ah, this is just the current controller going unstable instead of the motor running in reverse a bit. Same fix as #1.

Thanks! I’ll try these things in the shop tomorrow and report back.

What is the ramp locking current?

axis.config.sensorless_ramp.current, etc.

Hi. I tried what you suggested and still facing the same / similar problems.

  1. Increasing <axis>.config.sensorless_ramp.current (currently at 30) and decreasing <axis>.controller.config.vel_ramp_rate doesn’t seem to have affected the problem of the motor turning the wrong direction slowly at spin up.

  2. I set the parameters to the values you suggested and the power to the motor is still cutting off before it reaches velocity (I can hear a faint “click” almost like a relay). Perhaps worth noting that if I set <axis>.config.sensorless_ramp.vel to a low speed (like 200) and then slowly raise it while repeatedly setting <axis>.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL I can eventually reach the desired velocity. Obviously when ramping up from speed 0 the current draw is going to be much higher, so I would expect your advice re: point 1. to help smooth this out… maybe there’s something else at play here.

Would appreciate further input. Happy to provide video or any other info you’d like.

Would appreciate further support.

Edit: I tried a different power source and the problem of the motor’s cutting out after ramping up seems to have disappeared. Not quite sure what’s going on there - but for the moment they’re working OK.

1 Like