Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reliable encoder wheel action when reversing direction #18694

Merged
merged 13 commits into from
Jul 19, 2020
18 changes: 16 additions & 2 deletions Marlin/src/lcd/ultralcd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -896,7 +896,21 @@ void MarlinUI::update() {
if (TERN0(REPRAPWORLD_KEYPAD, handle_keypad()))
RESET_STATUS_TIMEOUT();

const float abs_diff = ABS(encoderDiff);
float abs_diff = ABS(encoderDiff);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

abs_diff should not be a float.
The only place where abs_diff is used as float is in calculating encoderMovementSteps. But even there it is questionable.
Note that the M3 has no floating point unit.


#if ENCODER_PULSES_PER_STEP > 1
// When reversing the encoder direction, a movement step can be missed because
// encoderDiff has a non-zero residual value, making the controller unresponsive.
// The fix clears the residual value when the encoder is reversed.
static int8_t lastEncoderDiff;
// When not past threshold, and reversing...
if (abs_diff < (ENCODER_PULSES_PER_STEP) && (encoderDiff > 0) == (lastEncoderDiff < 0)) {
encoderDiff = (encoderDiff < 0 ? -1 : 1) * (ENCODER_PULSES_PER_STEP); // Treat as full step
abs_diff = ENCODER_PULSES_PER_STEP;
}
lastEncoderDiff = encoderDiff;
#endif

const bool encoderPastThreshold = (abs_diff >= (ENCODER_PULSES_PER_STEP));
if (encoderPastThreshold || lcd_clicked) {
if (encoderPastThreshold) {
Expand Down Expand Up @@ -936,7 +950,7 @@ void MarlinUI::update() {
#endif // ENCODER_RATE_MULTIPLIER

encoderPosition += (encoderDiff * encoderMultiplier) / (ENCODER_PULSES_PER_STEP);
encoderDiff = 0;
encoderDiff = 0; // Move this and clear always?
Copy link
Member

@thinkyhead thinkyhead Jul 18, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check to see if moving this down to line 964 (after the if (encoderPastThreshold || lcd_clicked) condition) helps to fix the issue, while also not causing the encoder to miss steps. The lcd update loop is called either 10 or 20 times per second, so that should be good enough not to miss 99.9% of multiple-pulses.

Of course, test this with the other fix disabled.

}

RESET_STATUS_TIMEOUT();
Expand Down