Sensorless mode

A new ODrive feature is ready for testing: Sensorless mode. This mode lets you run motors without and enocder. To do this we sacrifice two things: reduced accuracy as compared to an optical encoder, and lack of precise control at low speeds.

On the accuracy side, very preliminary results on this seems to indicate around 0.5 degrees 1-sigma error on my 7 pole pair motor.
On the low speed control: The minimum speed that supports good control is not yet established, but it will depend on the kv of the motor (rpm/v), and will probably be established in volts. My guess is that we could go down to around 500mV (so about 135 RPM for a 270 kv motor).
The other thing to consider is that we need to spin the motor up to the minimum controllable speed. Right now this is done by using an open-loop current that spins up with a fixed acceleration, with no feedback on the rotor position. That is, we simply hope that we don’t lose the rotor as it get’s pulled up to speed by the current vector. The startup current, acceleration, and the target speed for enabling closed loop are all configurable.
There will be a mechanism to check that we think we managed to get the rotor up to speed, and that the closed loop is working, so we can fail or start over if we lost the rotor on our way up to full speed. This mechanism will consist of checking that the velocity tracking PLL is reporting a speed that matches the final speed we hope the rotor to be in by the time we wish to enable sensorless closed loop control. This mechanism is not implemented yet.

The open-loop startup speed-ramp followed by switching to closed loop FOC velocity control is demonstrated in this video:

Instructions

The feature is available on the branches sensorless for ODrive v3.3 and up, and on sensorless-b4-v3.3 for ODrive v3.2 and earlier.

Note that position control is not available in this mode, and that the tuning parameters that used to have units of counts/s (reffering to encoder counts/s), now have rad/s, reffering to radians per second electrical. Note that electrical frequency = mechanical frequency / pole pairs.

For example, to get my motor to spin at 500 RPM, and it has 14 magnets in the rotor (so 7 pole pairs), I would set the velocity setpoint to 500/60 * 2 * pi * 7 = 366.5 rad/s electrical. Similarly, if previously I had my machine well-tuned with a 2400CPR encoder, and the velocity gain was x [A/(count/s)], it would now be x*7*2*pi/(2400) [A/(rad/s)].

Four new parameters must be set:

  • motor.sensorless.pm_flux_linkage: this should be set to 5.51328895422 / (<pole pairs> * <rpm/v>). The <rpm/v> is the kv of the motor.
  • motor.sensorless.spinup_current: motor current during spinup, in amps.
  • motor.sensorless.spin_up_acceleration: acceleration (slope) of the spin-up velocity ramp, in rad/s^2 electrical.
  • motor.sensorless.spin_up_target_vel: the speed at the end of the velocity spin-up ramp, where we switch over to sensorless closed loop. In rad/s electrical.
2 Likes

Becuase I did not recive my encoder yet I want to try sensorless controll.
Where is the sensorless branch?

The sensorless branch has been merged a long time ago.
You can follow along how to run sensorless in the other active thread about it.

Hey, I’ve been doing sensorless control recently, but it didn’t work. The motor can be calibrated normally. I also input some commands and found that it can’t run. What shall I do? My firmware version is 0.4.7 and my hardware version is 0.34. I can’t use the remote control to control the motor 0. Did I miss any commands or did I make a mistake?
Motor config:
odrv0.axis0.motor.config.pole_pairs = 7 odrv0.axis0.motor.config.resistance_calib_max_voltage = 4 odrv0.axis0.motor.config.requested_current_range = 25 odrv0.save_configuration() odrv0.reboot() odrv0.axis0.motor.config.current_control_bandwidth = 100 odrv0.axis0.controller.config.pos_gain = 1 odrv0.axis0.controller.config.vel_gain = 0.02 odrv0.axis0.controller.config.vel_integrator_gain = 0.1 odrv0.axis0.controller.config.vel_limit = 1000 odrv0.save_configuration() odrv0.reboot() odrv0.axis0.requested_state = AXIS_STATE_MOTOR_CALIBRATION odrv0.axis0.motor odrv0.axis0.motor.config.pre_calibrated = True
Four new parameters must be set:
odrv0.axis0.sensorless_estimator.config.pm_flux_linkage = 5.51328895422/(7*190) odrv0.axis0.config.spin_up_current = 10.0
odrv0.axis0.config.spin_up_acceleration = 1000.0
odrv0.axis0.config.spin_up_target_vel = 1000.0
Control motor 0 with GPIO4
odrv0.config.gpio4_pwm_mapping.min = -200 odrv0.config.gpio4_pwm_mapping.max = 200 odrv0.config.gpio4_pwm_mapping.endpoint = odrv0.axis0.controller._remote_attributes['vel_setpoint']
odrv0.save_configuration()
odrv0.reboot()
Control the wheel:
odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL

You should be setting the requested_state to AXIS_STATE_SENSORLESS_CONTROL, not AXIS_STATE_CLOSED_LOOP_CONTROL.

I changed it according to your method, but it only rotated for a while and then stopped. What should I do?

To be honest I ran into the same issue with the ODrive and also with another sensorless controller from TI. I think sensorless control is just super finicky.

