Saving the index location

I have my encoder index pulse working but it appears that I get a different offset from the AXIS_STATE_ENCODER_OFFSET_CALIBRATION after resetting the board…

Here’s what I’m doing…

  1. standard getting started procedure
  2. motor works as expected
  3. set use index to true
  4. search for the index…works
  5. check the encoder offset…
  6. run the AXIS_STATE_ENCODER_OFFSET_CALIBRATION and it matches what i had after searching the index
  7. set encoder.config.pre_calibrated = True
  8. double check that all numbers look good
  9. save and reboot
  10. motor auto finds index at start and the offset number matches what I had previously…
  11. do another AXIS_STATE_ENCODER_OFFSET_CALIBRATION and the number is different

:confused:

Two other pieces of data…

If I start from scratch with a fresh config I see this result…After the full startup sequence I have an offset value…the index search will match this initial value. If I then run an additional encoder offset I get a different value. I’ve notionally checked that I’m getting 40,000 counts by comparing the position estimates in subsequent index searches…I’m always close to 40,000 but not exact. Maybe I’m losing counts.

What is your encoder cpr and how many motor pole pairs?
Check that encoder.index_found is true before running the offset calibration.
Can you give us two (or more) offsets that it found?

CPR = 40,000
Poles = 7

I will gather additional offsets tonight and report back.

Here is my screen dump from a fresh configuration…7 poles, 10,000PPR set as 40,000CPR.

At line 28, after a reboot the motor successfully found the index…when I went to “closed loop” it took off full blast.

Connected to ODrive 206137883548 as odrv0
In [1]: odrv0.axis0
Out[1]:
error = 0x0000 (int)
enable_step_dir = False (bool)
current_state = 1 (int)
requested_state = 0 (int)
loop_counter = 388502 (int)
config:
  startup_motor_calibration = False (bool)
  startup_encoder_index_search = False (bool)
  startup_encoder_offset_calibration = False (bool)
  startup_closed_loop_control = False (bool)
  startup_sensorless_control = False (bool)
  enable_step_dir = False (bool)
  counts_per_step = 2.0 (float)
  ramp_up_time = 0.4000000059604645 (float)
  ramp_up_distance = 12.566370964050293 (float)
  spin_up_current = 10.0 (float)
  spin_up_acceleration = 400.0 (float)
  spin_up_target_vel = 400.0 (float)
get_temp()
motor:
  error = 0x0000 (int)
  armed_state = 0 (int)
  is_calibrated = False (bool)
  current_meas_phB = 0.17474013566970825 (float)
  current_meas_phC = -0.09392213821411133 (float)
  DC_calib_phB = -1.101399540901184 (float)
  DC_calib_phC = -1.718788981437683 (float)
  phase_current_rev_gain = 0.02500000037252903 (float)
  current_control: ...
  gate_driver: ...
  timing_log: ...
  config: ...
  set_current_control_bandwidth(current_control_bandwidth: float)
controller:
  pos_setpoint = 0.0 (float)
  vel_setpoint = 0.0 (float)
  vel_integrator_current = 0.0 (float)
  current_setpoint = 0.0 (float)
  config: ...
  set_pos_setpoint(pos_setpoint: float, vel_feed_forward: float, current_feed_forward: float)
  set_vel_setpoint(vel_setpoint: float, current_feed_forward: float)
  set_current_setpoint(current_setpoint: float)
  start_anticogging_calibration()
encoder:
  error = 0x0000 (int)
  is_ready = False (bool)
  index_found = False (bool)
  shadow_count = 3 (int)
  count_in_cpr = 3 (int)
  offset = 0 (int)
  interpolation = 0.5 (float)
  phase = 0.018791265785694122 (float)
  pos_estimate = 3.9820456504821777 (float)
  pos_cpr = 3.7660698890686035 (float)
  hall_state = 1 (int)
  pll_vel = 0.0 (float)
  config: ...
sensorless_estimator:
  error = 0x0000 (int)
  phase = 0.0 (float)
  pll_pos = 0.0 (float)
  pll_vel = 0.0 (float)
  config: ...

In [2]: odrv0.axis0.encoder.config.cpr
Out[2]: 8192

In [3]: odrv0.axis0.encoder.config.cpr = 40000

In [4]: odrv0.axis0.controller.config.vel_gain = .0001
   ...:

In [5]: odrv0.axis0.encoder.config.use_index = True
   ...:

In [6]: odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE
   ...:

