ODrive
ODrive copied to clipboard
Position control with loaded encoder issues
Describe the bug
- Homing does not reset the loaded encoder position
- CAN interface reads position estimate from "own" encoder
To Reproduce
- Use secondary encoder input with an incremental encoder and use as position/velocity feedback (use hall sensors on primary input)
odrv.axis0.controller.config.load_encoder_axis = 1. Home the axis and move to position 0. Motor will move sinceodrv.axis1.encoderdid not reset. - Query the position over CAN and you'll notice an offset when reaching position due to a lower resolution of the hall sensors
Solution I found a solution but I'm not sure it's the right way to do it. Basically during homing, reset the loaded encoder if it's different from self.
1 file changed, 6 insertions(+)
diff --git a/Firmware/MotorControl/axis.cpp b/Firmware/MotorControl/axis.cpp
index 0f834d0b..2a9336a9 100644
--- a/Firmware/MotorControl/axis.cpp
+++ b/Firmware/MotorControl/axis.cpp
@@ -438,6 +438,12 @@ bool Axis::run_homing() {
// Set the current position to 0.
encoder_.set_linear_count(0);
+ // Set loaded encoder position to 0 if used
+ if (controller_.config_.load_encoder_axis != axis_num_ && controller_.config_.load_encoder_axis < AXIS_COUNT)
+ {
+ Axis* ax = &axes[controller_.config_.load_encoder_axis];
+ ax->encoder_.set_linear_count(0);
+ }
controller_.input_pos_ = 0;
controller_.input_pos_updated();
Use InputPort from the controller instead of the OutputPort from the encoder
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Firmware/communication/can/can_simple.cpp b/Firmware/communication/can/can_simple.cpp
index a7af01ef..d9e64472 100644
--- a/Firmware/communication/can/can_simple.cpp
+++ b/Firmware/communication/can/can_simple.cpp
@@ -221,8 +221,8 @@ bool CANSimple::get_encoder_estimates_callback(const Axis& axis) {
txmsg.isExt = axis.config_.can.is_extended;
txmsg.len = 8;
- can_setSignal<float>(txmsg, axis.encoder_.pos_estimate_.any().value_or(0.0f), 0, 32, true);
- can_setSignal<float>(txmsg, axis.encoder_.vel_estimate_.any().value_or(0.0f), 32, 32, true);
+ can_setSignal<float>(txmsg, axis.controller_.pos_estimate_linear_src_.any().value_or(0.0f), 0, 32, true);
+ can_setSignal<float>(txmsg, axis.controller_.vel_estimate_src_.any().value_or(0.0f), 32, 32, true);
return canbus_->send_message(txmsg);
}
Happy to send a PR if you're happy with the proposals