The motor stopped because the controller ran into an error, which may be solvable. For example if it was overspeed, you can increase the speed limit.

To find out, check axis0.error. Then if it’s 0x40 you check axis0.motor.error for a more specific motor error, and respectively for 0x80 axis0.sensorless_estimator.error, 0x100 axis0.encoder.error, 0x200 axis0.controller.error.

2 Likes

%E6%8D%95%E8%8E%B71 !
%E6%8D%95%E8%8E%B72


TIM%E5%9B%BE%E7%89%8720190111104909
As you can see, axis is 0x400 and motor is 0x0010. But I don’t know how to deal with it.

What is axis0.controller.config.control_mode? Based on the wording of error 0x0400 and the setup example here I think sensorless control only works in velocity control mode (2).

Oh, thank you. You‘re rignt. I seem to have taken another step forward. Now I can use senseless control, but there are still problems that remain unsolved. This is my command line:
Motor configuration:
odrv0.axis0.controller.config.vel_gain = 0.02 odrv0.axis0.controller.config.vel_integrator_gain = 0.05 odrv0.axis0.controller.config.control_mode = 2
odrv0.axis0.controller.vel_setpoint = 400
odrv0.axis0.sensorless_estimator.config.pm_flux_linkage = 5.51328895422/(7*190)
odrv0.axis0.config.spin_up_current = 10.0
odrv0.axis0.config.spin_up_acceleration = 1000.0
odrv0.axis0.config.spin_up_target_vel = 1000.0
odrv0.save_configuration()
odrv0.reboot()

odrv0.axis0.requested_state = AXIS_STATE_MOTOR_CALIBRATION
odrv0.axis0.motor
odrv0.axis0.motor.config.pre_calibrated = True
odrv0.config.gpio4_pwm_mapping.min = -200
odrv0.config.gpio4_pwm_mapping.max = 200
odrv0.config.gpio4_pwm_mapping.endpoint = odrv0.axis0.controller._remote_attributes['vel_setpoint']
odrv0.save_configuration()
odrv0.reboot()
odrv0.axis0.requested_state = AXIS_STATE_SENSORLESS_CONTROL
odrv0.axis0.config.startup_sensorless_control = True
odrv0.save_configuration()
odrv0.reboot()
But I still have some problems.

  1. Every time I use the command odrv0.axis0.requested_state = AXIS_STATE_SENSORLESS_CONTROL, the motor will automatically rotate and stop. I can control the motor with the remote control after stopping. Is there any way I can directly control the motor after using this command odrv0.axis0.requested_state = AXIS_STATE_SENSORLESS_CONTROL instead of waiting for the motor to automatically rotate.
  2. Every time I use the remote control to control for a period of time, then do not use the remote control for more than ten seconds, then control the remote control, the motor sometimes appears to rotate very slowly. I have to control it for a while to get back to normal motor control
  3. Sometimes it can’t be controlled after booting, and sometimes it can be used. I feel very strange

Continuing the discussion from Sensorless mode:


i want do sensorless control together with pwm
How can I do?
I tired them:

In [2]: odrv0.config.enable_uart = False

In [3]: odrv0.axis0.config.enable_step_dir=False

In [4]: odrv0.axis0.controller.config.vel_limit_tolerance=0

In [5]: odrv0.config.gpio4_pwm_mapping.endpoint = odrv0.axis0.controller._remote_attributes[‘vel_setpoint’]

In [6]: odrv0.config.gpio4_pwm_mapping.max = 4096

In [7]: odrv0.axis0.controller.config.vel_gain = 0.01

In [8]: odrv0.axis0.controller.config.vel_integrator_gain = 0.05

In [9]: odrv0.axis0.controller.config.control_mode = 2

In [10]: odrv0.axis0.sensorless_estimator.config.pm_flux_linkage = 5.51328895422 / (7 * 1000)

In [11]: odrv0.axis0.motor.config.direction = 1

In [12]: odrv0.axis0.config.lockin.current=5

In [13]: odrv0.axis0.controller.vel_setpoint=odrv0.axis0.config.lockin.vel=100

In [14]: odrv0.save_configuration()

In [15]: odrv0.reboot()

In [16]: odrv0.axis0.requested_state = AXIS_STATE_MOTOR_CALIBRATION

In [17]: odrv0.axis0.motor.config.pre_calibrated = True

In [18]: odrv0.save_configuration()

In [19]: odrv0.reboot()

That all looks good, what is the problem?
You need to start sensorless mode with
odrv0.axis0.requested_state = AXIS_STATE_SENSORLESS_CONTROL

I want to do pwm control but the system is just running sensorless. I can’t control system

Hi the Odrive i received from my supplier does not recognize the commands “spinup_current”, “spin_up_acceleration” and “spin_up_target_vel”.

Maybe its an older version although i did order and receive it last week, 18 August 2023. Without configuring these commands i tried to do sensorless but it wont work.

During initial motor calibration sequence the shaft would move a few degrees and stop. The dump errors command would reveal an error with the axis. What do you suggest i do?

Hi Kumayl - which ODrive are you using? v3.6, S1, or Pro?