In [7]: odrv0.axis0.encoder.config.offset
Out[7]: 34339

In [8]: odrv0.axis0.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION
   ...:

In [9]: odrv0.axis0.encoder.config.offset
Out[9]: 34340

In [10]: odrv0.axis0.requested_state = AXIS_STATE_ENCODER_INDEX_SEARCH
    ...:

In [11]: odrv0.axis0.encoder.config.offset
Out[11]: 34340

In [12]: odrv0.axis0.requested_state = AXIS_STATE_ENCODER_INDEX_SEARCH
    ...:

In [13]: odrv0.axis0.encoder.config.offset
Out[13]: 34340

In [14]: odrv0.axis0.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION
    ...:

In [15]: odrv0.axis0.encoder.config.offset
Out[15]: 74342

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

In [17]: odrv0.axis0.encoder.config.offset
Out[17]: 74342

In [18]: odrv0.axis0.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION
    ...:

In [19]: odrv0.axis0.encoder.config.offset
Out[19]: 20232

In [20]: odrv0.axis0.requested_state = AXIS_STATE_ENCODER_INDEX_SEARCH
    ...:

In [21]: odrv0.axis0.encoder.config.offset
Out[21]: 20232

In [22]: odrv0.axis0.error
Out[22]: 0

In [23]: odrv0.axis0.encoder.config.pre_calibrated = True
    ...:

In [24]: odrv0.axis0.config.startup_encoder_index_search = True

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

In [26]: odrv0.save_configuration()
    ...:

In [27]: odrv0.reboot()
    ...:
---------------------------------------------------------------------------
USBError                                  Traceback (most recent call last)
~\Anaconda3\lib\site-packages\fibre\usbbulk_transport.py in process_packet(self, usbBuffer)
     96     try:
---> 97       ret = self.epw.write(usbBuffer, 0)
     98       if self._was_damaged:

