Disabling sensorless spinup

Hi everybody,

I am currently working with ODrive on Windows 10, with the SENSORLESS mode and with current control.
I would like to skip the calibration procedure so that the motors don’t move each time I switch the power ON. How can I do that ?

Moreover, I might have a problem with my ST Link. The make flash works well, and if I switch the power ON the calibration works even when the ST Link is not connected (since the flash had allready been done). But if I try to send a command via USB, I have this error when the ST Link is not connected:

usb.core.USBError: [Errno None] b’libusb0-dll:err [clear_halt] could not clear halt, ep 0x01, win error: A device attached to the system is not functioning.\r\n’

If I send a command after the make flash while the ST Link is still connected everything works fine.

Any ideas ?

Do you mean the motion “move a little one way, then back again”. That is the encoder calibration that shouldn’t run in sensorless. The resistance and inductance measurement beep shouldn’t move the motor much.

Do you have the 5V or 3.3V line connected on the ST link? Please do not connect that if you are powering the main power input: try the main power input only, then flash like that.

Thank you for your answer!

About the motor calibration:

No I only had some forward movements. Those movements came from the call to this function “spin_up_sensorless()” in the axis.cpp file.

Here is the diff file showing up the modification I made compared to the ODrive fw v.0.3.5-rc branch in order to skip the motors movements during the calibration:

