TIMING_ERROR during anti-cogging calibration

Hi! I’m trying to run the anti-cogging calibration sequence on my ODrive Pro board, as I need to get trapezoidal velocity profiles on the motor I’m driving, and just by tuning the velocity gains doesn’t get rid of this problem. The configuration I’m using is the following:ù

odrv0.config.dc_bus_overvoltage_trip_level = 28
odrv0.config.dc_bus_undervoltage_trip_level = 10.5
odrv0.config.dc_max_positive_current = 4
odrv0.config.dc_max_negative_current = -100000
odrv0.axis0.config.motor.motor_type = MotorType.HIGH_CURRENT
odrv0.axis0.config.motor.pole_pairs = 2
odrv0.axis0.config.motor.torque_constant = 0.0567098676541178
odrv0.axis0.config.motor.current_soft_max = 5
odrv0.axis0.config.motor.current_hard_max = 16.5
odrv0.axis0.config.motor.calibration_current = 2
odrv0.axis0.config.motor.resistance_calib_max_voltage = 10
odrv0.axis0.config.calibration_lockin.current = 2
odrv0.axis0.motor.motor_thermistor.config.enabled = False
odrv0.axis0.controller.config.control_mode = ControlMode.VELOCITY_CONTROL
odrv0.axis0.controller.config.input_mode = InputMode.PASSTHROUGH
odrv0.axis0.controller.config.vel_limit = 50
odrv0.axis0.controller.config.vel_limit_tolerance = 1.16
odrv0.axis0.config.torque_soft_min = -100000
odrv0.axis0.config.torque_soft_max = 100000
odrv0.can.config.protocol = Protocol.NONE
odrv0.axis0.config.enable_watchdog = False
odrv0.axis0.config.load_encoder = EncoderId.ONBOARD_ENCODER0
odrv0.axis0.config.commutation_encoder = EncoderId.ONBOARD_ENCODER0
odrv0.config.enable_uart_a = False
odrv0.axis0.config.encoder_bandwidth = 200
odrv0.axis0.controller.config.pos_gain = 20
odrv0.axis0.controller.config.vel_gain = 0.01
odrv0.axis0.controller.config.vel_integrator_gain = 0.05

When I try to run the anti-cogging calibration with the recommended parameters for other motors:
odrv0.axis0.controller.config.vel_gain = 0.8
odrv0.axis0.config.anticogging.max_torque = 0.4
odrv0.axis0.config.anticogging.calib_start_vel = 0.5
odrv0.axis0.config.anticogging.calib_end_vel = 0.05
odrv0.axis0.config.anticogging.calib_coarse_integrator_gain = 25

The rotor starts to vibrate a lot, so I went back to my previous vel_gain = 0.01 and increased the calib_start_vel to 5. With this it starts running fine but after a second the board disarms and dumps the following error:

axis0
active_errors: no error
disarm_reason: Error(s):
ODriveError.TIMING_ERROR
procedure_result: ProcedureResult.DISARMED
last_drv_fault: none
internal issues: 64
details for bug report: [(135270404, 2767, 0, 0), (135270404, 2779, 0, 0), (135270404, 2767, 0, 0), (135270404, 2779, 0, 0), (135270404, 2767, 0, 0), (135270404, 2779, 0, 0), (135270404, 2767, 0, 0), (135270404, 2779, 0, 0), (135270404, 2767, 0, 0), (135270404, 2779, 0, 0), (135270404, 2767, 0, 0), (135270404, 2779, 0, 0), (135270404, 2767, 0, 0), (135270404, 2779, 0, 0), (135270404, 2767, 0, 0), (135270404, 2779, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0), (135270404, 2767, 0, 0)]

Do you know how should I tweak the anticogging calibration parameters to avoid running into this or other errors? Thanks in advance!

Can you show how the ODrive’s mounted, and how the encoder magnet is attached to the motor’s shaft?

Sure, here are some pictures



I carefully glued the magnet in the end of the rotor shaft after a plastic spacer using centering collars to ensure the axis alignment. With this setup, the distance between the face of the magnet and the face of the magnetic encoder is 0.7mm, which is within the recommended distance in the documentation.

Note: this was the only way to attach the magnet, as the back face of the rotor shaft is flush with the bearing attached to the housing, so no space for a regular mounting adapter.

Can you give me some information about in which cases TIMING_ERROR is produced in the ODrive Pro?

Yeah honestly this is really impressive :stuck_out_tongue_winking_eye: no comments on magnet mounting or anything. Nice work, and I appreciate the ferrules.

TIMING_ERROR should really never be produced – this is only if a critical aspect of one of the internal loops hangs, and we have more than enough processing power for everything. I think this is the first one I’ve seen all year, so congrats.

