At this point in time I am at a loss of what is going wrong with ODrive and my motor. No matter what I have done I am getting ERROR_CURRENT_UNSTABLE when trying to operate in closed loop velocity control with my motor. The weird thing is that with 0.4.12 firmware I can run in sensorless mode and as long as my acceleration is not too high I can get up to well over 35000 RPM. With closed loop control I am lucky to get above 10k. With 0.5.1 firmware I can not get above 14000 RPM and simply cannot run closed loop. At first @madcowswe and @Wetmelon suggested that the motor’s back EMF was to blame. This is what that waveform looks like on an Oscilloscope though and running at around 19000 RPM though:
This looks very sinusoidal to me. The next thing to rule out was the Hall Sensors themselves. Perhaps they were giving a weird signal. This is what those look like on a scope though:
Hall A and B:
Hall A and Z:
Both of those seem to be working just fine. The last thing suggested was that the motor’s inductance was possibly too low so I soldered three of these in line with the phases:
https://www.digikey.com/product-detail/en/bourns-inc/PQ2617BHA-220K/PQ2617BHA-220K-ND/
That did make it so that on the 0.4.12 firmware I could run at a bit higher acceleration without getting ERROR_CURRENT_UNSTABLE, but it did not help with closed loop control. At this point I am out of ideas and well outside my level of knowledge on motors. @Wetmelon suggested that there could be an error in the hall code affecting this, but this is not something I can debug due to my lack of knowledge on brushless motor theory.
Here is my 0.5.1 config:
In [1]: odrv0.axis0
Out[1]:
error = 0x0100 (int)
step_dir_active = False (bool)
current_state = 1 (int)
requested_state = 0 (int)
loop_counter = 484246 (int)
lockin_state = 0 (int)
is_homed = False (bool)
config:
startup_motor_calibration = False (bool)
startup_encoder_index_search = False (bool)
startup_encoder_offset_calibration = False (bool)
startup_closed_loop_control = False (bool)
startup_sensorless_control = False (bool)
startup_homing = False (bool)
enable_step_dir = False (bool)
step_dir_always_on = False (bool)
turns_per_step = 0.0009765625 (float)
watchdog_timeout = 0.0 (float)
enable_watchdog = False (bool)
step_gpio_pin = 1 (int)
dir_gpio_pin = 2 (int)
calibration_lockin: ...
sensorless_ramp: ...
general_lockin: ...
can_node_id = 0 (int)
can_node_id_extended = False (bool)
can_heartbeat_rate_ms = 100 (int)
fet_thermistor:
error = 0x0000 (int)
temperature = 25.999391555786133 (float)
config: ...
motor_thermistor:
error = 0x0000 (int)
temperature = 0.0 (float)
config: ...
motor:
error = 0x0000 (int)
armed_state = 0 (int)
is_calibrated = True (bool)
current_meas_phB = -0.15174412727355957 (float)
current_meas_phC = 0.03545680642127991 (float)
DC_calib_phB = -0.7747852206230164 (float)
DC_calib_phC = -0.4790705740451813 (float)
phase_current_rev_gain = 0.02500000037252903 (float)
effective_current_lim = 10.0 (float)
current_control: ...
gate_driver: ...
timing_log: ...
config: ...
controller:
error = 0x0000 (int)
input_pos = 0.0 (float)
input_vel = 0.0 (float)
input_torque = 0.0 (float)
pos_setpoint = 0.0 (float)
vel_setpoint = 0.0 (float)
torque_setpoint = 0.0 (float)
trajectory_done = True (bool)
vel_integrator_torque = 0.0 (float)
anticogging_valid = False (bool)
config: ...
move_incremental(displacement: float, from_input_pos: bool)
start_anticogging_calibration()
encoder:
error = 0x0010 (int)
is_ready = False (bool)
index_found = False (bool)
shadow_count = 0 (int)
count_in_cpr = 0 (int)
interpolation = 0.0 (float)
phase = 0.0 (float)
pos_estimate = 0.0 (float)
pos_estimate_counts = 0.0 (float)
pos_cpr = 0.0 (float)
pos_cpr_counts = 0.0 (float)
pos_circular = 0.0 (float)
hall_state = 7 (int)
vel_estimate = 0.0 (float)
vel_estimate_counts = 0.0 (float)
calib_scan_response = 0.0 (float)
pos_abs = 0 (int)
spi_error_rate = 0.0 (float)
config: ...
set_linear_count(count: int)
sensorless_estimator:
error = 0x0000 (int)
phase = -0.006432728376239538 (float)
pll_pos = -0.005587339401245117 (float)
vel_estimate = -0.17820142209529877 (float)
config: ...
trap_traj:
config: ...
min_endstop:
endstop_state = False (bool)
config: ...
max_endstop:
endstop_state = False (bool)
config: ...
watchdog_feed()
clear_errors()
In [2]: odrv0.axis0.motor
Out[2]:
error = 0x0000 (int)
armed_state = 0 (int)
is_calibrated = True (bool)
current_meas_phB = 0.2098262906074524 (float)
current_meas_phC = 0.1917402446269989 (float)
DC_calib_phB = -0.7738049030303955 (float)
DC_calib_phC = -0.4736144542694092 (float)
phase_current_rev_gain = 0.02500000037252903 (float)
effective_current_lim = 10.0 (float)
current_control:
p_gain = 0.0326908677816391 (float)
i_gain = 35.110958099365234 (float)
v_current_control_integral_d = 0.0 (float)
v_current_control_integral_q = 0.0 (float)
Ibus = 0.0 (float)
final_v_alpha = 0.0 (float)
final_v_beta = 0.0 (float)
Id_setpoint = 0.0 (float)
Iq_setpoint = 0.0 (float)
Iq_measured = 0.0 (float)
Id_measured = 0.0 (float)
I_measured_report_filter_k = 1.0 (float)
max_allowed_current = 60.75 (float)
overcurrent_trip_level = 67.5 (float)
acim_rotor_flux = 0.0 (float)
async_phase_vel = 0.0 (float)
async_phase_offset = 0.0 (float)
gate_driver:
drv_fault = 0 (int)
timing_log:
general = 12786 (int)
adc_cb_i = 2954 (int)
adc_cb_dc = 12846 (int)
meas_r = 1254 (int)
meas_l = 22111 (int)
enc_calib = 15916 (int)
idx_search = 10114 (int)
foc_voltage = 26988 (int)
foc_current = 62703 (int)
spi_start = 54814 (int)
sample_now = 38212 (int)
spi_end = 30942 (int)
config:
pre_calibrated = True (bool)
pole_pairs = 2 (int)
calibration_current = 20.0 (float)
resistance_calib_max_voltage = 2.0 (float)
phase_inductance = 3.269086664658971e-05 (float)
phase_resistance = 0.0351109579205513 (float)
torque_constant = 0.03999999910593033 (float)
direction = 1 (int)
motor_type = 0 (int)
current_lim = 20.0 (float)
current_lim_margin = 8.0 (float)
torque_lim = inf (float)
inverter_temp_limit_lower = 100.0 (float)
inverter_temp_limit_upper = 120.0 (float)
requested_current_range = 60.0 (float)
current_control_bandwidth = 1000.0 (float)
acim_slip_velocity = 14.706000328063965 (float)
acim_gain_min_flux = 10.0 (float)
acim_autoflux_min_Id = 10.0 (float)
acim_autoflux_enable = False (bool)
acim_autoflux_attack_gain = 10.0 (float)
acim_autoflux_decay_gain = 1.0 (float)
In [3]: odrv0.axis0.controller
Out[3]:
error = 0x0000 (int)
input_pos = 0.0 (float)
input_vel = 0.0 (float)
input_torque = 0.0 (float)
pos_setpoint = 0.0 (float)
vel_setpoint = 0.0 (float)
torque_setpoint = 0.0 (float)
trajectory_done = True (bool)
vel_integrator_torque = 0.0 (float)
anticogging_valid = False (bool)
config:
gain_scheduling_width = 10.0 (float)
enable_vel_limit = True (bool)
enable_current_mode_vel_limit = True (bool)
enable_gain_scheduling = False (bool)
enable_overspeed_error = True (bool)
control_mode = 2 (int)
input_mode = 2 (int)
pos_gain = 1.0 (float)
vel_gain = 0.019999999552965164 (float)
vel_integrator_gain = 0.10000000149011612 (float)
vel_limit = 35000.0 (float)
vel_limit_tolerance = 1.2000000476837158 (float)
vel_ramp_rate = 2000.0 (float)
torque_ramp_rate = 0.009999999776482582 (float)
circular_setpoints = False (bool)
circular_setpoint_range = 1.0 (float)
homing_speed = 0.25 (float)
inertia = 0.0 (float)
axis_to_mirror = 255 (int)
mirror_ratio = 1.0 (float)
load_encoder_axis = 0 (int)
input_filter_bandwidth = 2.0 (float)
anticogging: ...
move_incremental(displacement: float, from_input_pos: bool)
start_anticogging_calibration()
In [4]: odrv0.axis0.encoder
Out[4]:
error = 0x0010 (int)
is_ready = False (bool)
index_found = False (bool)
shadow_count = 0 (int)
count_in_cpr = 0 (int)
interpolation = 0.0 (float)
phase = 0.0 (float)
pos_estimate = 0.0 (float)
pos_estimate_counts = 0.0 (float)
pos_cpr = 0.0 (float)
pos_cpr_counts = 0.0 (float)
pos_circular = 0.0 (float)
hall_state = 7 (int)
vel_estimate = 0.0 (float)
vel_estimate_counts = 0.0 (float)
calib_scan_response = 0.0 (float)
pos_abs = 0 (int)
spi_error_rate = 0.0 (float)
config:
mode = 1 (int)
use_index = False (bool)
find_idx_on_lockin_only = False (bool)
abs_spi_cs_gpio_pin = 1 (int)
zero_count_on_find_idx = True (bool)
cpr = 12 (int)
offset = 33 (int)
pre_calibrated = False (bool)
offset_float = 0.5141406059265137 (float)
enable_phase_interpolation = True (bool)
bandwidth = 100.0 (float)
calib_range = 0.02500000037252903 (float)
calib_scan_distance = 50.26548385620117 (float)
calib_scan_omega = 12.566370964050293 (float)
idx_search_unidirectional = False (bool)
ignore_illegal_hall_state = False (bool)
sincos_gpio_pin_sin = 3 (int)
sincos_gpio_pin_cos = 4 (int)
set_linear_count(count: int)
Any further help with this would be greatly appreciated.