I’m pretty new to working with ODrive and recently I’ve run into a issue that I’ve been struggling to solve. I have been trying to drive a cart with two BLDC hoverboard style wheels (120 cpr) at 0.2 rev/s. I’ve been able to get the wheels to spin very consistently at 0.2 rev/s when there is no load on them in velocity control mode. However, when trying to actually drive the cart and with load on the wheels, I’ve found that both wheels start by spinning faster than 0.2 rev/s (around 0.25 rev/s), but after a few seconds will drop down to about 0.1 rev/s. This lasts for a few seconds before they speed back up to 0.25 rev/s. The motors continually oscillate between overshooting and undershooting the desired speed. Additionally, when I run dump_errors()
, it shows no errors in either axis.
My first thought was that this was probably a tuning issue. I tried both changing vel_gain
and vel_integrator_gain
to a variety of values. I found that this did affect the behavior, but did not fix it. Changing these values either made the wheels start rapidly vibrating during the period it was slowing down or make the cart stop entirely instead of just slowing down. I’ve tried changing some other values as well, such as the bandwidth of the encoder or the current limit, but did not see improvement. I’m guessing this is a problem with either how I am configuring the encoder or the controller since the problem is so consistent, but I’m unsure what exactly is wrong.
While trying to find the origin of this problem I was printing out the vel_estimate
and vel_estimate_counts
from the encoder, while additionally doing my own calculations for the velocity using the difference in shadow_count
each second. I did notice that the vel_estimate
was always a good bit larger than what I determined in my calculations. When testing the wheels at 0.2 rev/s without load, my calculation would consistently read out 0.2, where as vel_estimate
fluctuated between 0.25 and 0.3 rev/s. This could possibly be completely unrelated to the aforementioned problem, but I figured that is was worth mentioning as it seemed peculiar.
I am leaving my configuration settings for the motor, the encoder, and the controller below to try to make sure all relevant information is available. My configuration for axis0 and axis1 are identical. Any help would be greatly appreciated. Thanks!
Motor Settings
DC_calib_phA: 0.4081537127494812 (float)
DC_calib_phB: -0.17754331231117249 (float)
DC_calib_phC: -0.23056994378566742 (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: 40.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.0002825653937179595 (float)
phase_resistance: 0.20705918967723846 (float)
pole_pairs: 20 (int32)
pre_calibrated: True (bool)
requested_current_range: 60.0 (float)
resistance_calib_max_voltage: 4.0 (float)
torque_constant: 0.2977199852466583 (float)
torque_lim: inf (float)
current_control:
I_measured_report_filter_k: 1.0 (float)
Ialpha_measured: -6.474801063537598 (float)
Ibeta_measured: -7.8197174072265625 (float)
Id_measured: 10.063177108764648 (float)
Id_setpoint: 10.0 (float)
Iq_measured: 1.342167615890503 (float)
Iq_setpoint: 0.0 (float)
Vd_setpoint: 0.0 (float)
Vq_setpoint: 0.0 (float)
final_v_alpha: -1.6940659284591675 (float)
final_v_beta: -1.6403868198394775 (float)
i_gain: 20.70591926574707 (float)
p_gain: 0.02825653925538063 (float)
phase: 1.3816916942596436 (float)
phase_vel: 40.0 (float)
power: 35.665802001953125 (float)
v_current_control_integral_d: 2.3594958782196045 (float)
v_current_control_integral_q: 0.07132841646671295 (float)
current_meas_phA: -0.40825068950653076 (float)
current_meas_phB: 0.1785786896944046 (float)
current_meas_phC: 0.23011401295661926 (float)
effective_current_lim: 40.0 (float)
error: 0 (uint64)
fet_thermistor:
config: ...
temperature: 31.258031845092773 (float)
is_armed: False (bool)
is_calibrated: True (bool)
last_error_time: 0.0 (float)
max_allowed_current: 60.75 (float)
max_dc_calib: 6.075000286102295 (float)
motor_thermistor:
config: ...
temperature: 0.0 (float)
n_evt_current_measurement: 28053287 (uint32)
n_evt_pwm_update: 28053297 (uint32)
phase_current_rev_gain: 0.02500000037252903 (float)
Encoder Settings
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: 120 (int32)
direction: 1 (int32)
enable_phase_interpolation: True (bool)
find_idx_on_lockin_only: False (bool)
hall_polarity: 0 (uint8)
hall_polarity_calibrated: True (bool)
ignore_illegal_hall_state: False (bool)
index_offset: 0.0 (float)
mode: 1 (uint16)
phase_offset: 78 (int32)
phase_offset_float: 1.447070598602295 (float)
pre_calibrated: True (bool)
sincos_gpio_pin_cos: 4 (uint16)
sincos_gpio_pin_sin: 3 (uint16)
use_index: True (bool)
use_index_offset: True (bool)
count_in_cpr: 0 (int32)
delta_pos_cpr_counts: -5.605193857299268e-45 (float)
error: 0 (uint16)
hall_state: 1 (uint8)
index_found: True (bool)
interpolation: 0.5 (float)
is_ready: True (bool)
phase: -0.9917759895324707 (float)
pos_abs: 0 (int32)
pos_circular: 0.01625862345099449 (float)
pos_cpr_counts: 0.9750081300735474 (float)
pos_estimate: 0.008328811265528202 (float)
pos_estimate_counts: 0.9994573593139648 (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)
Controller Settings
anticogging_valid: False (bool)
autotuning:
frequency: 0.0 (float)
pos_amplitude: 0.0 (float)
pos_phase: 0.0 (float)
torque_amplitude: 0.0 (float)
torque_phase: 0.0 (float)
vel_amplitude: 0.0 (float)
vel_phase: 0.0 (float)
config:
anticogging: ...
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_current_mode_vel_limit: True (bool)
enable_gain_scheduling: False (bool)
enable_overspeed_error: 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: 1.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: 2.0 (float)
vel_integrator_gain: 5.0 (float)
vel_limit: 10.0 (float)
vel_limit_tolerance: 1.2000000476837158 (float)
vel_ramp_rate: 1.0 (float)
electrical_power: 3.6536953449249268 (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)