Motor Windup in Sensorless Velocity Mode


I am attenpting to drive a 20-A motor in sensorless velocity control mode. In order to get the motors to output the torque I need for my system, I had to set the current_setpoint parameter to 100 which keeps the motor from stalling. However, in doing so, after exiting the ramp-up state the motor will spin up, exceeding the target velocity before slowing down again.

I have adjusted the motor current and velocity PI parameters:
Current_I: No change, motor stalls at lower load
Current_P:No change
Veloc_P: Increasing this parameter would reduce the amount of windup, however the motor does not run properly if this value exceeds .15 (It vibrates, makes a loud noise, and heats up)
Veloc_I: Increasing this value reduced the amount of time it takes for the motor to reach its target speed after the windup. I increased by a factor of 10 from .1->1

Here is my setup code:
odrv0.axis0.controller.config.control_mode = CTRL_MODE_VELOCITY_CONTROL
odrv0.axis0.sensorless_estimator.config.pm_flux_linkage = 5.51328895422 / (POLEPAIRS * MOTORKV) #Constants defined above

odrv0.axis0.controller.vel_ramp_target = 500
odrv0.axis0.controller.vel_ramp_enable = True
odrv0.axis0.config.startup_motor_calibration = True

odrv0.axis0.config.spin_up_acceleration = 1000
odrv0.axis0.config.ramp_up_time = .1
odrv0.axis0.controller.current_setpoint = 20
odrv0.axis0.config.spin_up_target_vel = 200
odrv0.axis0.config.spin_up_current = 20
odrv0.axis0.motor.config.current_lim = 27

odrv0.axis0.motor.current_control.p_gain = .015 #.015
odrv0.axis0.motor.current_control.i_gain = 102 #102
odrv0.axis0.controller.config.vel_gain = 0.1 #0.1
odrv0.axis0.controller.config.vel_integrator_gain = 1 #0.1 

odrv0.axis0.requested_state = AXIS_STATE_IDLE
odrv0.axis0.requested_state = AXIS_STATE_SENSORLESS_CONTROL

Is there another tuning parameter I may be missing? I need the current setpoint to be high, else the motor will stall at too low a load, but the windup is its own control issue.



What type of load is it? Is it mostly mass or is there a lot of friction/drag also? It seems you want to spool it up very quickly is that the case?



The motors are for a drivetrain. I want the motors to ramp up from rest to a set velocity while being able to carry the load of the vehicle. I have three ODrive 3.5s operating six NeuMotor 1907 3Ys to move a 50 KG vehicle.
When I do not set the value "“controller.current_setpoint” the drives stall out before moving the system. When I set the value of “controller.current_setpoint” to 100* the motor has enough torque to move the system, but when going from the ramp-up state to the open-loop-velocity state the motor will jump from its spin_up_target_vel to a speed past the vel_ramp_target before resolving to the vel_ramp_target. This puts a lot of strain on the gearboxes and is non-ideal for short-distance control of the vehicle, so I’m trying to eliminate that overshoot.

*(This is done in a library I wrote for the TM4C129 launchpad in Energia which comunicates serially to the drives)

Thank you for your quick reply.



What is <odrv>.<axis>.config.lockin.current set to? You should set it to 20A and then current_setpoint to 0. If that doesn’t work, then you can either:

  1. Increase lockin current until you have enough that it doesn’t stall
  2. Reduce the lockin acceleration


I have not set ..config.lockin.current, so it would be set to its default value. I am out of the shop for the week and wont be able to test until Saturday, but I’ll certainly give this a try.

Can you explain what the lockin parameters do?



There is no parameter ..config.lockin



That is in the new (as of now unreleased) firmware version.
You probably have it as odrv0.axis0.config.spin_up_current.



I had the spin_up_current and current_setpoint both set to 20.

when I set spin_up_current to 20 and current_setpoint to 0, the motor would spin up just fine and not overshoot, but would not have enough torque to move under a load. It would spin up, but then immediately stall.

Adjusting the spin_up_current only changes the motor acceleration in the spin_up state. Once it exits that state, the motor overshoots.

I believe the issue is caused by the current_setpoint parameter engaging immediately following the spinup. I have tried to adjust the motor.current_control PI parameters and saw no difference in operation. I wrote a current rampup function in my external controller to slowly ramp up the current_setpoint after the drive is enabled to mitigate the overshoot while allowing full current to be quickly delivered to the drive. That seems to work alright but there is still a bit of overshoot, and setting the current setpoint lower would mean the drive initially has less torque. That may be the best I can get using sensorless control though.



I would suggest not changing the current_control.p/i_gain, instead you should set the motor.config.current_control_bandwidth, it will update the current control gains for you.

Here is my recommendation, start by leaving:

motor.config.current_control_bandwidth = 100

You can try to turn it up a little bit later if you need faster response.

Then play with


I would suggest to leave current_setpoint at 0, since otherwise you may get issues at steady-state.

If all that still stalls it out, you can try this feature branch, where I have added an inertia term to the ramped velocity mode (see here). You set it at controller.config.inertia with units of A/(counts/s^2). You can set that value to the amps you seem to need to accelerate, divided by your vel_ramp_rate.