Hi ! I am Attempting to use ODrive controller with a Hoverboard motor. The Hoverboard Motor is rated 350W at 36V. I am currently using the 56V ODrive controller. I am able to operate the motors via the controller when I use the Hoverboard Motors hall effect sensor. However, due to the hall effect sensor being of low resolution, I purchased an incremental rotary encoder with 2500 ppr. (https://robu.in/product/orange-2500ppr-abz-phase-incremental-optical-rotary-encoder/) I have connected the encoder to a 70mm dia wheel which is driven by a timing belt drive connected to a flange of dia 105mm on the hoverboard motor. I carried out the FULL_AXIS_CALIBRATION and AXIS_MOTOR_CALIBRATION. There was no problem with this step. However, when I set the requested state to CLOSED_LOOP_CONTROL, The motor spins suddenly and stops. Upon checking the errors, I get the following error : ERROR_CURRENT_LIMIT_VIOLATION. How do i fix this error ?
So… what is the ratio between the ODrive and the encoder? Also, I assume you have
encoder.config.cpr = 10000
FULL_AXIS_CALIBRATION and AXIS_MOTOR_CALIBRATION.
Just do the FULL_AXIS_CALIBRATION then check
The ratio would be 1.5.
I set the encoder.cpr = 15000.
Also I did FULL_AXIS_CALIBRATION only and it shows no errors.
I still get the CURRENT_LIMIT_VIOLATION error
Sorry, don’t know! You’re going to have to give us more information. Graphs, data, video, procedures, etc.
Okay so I have done the following
I have used the Orange Rotary Encoder for feedback.
The resolution of the encoder is 2500 ppr which is 10000 cpr.
The following image shows the setup
The following image shows the connections of the Encoder to the ODrive board
Based on the image showed in the setup, it can be seen that the gear ratio is 105mm/70mm = 1.5, which implies that the encoder cpr = 1.5 * 10000 cpr = 15000 cpr
Thus the parameter odrv0.axis0.encoder.config.cpr = 15000
The next step I performed was to set the motor parameters. For this I followed the guide for Hoverboard motors provided by ODrive
The next Step I set the Encoder paramters
In : odrv0.axis0.encoder.config.cpr = 15000
Finally, I have set the controller parameters
In : odrv0.axis0.controller.config.vel_gain = 0.9303750395774841 In : odrv0.axis0.controller.config.vel_integrator_gain = 4.6518754959106445 In : odrv0.axis0.controller.config.vel_limit = 10 In : odrv0.axis0.controller.config.control_mode = CONTROL_MODE_VELOCITY_CONTROL
I have then Performed motor calibration after saving the configuration and rebooting
These were the results of the calibration
error = 0x0000 (int)
phase_inductance = 0.00039534387178719044 (float)
phase_resistance = 0.20221738517284393 (float)
I then have performed Encoder calibration
In : odrv0.axis0.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION
The motor rotated in both directions and i got no errors when I ran the command dump_errors(odrv0)
These were the encoder values
error = 0x0000 (int) is_ready = True (bool) index_found = False (bool) shadow_count = -241 (int) count_in_cpr = 14759 (int) interpolation = 0.5 (float) phase = -0.14742207527160645 (float) pos_estimate = -0.016051040962338448 (float) pos_estimate_counts = -240.765625 (float) pos_cpr = 0.9839489459991455 (float) pos_cpr_counts = 14759.234375 (float) pos_circular = 0.983941912651062 (float) hall_state = 3 (int) vel_estimate = 0.0 (float) vel_estimate_counts = 0.0 (float) calib_scan_response = 7921.0 (float) pos_abs = 0 (int) spi_error_rate = 0.0 (float) config: mode = 0 (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 = 15000 (int) offset = -4217 (int) pre_calibrated = False (bool) offset_float = -0.0363125205039978 (float) enable_phase_interpolation = True (bool) bandwidth = 1000.0 (float) calib_range = 0.019999999552965164 (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)
I have saved the configuration and rebooted the odrive.
I have then attempted to run the ODrive in CLOSED_LOOP_CONTROL mode by giving the following commands
In : odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL
odrv0.axis0.controller.input_vel = 2
At this Point the Motor suddenly rotates and then stops. When I check errors I see the CURRENT_LIMIT_VIOLATION error
Do let me know if more information is required.
Those encoders on long timing belts (which look slack!) will give even worse feedback than Hall sensors.
Maybe you could mount a SPI magnetic encoder on the opposite bar, in line with the axis of the motor?
Yeah I’m with @towen on this one. Those encoder belts need to be nice and tight if you want any hope of this working. And rather than just going by diameter, make sure you’re using the tooth count ratio.
@Wetmelon , @towen
So I have improved the mechanical fitting. I did tighten the belts and i see no slippage when I turn the hoverboard motor.
I have also improved my setup a bit. Got some ferrite cores to shield of the noise and EMI. GOt the capacitive filters (47nF) for both axes.
Now what i did was reconfigure the Odrive and configured the motor and encoder as stated in the first post of the thread here.
When I perform AXIS_ENCODER_OFFSET_CALIBRATION, I dont see any errors.
now, when I try and run the motor in CLOSED_LOOP_CONTROL mode, and when i set the velocity for the motor, I dont see any errors but the motors do not move at all.
However, when closed loop control was set, and when i try to rotate the motor, i do feel the resistance of the motor against my rotation.
What could be happening here ?
Sounds like it might be working!
Probably, it is in position control mode, not velocity control. Set controller.config.control_mode=CONTROL_MODE_VELOCITY_CONTROL if you want velocity, or try setting controller.input_pos to move to another position if you stay in position mode.
You have yet to tune the gains, so until then it will feel very spongy, as the default gains are designed to be ‘safe’
I have mode some changes to my setup.
I used a GT2 timing pulley. The timing pulley has a pitch of 2mm. I have also used a different pulley as suggested. The meshing with that pulley mounted on the encoder shaft is better that the earlier setup shown in the images above.
The setup now is shown in the image below.
the front side of the encoder is shown in the image below
based on the setup. the gear ratio now is 1:8.35
the pulley on the encoder has 20 teeth, the number of teeth on the hub motor is 167.
I did the necessary configuations
My Encoder configuration is as follows
error = 0x0000 (int)
is_ready = False (bool)
index_found = False (bool)
shadow_count = 5 (int)
count_in_cpr = 5 (int)
interpolation = 0.5 (float)
phase = -2.4740355014801025 (float)
pos_estimate = 6.886239862069488e-05 (float)
pos_estimate_counts = 5.750010013580322 (float)
pos_cpr = 6.886228220537305e-05 (float)
pos_cpr_counts = 5.750000476837158 (float)
pos_circular = 0.9998509287834167 (float)
hall_state = 1 (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)
mode = 0 (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 = 83500 (int)
offset = -25636 (int)
pre_calibrated = False (bool)
offset_float = 0.06751561164855957 (float)
enable_phase_interpolation = True (bool)
bandwidth = 1000.0 (float)
calib_range = 0.05000000074505806 (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)
Motor configuration is as follows
error = 0x0000 (int)
armed_state = 0 (int)
is_calibrated = True (bool)
current_meas_phB = -0.09500789642333984 (float)
current_meas_phC = 0.11590272188186646 (float)
DC_calib_phB = -1.1943212747573853 (float)
DC_calib_phC = -0.47860780358314514 (float)
phase_current_rev_gain = 0.012500000186264515 (float)
effective_current_lim = 10.0 (float)
p_gain = 0.03970155864953995 (float)
i_gain = 21.65802001953125 (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 = 30.375 (float)
overcurrent_trip_level = 33.75 (float)
acim_rotor_flux = 0.0 (float)
async_phase_vel = 0.0 (float)
async_phase_offset = 0.0 (float)
drv_fault = 0 (int)
general = 27676 (int)
adc_cb_i = 2610 (int)
adc_cb_dc = 12842 (int)
meas_r = 49966 (int)
meas_l = 15673 (int)
enc_calib = 41786 (int)
idx_search = 54226 (int)
foc_voltage = 27138 (int)
foc_current = 55033 (int)
spi_start = 62887 (int)
sample_now = 34524 (int)
spi_end = 33205 (int)
pre_calibrated = True (bool)
pole_pairs = 15 (int)
calibration_current = 10.0 (float)
resistance_calib_max_voltage = 4.0 (float)
phase_inductance = 0.0003970155958086252 (float)
phase_resistance = 0.21658019721508026 (float)
torque_constant = 0.5168750286102295 (float)
direction = -1 (int)
motor_type = 0 (int)
current_lim = 10.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 = 25.0 (float)
current_control_bandwidth = 100.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)
the controller config is as follows
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)
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 = 1 (int)
pos_gain = 20.0 (float)
vel_gain = 0.10000000149011612 (float)
vel_integrator_gain = 0.3333333432674408 (float)
vel_limit = 10.0 (float)
vel_limit_tolerance = 1.2000000476837158 (float)
vel_ramp_rate = 1.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)
move_incremental(displacement: float, from_input_pos: bool)
The ENCODER_OFFSET_CALIBRATION is successful.
However my motor does not Run when I try out the CLOSED_LOOP_CONTROL_MODE.
I give a input_vel and still the motor does not rotate as required.
What is get is some abnormal behavior where the motor turns in one direction and violently oscillates.
How do I fix this issue ?
This is extremely concerning.
Here is a video of the motor behavior. I requested the motor a
Thanks in advance!