diff --git a/Firmware/MotorControl/axis.cpp b/Firmware/MotorControl/axis.cpp
index bd00091..dd09006 100644
--- a/Firmware/MotorControl/axis.cpp
+++ b/Firmware/MotorControl/axis.cpp
@@ -40,6 +40,7 @@ Axis::Axis(const AxisConfig& config, uint8_t axis_number, Moto                                                                                                                                                                                               r_t* legacy_motor_
     : axis_number_(axis_number),
       enable_control_(config.enable_control_at_start),
       do_calibration_(config.do_calibration_at_start),
+      enable_spin_at_sensorless_calibration_(config.enable_spin_at_sensorless_c                                                                                                                                                                                               :...skipping...

diff --git a/Firmware/MotorControl/axis.cpp b/Firmware/MotorControl/axis.cpp
index bd00091..dd09006 100644
--- a/Firmware/MotorControl/axis.cpp
+++ b/Firmware/MotorControl/axis.cpp
@@ -40,6 +40,7 @@ Axis::Axis(const AxisConfig& config, uint8_t axis_number, Motor_t* legacy_motor_
     : axis_number_(axis_number),
       enable_control_(config.enable_control_at_start),
       do_calibration_(config.do_calibration_at_start),
+      enable_spin_at_sensorless_calibration_(config.enable_spin_at_sensorless_calibration),
       legacy_motor_ref_(legacy_motor_ref) {
     SetupLegacyMappings();
 }
@@ -77,7 +78,7 @@ void Axis::StateMachineLoop() {
             __HAL_TIM_MOE_ENABLE(legacy_motor_ref_->motor_timer);

             bool spin_up_ok = true;
-            if (legacy_motor_ref_->rotor_mode == ROTOR_MODE_SENSORLESS)
+            if (legacy_motor_ref_->rotor_mode == ROTOR_MODE_SENSORLESS && enable_spin_at_sensorless_calibration_)
                 spin_up_ok = spin_up_sensorless(legacy_motor_ref_);
             if (spin_up_ok)
                 control_motor_loop(legacy_motor_ref_);
diff --git a/Firmware/MotorControl/axis.h b/Firmware/MotorControl/axis.h
index b3cdf54..7a60643 100644
--- a/Firmware/MotorControl/axis.h
+++ b/Firmware/MotorControl/axis.h
@@ -13,6 +13,7 @@ extern "C" {
 // TODO: decide if we want to consolidate all default configs in one file for ease of use?
 struct AxisConfig {
     bool enable_control_at_start = true;
+    bool enable_spin_at_sensorless_calibration = false;
     bool do_calibration_at_start = true;
 };

@@ -49,6 +50,7 @@ public:

     bool enable_control_;
     bool do_calibration_;
+    bool enable_spin_at_sensorless_calibration_;

     Motor_t* legacy_motor_ref_;

About the ST Link :

I have the 3.3V line connected on the ST Link, and I disconnected it while using the main power input.
But again, if after the flash I disconnect the ST Link, the same error as before appears.
If it is only for the flash, why do I have an error when I disconnect it ?
Does the ST link have to be connected all the time ?

So spin_up_sensorless is not a calibration, it is a starting routine to get the motor up to speed before enabling senorless because sensorless only works when spinning at a minimum speed. This means that you cannot use sensorless at standstill, the motor must be spinning before you can use it.

I don’t think 3.3V should ever have to be connected, I never connect it. It would seem that it’s possibly the case that your computer’s GND is being tied to the ODrive GND through the STLink, and the ODrive’s USB cable’s GND signal is broken?

Hi,

Thank you for your answer.

I tried your suggestion about the ST Link but that doesn’t seem to be the problem.
Here are my steps :

  • ST Link connected both on computer and on card, I flash, everything works fine, I can control the motors
  • ST Link connected to the computer but not to the card (disconnected pins and connected usb), I can control the motors
  • ST Link disconnected (both from motor and computer), I can’t control my motors

So it seems that the computer just needs to be connected to the ST Link …

Another question, do you have an API for cpp (so that I can send commands in cpp instead of python)?

Thanks in advance!

There’s no STLink related code involved in the regular ODrive communication, so this issue seems rather strange.

What’s the reproduction rate of the error if you repeat the same actions three times or so?
Does the ODrive show up in the Windows Device Manager at the time of the error?
Does the error persist after rebooting everything (ODrive and PC)?

As for the C++ API, there’s unfortunately none available yet. In the near-to-mid-term future there will be another protocol overhaul and a C++ API along with it but until then there are two options:

The error always happen when repeating the same actions and persists after reboot. And the ODrive shows up in the Windows Device Manager at the time of the error.

So I installed a clean version of all the ODrive firmware on linux ubuntu this time, with the original code of the master branch everything worked fine even with the ST Link disconnected from the computer.

Then I made the changes for the current control mode and the sensorless mode:

diff --git a/Firmware/Board/v3.3/Inc/main.h b/Firmware/Board/v3.3/Inc/main.h
index b7dbdb5..855396e 100644
--- a/Firmware/Board/v3.3/Inc/main.h
+++ b/Firmware/Board/v3.3/Inc/main.h
@@ -53,7 +53,7 @@
 /* USER CODE BEGIN Includes */
 
 #define HW_VERSION_MAJOR 3
-#define HW_VERSION_MINOR 4
+#define HW_VERSION_MINOR 3
 // #define HW_VERSION_HIGH_VOLTAGE true
 
 #if HW_VERSION_MAJOR == 3 && HW_VERSION_MINOR == 1 \
diff --git a/Firmware/MotorControl/low_level.c b/Firmware/MotorControl/low_level.c
index 4b4a096..2a24477 100644
--- a/Firmware/MotorControl/low_level.c
+++ b/Firmware/MotorControl/low_level.c
@@ -55,7 +55,7 @@ const float elec_rad_per_enc = POLE_PAIRS * 2 * M_PI * (1.0f / (float)ENCODER_CP
 Motor_t motors[] = {
     {
         // M0
-        .control_mode = CTRL_MODE_POSITION_CONTROL,  //see: Motor_control_mode_t
+        .control_mode = CTRL_MODE_CURRENT_CONTROL,  //see: Motor_control_mode_t
         .enable_step_dir = false,                    //auto enabled after calibration
         .counts_per_step = 2.0f,
         .error = ERROR_NO_ERROR,
@@ -118,9 +118,9 @@ Motor_t motors[] = {
             .Iq_measured = 0.0f,
             .max_allowed_current = 0.0f,
         },
-        // .rotor_mode = ROTOR_MODE_SENSORLESS,
+        .rotor_mode = ROTOR_MODE_SENSORLESS,
         // .rotor_mode = ROTOR_MODE_RUN_ENCODER_TEST_SENSORLESS,
-        .rotor_mode = ROTOR_MODE_ENCODER,
+        //.rotor_mode = ROTOR_MODE_ENCODER,
         .encoder = {
             .encoder_timer = &htim3,
             .use_index = false,
@@ -165,7 +165,7 @@ Motor_t motors[] = {
         },
     },
     {                                             // M1
-        .control_mode = CTRL_MODE_POSITION_CONTROL,  //see: Motor_control_mode_t
+        .control_mode = CTRL_MODE_CURRENT_CONTROL,  //see: Motor_control_mode_t
         .enable_step_dir = false,                    //auto enabled after calibration
         .counts_per_step = 2.0f,
         .error = ERROR_NO_ERROR,
@@ -224,7 +224,7 @@ Motor_t motors[] = {
             .Iq_measured = 0.0f,
             .max_allowed_current = 0.0f,
         },
-        .rotor_mode = ROTOR_MODE_ENCODER,
+        .rotor_mode = ROTOR_MODE_SENSORLESS,
         .encoder = {
             .encoder_timer = &htim4,
             .use_index = false,

And with those changes I have the same error as before when I try my 3 steps:

So this forces me to have the ST Link connected if I want to use the ODrive.

Please let me know if there is a fix for that, otherwise I’ll just continue that way.
Thanks again!

Hmm this is very strange and we have no good explanation. The parameters you changed should not have any influence on the USB operation.

So at this point I can only suggest some general things you could try (if you didn’t already):

  • change around USB ports
  • try without a hub in case you’re using one
  • try a different/shorter microUSB cable for the ODrive
  • try on a completely different computer (you said you switched the OS but I’m not sure if this is on the same computer)