~\Anaconda3\lib\site-packages\usb\core.py in write(self, data, timeout)
    386         """
--> 387         return self.device.write(self, data, timeout)
    388

~\Anaconda3\lib\site-packages\usb\core.py in write(self, endpoint, data, timeout)
    947                 _interop.as_array(data),
--> 948                 self.__get_timeout(timeout)
    949             )

~\Anaconda3\lib\site-packages\usb\backend\libusb0.py in bulk_write(self, dev_handle, ep, intf, data, tim
eout)
    532                             intf,
--> 533                             data, timeout)
    534

~\Anaconda3\lib\site-packages\usb\backend\libusb0.py in __write(self, fn, dev_handle, ep, intf, data, ti
meout)
    615                         length,
--> 616                         timeout
    617                     )))

~\Anaconda3\lib\site-packages\usb\backend\libusb0.py in _check(ret)
    430             return ret
--> 431     raise USBError(errmsg, ret)
    432

USBError: [Errno None] b'libusb0-dll:err [submit_async] submitting request failed, win error: The device
 does not recognize the command.\r\n'

During handling of the above exception, another exception occurred:

TimeoutError                              Traceback (most recent call last)
~\Anaconda3\lib\site-packages\fibre\shell.py in <module>()
----> 1 odrv0.reboot()

~\Anaconda3\lib\site-packages\fibre\remote_object.py in __call__(self, *args)
    122         for i in range(len(args)):
    123             self._inputs[i].set_value(args[i])
--> 124         self._parent.__channel__.remote_endpoint_operation(self._trigger_id, None, True, 0)
    125         if len(self._outputs) > 0:
    126             return self._outputs[0].get_value()

~\Anaconda3\lib\site-packages\fibre\protocol.py in remote_endpoint_operation(self, endpoint_id, input, e
xpect_ack, output_length)
    294                     self._my_lock.acquire()
    295                     try:
--> 296                         self._output.process_packet(packet)
    297                     except ChannelDamagedException:
    298                         attempt += 1

~\Anaconda3\lib\site-packages\fibre\usbbulk_transport.py in process_packet(self, usbBuffer)
    104         raise fibre.protocol.ChannelBrokenException()
    105       elif ex.errno is None or ex.errno == 60 or ex.errno == 110: # timeout
--> 106         raise TimeoutError()
    107       else:
    108         self._logger.debug("error in usbbulk_transport.py, process_packet")

TimeoutError:

Reconnected to ODrive 206137883548 as odrv0
In [28]: odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL
    ...:

In [29]: odrv0.axis0.requested_state = AXIS_STATE_IDLE

In [30]: odrv0.axis0.error
Out[30]: 0

In [31]: odrv0.axis0.encoder.config.offset
Out[31]: 20232

In [32]: odrv0.axis0
Out[32]:
error = 0x0000 (int)
enable_step_dir = False (bool)
current_state = 1 (int)
requested_state = 0 (int)
loop_counter = 2372438 (int)
config:
  startup_motor_calibration = False (bool)
  startup_encoder_index_search = True (bool)
  startup_encoder_offset_calibration = False (bool)
  startup_closed_loop_control = False (bool)
  startup_sensorless_control = False (bool)
  enable_step_dir = False (bool)
  counts_per_step = 2.0 (float)
  ramp_up_time = 0.4000000059604645 (float)
  ramp_up_distance = 12.566370964050293 (float)
  spin_up_current = 10.0 (float)
  spin_up_acceleration = 400.0 (float)
  spin_up_target_vel = 400.0 (float)
get_temp()
motor:
  error = 0x0000 (int)
  armed_state = 0 (int)
  is_calibrated = True (bool)
  current_meas_phB = 0.20189160108566284 (float)
  current_meas_phC = -0.05986285209655762 (float)
  DC_calib_phB = -1.1288903951644897 (float)
  DC_calib_phC = -1.7529141902923584 (float)
  phase_current_rev_gain = 0.02500000037252903 (float)
  current_control: ...
  gate_driver: ...
  timing_log: ...
  config: ...
  set_current_control_bandwidth(current_control_bandwidth: float)
controller:
  pos_setpoint = 0.0 (float)
  vel_setpoint = 0.0 (float)
  vel_integrator_current = -7.006492321624085e-44 (float)
  current_setpoint = 0.0 (float)
  config: ...
  set_pos_setpoint(pos_setpoint: float, vel_feed_forward: float, current_feed_forward: float)
  set_vel_setpoint(vel_setpoint: float, current_feed_forward: float)
  set_current_setpoint(current_setpoint: float)
  start_anticogging_calibration()
encoder:
  error = 0x0000 (int)
  is_ready = True (bool)
  index_found = True (bool)
  shadow_count = 12324297 (int)
  count_in_cpr = 9916 (int)
  offset = 20232 (int)
  interpolation = 0.5 (float)
  phase = 1.2230281829833984 (float)
  pos_estimate = 12324296.0 (float)
  pos_cpr = 9916.232421875 (float)
  hall_state = 2 (int)
  pll_vel = 0.0 (float)
  config: ...
sensorless_estimator:
  error = 0x0000 (int)
  phase = 1.288478136062622 (float)
  pll_pos = 1.2895407676696777 (float)
  pll_vel = -0.3880535364151001 (float)
  config: ...

In [33]:

Sounds like the bug we fixed in firmware version 0.4.3 (see changelog). What firmware version do you have?

 vbus_voltage = 12.699682235717773 (float)
serial_number = 206137883548 (int)
hw_version_major = 3 (int)
hw_version_minor = 5 (int)
hw_version_variant = 24 (int)
fw_version_major = 0 (int)
fw_version_minor = 4 (int)
fw_version_revision = 2 (int)
fw_version_unreleased = 0 (int)
user_config_loaded = True (bool)
brake_resistor_armed = True (bool)

looks like 0.4.2 if I understand how to read this

I agree this sounds liek the same problem that was addressed in 0.4.3…

Flashing the firmware looks a bit daunting. I have the ST Link…should I just try to follow through the developers section or is there an alternate way to get this flashed quickly?

Is it possible to get a pre-compiled binary of the firmware and just flash it ?

Thanks.

You shoudn’t need the STLink. You can use the Device Firmware Update (DFU) https://docs.odriverobotics.com/odrivetool.html#device-firmware-update

Oh I was pumped to read this!!

However, my board reboots everytime it says “entering DFU mode”…it never erases or flashes. :confused:

(base) C:\Users\ajlapp>odrivetool dfu
ODrive control utility v0.4.1
Waiting for ODrive...
Found ODrive 206137883548 (v3.5-24V) with firmware v0.4.2-dev
Checking online for newest firmware... found v0.4.4
Downloading firmware v0.4.4...
Putting device 206137883548 into DFU mode...
---------------------------------------------------------------------------
USBError                                  Traceback (most recent call last)
~\Anaconda3\lib\site-packages\fibre\usbbulk_transport.py in process_packet(self, usbBuffer)
     96     try:
---> 97       ret = self.epw.write(usbBuffer, 0)
     98       if self._was_damaged:

~\Anaconda3\lib\site-packages\usb\core.py in write(self, data, timeout)
    386         """
