Vibrations when trying to control velocity of motor

Hi, I am trying to control a BLDC motor with the ODrive Pro. The motor is the following:
24V 84W 350RPM Geared Brushless DC Motor 1.89Nm 10:1 - 57BLR50-24-01-HG10 | StepperOnline
The configurations I’m using in the GUI for the motor are:

odrv = odrv0
odrv.config.dc_bus_overvoltage_trip_level = 25
odrv.config.dc_bus_undervoltage_trip_level = 10.5
odrv.config.dc_max_positive_current = 4
odrv.config.dc_max_negative_current = -math.inf
odrv.axis0.config.motor.motor_type = MotorType.HIGH_CURRENT
odrv.axis0.config.motor.pole_pairs = 2
odrv.axis0.config.motor.torque_constant = 0.0567098676541178
odrv.axis0.config.motor.current_soft_max = 5
odrv.axis0.config.motor.current_hard_max = 16.5
odrv.axis0.config.motor.calibration_current = 3.5
odrv.axis0.config.motor.resistance_calib_max_voltage = 10
odrv.axis0.config.calibration_lockin.current = 3.5
odrv.axis0.motor.motor_thermistor.config.enabled = False
odrv.axis0.controller.config.control_mode = ControlMode.VELOCITY_CONTROL
odrv.axis0.controller.config.input_mode = InputMode.VEL_RAMP
odrv.axis0.controller.config.vel_limit = 50
odrv.axis0.controller.config.vel_limit_tolerance = 1.16
odrv.axis0.config.torque_soft_min = -math.inf
odrv.axis0.config.torque_soft_max = math.inf
odrv.axis0.trap_traj.config.accel_limit = 100
odrv.axis0.controller.config.vel_ramp_rate = 100
odrv.can.config.protocol = Protocol.NONE
odrv.axis0.config.enable_watchdog = False
odrv.axis0.config.encoder_bandwidth = 100
odrv.hall_encoder0.config.enabled = True
odrv.axis0.config.load_encoder = EncoderId.HALL_ENCODER0
odrv.axis0.config.commutation_encoder = EncoderId.HALL_ENCODER0
odrv.config.enable_uart_a = False

When I go through the calibration process, the rotor vibrates a bit while rotating (idk if this is normal), when I check the Dashboard, the position and velocity are noiseless and they seem to give proper values when I move manually the rotor. When I turn on the Velocity Control Mode in the Dashboard, the current measurements are a bit noisy (±0.1A), but the measured position and velocity stay constant as long as the velocity setpoint remains equals to zero. When I try to give a low setpoint of velocity (e.g., 2 rev/s), the rotor rotates but with very high vibrations (See pic.)


As you can see, I tried just using just a velocity gain with zero integral term still giving the same behavior (with k_v = 0.01 the rotor doesn’t move, with 0.02 it moves slowly but very choppy).
Do you have ideas on what can be causing this behavior? Thanks in advance.

Hi,

Thanks for posting the config, this helps a lot!

I think this is an intrinsic issue of using hall sensors – they’re so low resolution that there’s just mathematically not enough fidelity in the velocity data for the ODrive to work with, so you need to really turn down your velocity gains – especially for small motors like these. I’d try keeping your vel gain at that 0.1 figure and then try slowly increasing the velocity integrator gain.

We generally recommend only using torque control with hall-based motors for this reason; if you need low speed velocity control, I’d strongly recommend adding an incremental encoder to your motor, and configuring that as the load encoder – that’ll give the ODrive some much-needed high-res velocity data, and is also great for dealing with gearbox backlash (if you add the encoder to the gearbox output).

Thanks a lot for your response!

I managed to find a low enough set of gains that minimize the choppiness at low speeds, though I still have cogging from 0 to ~7rev/s; this is with the integrated three-phase hall effect sensors in the motor. I will now try to use the magnetic encoder included in the ODrive Pro board together with the anti-cogging calibration.

I need to have the ability to control at low speeds as I am giving as reference to the board trapezoidal velocity profiles.

Can you confirm that the only way to do the anti-cogging calibration is through the odrivetool (i.e., not though the GUI) ?

You can do it in the GUI – the inspector tab has feature parity with ODrivetool. You just need to use the search bar for the relevant properties – e.g. axis0.requested_state, etc etc

You absolutely need a higher resolution encoder than the hall sensors for anticogging (it’s not mathematically possible w/ hall sensors), and note that you need the higher-res encoder to be directly on the motor – can’t be on the gearbox shaft unfortunately.

All this being said, when you say “cogging”, I’m guessing it’s not actually what we’d consider cogging torque (e.g. caused by passive iron-magnet interactions in the motor, compensated for by anticogging) – I think unless you’re trying to do some extremely smooth/precise low speed control (in which case anticogging would be helpful), this is sounding like an issue that’s just fundamentally driven by the hall sensors’ low resolution.

I can understand why with 3-phase hall effect sensors it won’t work due to low resolution, but this shouldn’t be the case with the integrated magnetic encoder on the board (MA702), which detects the absolute angular position of the magnet and if I’m not wrong outputs a signal of 12 bits, so it should have a similar resolution of an optical encoder of 4095 PPR, right? (assuming the board’s ADC is also 12 bits).

Here are the velocity profiles I need the motor to follow and the estimated velocity using the internal magnetic encoder of the ODrive Pro (these are the tuned gains for this motor: 0.01 vel_gain, 0.05 vel_integral_gain):

Reference 1:


Estimated velocity 1:

Reference 2:


Estimated velocity 2:

Note: I changed the encoder bandwidth from 1000 to 200 because it was too noisy the vel_estimate.

From these figures, isn’t it cogging what is making the controller be unable to follow the profiles at low speed? (dwells at low speeds, start of incremental ramp, end of decreasing ramp)

It’s all digital, but yes exactly.

Here are the velocity profiles I need the motor to follow and the estimated velocity using the internal magnetic encoder of the ODrive Pro (these are the tuned gains for this motor: 0.01 vel_gain, 0.05 vel_integral_gain):

Note: I changed the encoder bandwidth from 1000 to 200 because it was too noisy the vel_estimate.

From these figures, isn’t it cogging what is making the controller be unable to follow the profiles at low speed? (dwells at low speeds, start of incremental ramp, end of decreasing ramp)

Probably static friction, unless that’s a crazy high cogging torque motor. I’d definitely increase the encoder bandwidth back up to 1000. What does onboard_encoder0.get_field_strength() return? And can you share your whole config?