Closed Wetmelon closed 2 years ago
Bumping this issue as it is still present in 0.5.4.
Somehow correlated with odrv0.axis1.config.enable_step_dir being True.
@matevzsi what's the complete (minimal) list of steps needed to reproduce this issue?
I tried the following:
odrv0.erase_configuration()
odrv0.axis1.encoder.config.use_index = True
odrv0.axis1.config.enable_step_dir = True
odrv0.axis1.min_endstop.config.gpio_num = 1
odrv0.axis1.min_endstop.config.enabled = True
odrv0.config.gpio1_mode = GPIO_MODE_DIGITAL_PULL_DOWN
odrv0.axis1.requested_state = AXIS_STATE_MOTOR_CALIBRATION
odrv0.axis1.motor.config.pre_calibrated = True
odrv0.save_configuration()
odrv0.clear_errors()
odrv0.axis1.requested_state = AXIS_STATE_ENCODER_INDEX_SEARCH # interrupt manually with endstop press
odrv0.clear_errors()
odrv0.axis1.requested_state = AXIS_STATE_ENCODER_INDEX_SEARCH
However the second index search still works as expected.
I am using CUI encoders with index, connected to the M1 encoder header.
Video of the issue: https://photos.app.goo.gl/jcWELwLzaWPmLuQX6
# Start with a clean slate...
odrv0.erase_configuration()
# Enable brake resistor
odrv0.config.enable_brake_resistor = True
# General motor setup – motor 1 (belt motor)
odrv0.axis1.motor.config.current_lim = 40
odrv0.axis1.controller.config.vel_limit = 15
odrv0.axis1.motor.config.calibration_current = 20
odrv0.axis1.encoder.config.use_index = True
odrv0.axis1.encoder.config.cpr = 8192
odrv0.save_configuration()
# Calibrate…
odrv0.axis1.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE
# Wait to complete
odrv0.axis1.encoder.config.pre_calibrated = True
odrv0.axis1.motor.config.pre_calibrated = True
# Adjust the gains
odrv0.axis1.controller.config.pos_gain = 200.0
odrv0.axis1.controller.config.vel_integrator_gain = 1.5
# !!!! If the following two lines are left out, calibration works as expected !!!
odrv0.axis1.config.enable_step_dir = True
odrv0.axis1.config.step_dir_always_on = True
# Need to enable circular setpoints due to step/dir interface
odrv0.axis1.controller.config.circular_setpoints = True
# Save and reboot
odrv0.save_configuration()
odrv0.reboot()
# Calibrate…
odrv0.axis1.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE
# This one suceeds...
# ... but re-running the calibration fails
odrv0.axis1.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE
Thanks, it seems that I was missing odrv0.axis1.config.step_dir_always_on = True
. When I set this I can also see that index search on axis1 doesn't find the index anymore.
It boils down to a collision on the interrupt lines: The default step GPIO for axis 1 (GPIO7) maps to PA15 on the MCU and the index pin on axis 1 maps to PC15 on the MCU. Both PA15 and PC15 project onto the external interrupt line 15. It is invisible to software whether an external interrupt on line 15 came from PA15, PB15, PC15, etc. The firmware is implemented to allow only one subscriber per interrupt line, so the first one to subscribe wins.
Firmware handling of this needs to be improved, e.g. exiting index search if the interrupt line is already in use and changing the default GPIOs.
Here are some possible workarounds:
odrv0.axis1.config.step_gpio_pin
.odrv0.axis1.config.step_dir_always_on
. If you disable this, step/dir input will still be enabled in closed loop control but it won't count steps in IDLE (or other states).odrv0.axis1.config.step_dir_always_on = True
once the index has been found and then don't do an index search anymore.And as far as I can see it in the code, IO subscribers were introduced in 0.5.2, causing the issue since then...
We solved it by moving the step input to another GPIO pin. Other options are not really viable since we don't have the command line interface always available and the repeated homing/index search procedure may be required due to the setup (e.g. if it fails first time due to motor being too close to the hard limit).
Thank you for looking into the issue and suggesting the solutions.
Ok I'm glad that the workaround works for you!
Note that step_dir_always_on
and enable_step_dir
are two separate settings. In most cases you can leave step_dir_always_on = False
and still use step/dir input (it will just automatically be disabled during IDLE).
What is the application case for the step_dir_always_on
?
We had really rough time with 0.5.2 and 0.5.3 due to instability of the 0.5.2 (controllers randomly loosing the timing and spinning the motors out of control) and the amount of parameters that have changed since 0.5.1 - having both step_dir_always_on
and 'enable_step_dir' set to True got us into somehow reliable waters and haven't diven deeper into the operation of those.
step_dir_always_on
was primarily added for testing so we can test step/dir input having a motor set up.
There might be some cases where it's useful for an end user. For example if the user's motion controller sends position changes while the ODrive is in IDLE and expects the ODrive's position setpoint to remain in sync with the motion controller's setpoint in absolute terms during that idle time.
Given the workaround and fundamental hardware issue, I've added some information about this to the "troubleshooting" page on the docs. https://docs.odriverobotics.com/troubleshooting
bug still here
@tianrking As outlined in my earlier comment, this is a hardware issue and not something that can be easily fixed in firmware. Maybe you can use one of the workarounds proposed in my referenced comment.
Describe the bug Encoder Index Search fails on 0.5.3, but succeeds on 0.5.1.
See https://discourse.odriverobotics.com/t/problem-with-encoder-calibration-and-board-reset-after-firmware-odrivetool-update/7804/3