--> 387         return self.device.write(self, data, timeout)
    388

~\Anaconda3\lib\site-packages\usb\core.py in write(self, endpoint, data, timeout)
    947                 _interop.as_array(data),
--> 948                 self.__get_timeout(timeout)
    949             )

~\Anaconda3\lib\site-packages\usb\backend\libusb0.py in bulk_write(self, dev_handle, ep, intf, data, timeout)
    532                             intf,
--> 533                             data, timeout)
    534

~\Anaconda3\lib\site-packages\usb\backend\libusb0.py in __write(self, fn, dev_handle, ep, intf, data, timeout)
    615                         length,
--> 616                         timeout
    617                     )))

~\Anaconda3\lib\site-packages\usb\backend\libusb0.py in _check(ret)
    430             return ret
--> 431     raise USBError(errmsg, ret)
    432

USBError: [Errno None] b'libusb0-dll:err [submit_async] submitting request failed, win error: The device does not recognize the command.\r\n'

During handling of the above exception, another exception occurred:

TimeoutError                              Traceback (most recent call last)
~\Anaconda3\Scripts\odrivetool in <module>()
    140         print_version()
    141         import odrive.dfu
--> 142         odrive.dfu.launch_dfu(args, logger, app_shutdown_token)
    143
    144     elif args.command == 'liveplotter':

~\Anaconda3\lib\site-packages\odrive\dfu.py in launch_dfu(args, logger, cancellation_token)
    448     firmware = FirmwareFromFile(args.file) if args.file else None
    449
--> 450     update_device(device, firmware, logger, cancellation_token)
    451
    452

~\Anaconda3\lib\site-packages\odrive\dfu.py in update_device(device, firmware, logger, cancellation_token)
    347     if dfudev is None:
    348         find_odrive_cancellation_token = Event(cancellation_token)
--> 349         put_into_dfu_mode(device, find_odrive_cancellation_token)
    350         stm_device = find_device_in_dfu_mode(serial_number, cancellation_token)
    351         find_odrive_cancellation_token.set()

~\Anaconda3\lib\site-packages\odrive\dfu.py in put_into_dfu_mode(device, cancellation_token)
    224     print("Putting device {} into DFU mode...".format(device.__channel__.usb_device.serial_number))
    225     try:
--> 226         device.enter_dfu_mode()
    227     except fibre.ChannelBrokenException:
    228         pass # this is expected because the device reboots

~\Anaconda3\lib\site-packages\fibre\remote_object.py in __call__(self, *args)
    122         for i in range(len(args)):
    123             self._inputs[i].set_value(args[i])
--> 124         self._parent.__channel__.remote_endpoint_operation(self._trigger_id, None, True, 0)
    125         if len(self._outputs) > 0:
    126             return self._outputs[0].get_value()

~\Anaconda3\lib\site-packages\fibre\protocol.py in remote_endpoint_operation(self, endpoint_id, input, expect_ack, output_length)
    294                     self._my_lock.acquire()
    295                     try:
--> 296                         self._output.process_packet(packet)
    297                     except ChannelDamagedException:
    298                         attempt += 1

~\Anaconda3\lib\site-packages\fibre\usbbulk_transport.py in process_packet(self, usbBuffer)
    104         raise fibre.protocol.ChannelBrokenException()
    105       elif ex.errno is None or ex.errno == 60 or ex.errno == 110: # timeout
--> 106         raise TimeoutError()
    107       else:
    108         self._logger.debug("error in usbbulk_transport.py, process_packet")

TimeoutError:

Update…

I tried loading openOCD and using my STLink but I can’t seem to sort everything out. OpenOCD won’t run…I’m sure it’s something simple. I added it to PATH and tried following along with all the install instructions.

Anyway, any chance someone could remote into my machine and help me get this thing updated? I really need to get this index function working.

Thanks.

Okay…solved!

Thanks to @madcowswe!

DFU mode didn’t work but we were able to flash the board using STLink.

I’m on Windows so I had to use this command…

openocd -f interface/stlink-v2.cfg -f target/stm32f4x.cfg -c init -c "reset halt" -c "flash write_image erase YOUR_FIRMWARE_FILE.elf" -c "reset run" -c exit

1 Like