You’re on 0.6.9-1, newest firmware is 0.6.10, would appreciate if you could give updating firmware a shot and then see if you can reproduce this. I’ll also ping our firmware guy on this; worst comes to worst, would you be open to sending us the motor+magnet+heatspreader setup for a few days so we can hook up a debugger on our side?

Thanks for the comments!

Maybe there’s something I am missing during the whole setup sequence?

This is the complete sequence I’m doing:

odrv0.erase_configuration()

odrv0.config.dc_bus_overvoltage_trip_level = 28
odrv0.config.dc_bus_undervoltage_trip_level = 10.5
odrv0.config.dc_max_positive_current = 4
odrv0.config.dc_max_negative_current = -100000
odrv0.axis0.config.motor.motor_type = MotorType.HIGH_CURRENT
odrv0.axis0.config.motor.pole_pairs = 2
odrv0.axis0.config.motor.torque_constant = 0.0567098676541178
odrv0.axis0.config.motor.current_soft_max = 5
odrv0.axis0.config.motor.current_hard_max = 16.5
odrv0.axis0.config.motor.calibration_current = 2
odrv0.axis0.config.motor.resistance_calib_max_voltage = 10
odrv0.axis0.config.calibration_lockin.current = 2
odrv0.axis0.motor.motor_thermistor.config.enabled = False
odrv0.axis0.controller.config.control_mode = ControlMode.VELOCITY_CONTROL
odrv0.axis0.controller.config.input_mode = InputMode.PASSTHROUGH
odrv0.axis0.controller.config.vel_limit = 50
odrv0.axis0.controller.config.vel_limit_tolerance = 1.16
odrv0.axis0.config.torque_soft_min = -100000
odrv0.axis0.config.torque_soft_max = 100000
odrv0.can.config.protocol = Protocol.NONE
odrv0.axis0.config.enable_watchdog = False
odrv0.axis0.config.load_encoder = EncoderId.ONBOARD_ENCODER0
odrv0.axis0.config.commutation_encoder = EncoderId.ONBOARD_ENCODER0
odrv0.config.enable_uart_a = False
odrv0.axis0.config.encoder_bandwidth = 200
odrv0.axis0.controller.config.pos_gain = 20
odrv0.axis0.controller.config.vel_gain = 0.01
odrv0.axis0.controller.config.vel_integrator_gain = 0.05

odrv0.save_configuration()

odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE

odrv0.axis0.controller.config.absolute_setpoints = True
odrv0.axis0.pos_estimate = odrv0.onboard_encoder0.raw

odrv0.axis0.controller.config.control_mode = CONTROL_MODE_POSITION_CONTROL
odrv0.axis0.controller.config.input_mode = INPUT_MODE_PASSTHROUGH
odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL

odrv0.axis0.config.anticogging.max_torque = 1
odrv0.axis0.config.anticogging.calib_start_vel = 5
odrv0.axis0.config.anticogging.calib_end_vel = 0.05
odrv0.axis0.config.anticogging.calib_coarse_integrator_gain = 25

odrv0.axis0.requested_state = AxisState.ANTICOGGING_CALIBRATION

dump_errors(odrv0,clear=True)

Returning:

axis0
  active_errors: no error
  disarm_reason: Error(s):
    ODriveError.TIMING_ERROR
  procedure_result: ProcedureResult.DISARMED
  last_drv_fault: none
internal issues: 8
details for bug report: [(135270404, 2767, 0, 0), (135270404, 2779, 0, 0), (135270404, 2767, 0, 0), (135270404, 2779, 0, 0), (135270404, 2767, 0, 0), (135270404, 2779, 0, 0), (135270404, 2767, 0, 0), (135270404, 2779, 0, 0)]

Are there already cases where the anti-cogging calibration works with the integrated magnetic encoder?

I will try updating the firmware and try the sequence again. I don’t think its viable to send you the parts as my company is based in Italy haha, and we need this for testing one of our machines. Worst case scenario we will have to accept the choppiness at low speeds, but this is far from ideal, as it would make the rest of the equipment not work as intended. Should I give it a try with another ODrive Pro board? we have a couple more, but I guess as we got them all together they share the same firmware.

Hi - checked in, looks like TIMING_ERROR is actually something new (no wonder I didn’t recognize it!) and caused by the motor velocity being too high. So definitely try the calib_start_vel back down at 0.5, and try to find a higher but still stable vel_gain. One thing to note is you set your encoder bandwidth to 200 – a value of 1000 is fine with the onboard encoder, and will help allow for maintaining stability at higher vel_gains .

Worst case scenario we will have to accept the choppiness at low speeds, but this is far from ideal, as it would make the rest of the equipment not work as intended. Should I give it a try with another ODrive Pro board? we have a couple more, but I guess as we got them all together they share the same firmware.

This is definitely not the best response you can get. Shoot me an email at solomon.greenberg@odriverobotics.com and we can chat hopping on a call or something, if you’d like.