Realized motor current << current_lim setting

I’m attempting to perform a simple calibration of my ODrive system in torque control mode, measuring the difference between the requested and measured torque by determining a “torque offset” value (e.g. odrv0.axis0.controller.input_torque = T_request + T_offset) that enables the motor to suspend a known weight off of a pulley at 0 RPM.

Above a certain input_torque value, the system current (per both Iq_setpoint and Iq_measured) is limited to precisely 25A, despite my current_limit being set to 60A (I’ve made sure to save and reboot the controller after changing that limit).

I’ve tried changing requested_current_range up to 80A out of curiosity, no change in the behavior.

Could this be a thermal issue? The system doesn’t throw errors, and it also happens independently of how long I’ve had the system energized.

Any insight is greatly appreciated, I’m stumped. Hardware and configuration settings follow.

Hardware:
ODrive v3.6 controller, 56V version
single ODrive D5065 270KV motor running through a 20:1 reduction planetary gearbox
Power supply: 24V, max 41.7A / 1000W

Controller/firmware settings (dumping a bunch here, in case I’m missing something)
Settings under odrv0.axis0.config:
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: 0 (uint32)
dir_gpio_pin: 2 (uint16)
enable_sensorless_mode: False (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: 400.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: 1 (uint16)
watchdog_timeout: 0.0 (float)

Settings in odrv0.axis0.motor:
	DC_calib_phA: 0.22347372770309448 (float)
	DC_calib_phB: -0.3492250442504883 (float)
	DC_calib_phC: 0.1259220540523529 (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: 1000.0 (float)
	  current_lim: 60.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: 1.6069736375357024e-05 (float)
	  phase_resistance: 0.052728693932294846 (float)
	  pole_pairs: 7 (int32)
	  pre_calibrated: False (bool)
	  requested_current_range: 80.0 (float)
	  resistance_calib_max_voltage: 2.0 (float)
	  torque_constant: 0.03999999910593033 (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: 52.72869110107422 (float)
	  p_gain: 0.01606973633170128 (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_phA: -0.22057965397834778 (float)
	current_meas_phB: 0.3485667407512665 (float)
	current_meas_phC: -0.12793013453483582 (float)
	effective_current_lim: 60.0 (float)
	error: 0 (uint64)
	fet_thermistor:
	  config: ...
	  temperature: 30.631746292114258 (float)
	is_armed: False (bool)
	is_calibrated: False (bool)
	last_error_time: 0.0 (float)
	max_allowed_current: 121.5 (float)
	max_dc_calib: 12.15000057220459 (float)
	motor_thermistor:
	  config: ...
	  temperature: 0.0 (float)
	n_evt_current_measurement: 1619158 (uint32)
	n_evt_pwm_update: 1619161 (uint32)
	phase_current_rev_gain: 0.05000000074505806 (float)
	
     Settings in odrv0.axis0.controller:
	anticogging_valid: False (bool)
	autotuning:
	  frequency: 0.0 (float)
	  pos_amplitude: 0.0 (float)
	  torque_amplitude: 0.0 (float)
	  vel_amplitude: 0.0 (float)
	autotuning_phase: 0.0 (float)
	config:
	  anticogging: ...
	  axis_to_mirror: 255 (uint8)
	  circular_setpoint_range: 1.0 (float)
	  circular_setpoints: True (bool)
	  control_mode: 1 (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: 0 (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.10000000149011612 (float)
	  vel_integrator_gain: 0.0 (float)
	  vel_integrator_limit: inf (float)
	  vel_limit: 10.0 (float)
	  vel_limit_tolerance: 1.2000000476837158 (float)
	  vel_ramp_rate: 1.0 (float)
	electrical_power: 0.0 (float)
	error: 0 (uint8)
	input_pos: 0.0 (float)
	input_torque: 0.0 (float)
	input_vel: 0.0 (float)
	last_error_time: 0.0 (float)
	mechanical_power: 0.0 (float)
	move_incremental(obj: object_ref, displacement: float, from_input_pos: bool)
	pos_setpoint: 0.0 (float)
	start_anticogging_calibration(obj: object_ref)
	torque_setpoint: 0.0 (float)
	trajectory_done: True (bool)
	vel_integrator_torque: 0.0 (float)
            vel_setpoint: 0.0 (float)

Check the setting for odrv0.config.dc_max_positive_current ?

Thanks.

The value for odrv0.config.dc_max_positive_current is “inf”

Did a bit more testing… when moving (e.g. I forcibly back-drive the pulley) the controller provides >25A, up to ~35A in this test. The current limit appears to be when the motor is stationary.

I notice you have vel_integrator_gain set to 0 - can you increase that to 0.01 ?

You read the torque control docs, and made sure to set vel_gain appropriately, or set enable_torque_mode_vel_limit to False, right?

https://docs.odriverobotics.com/v/0.5.4/control-modes.html#torque-control