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

Encoder improvements #26501

Merged
merged 15 commits into from
Dec 9, 2023
2 changes: 2 additions & 0 deletions Marlin/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -1583,6 +1583,8 @@
//#define DOUBLE_LCD_FRAMERATE // Not recommended for slow boards.
#endif

//#define MENU_SCROLL_FEEDBACK // Beep when any menu is scrolled

// The timeout to return to the status screen from sub-menus
//#define LCD_TIMEOUT_TO_STATUS 15000 // (ms)

Expand Down
41 changes: 21 additions & 20 deletions Marlin/src/lcd/marlinui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ MarlinUI ui;

constexpr uint8_t epps = ENCODER_PULSES_PER_STEP;

#define BLOCK_CLICK_AFTER_MOVEMENT_MS 100

#if HAS_STATUS_MESSAGE
#if ENABLED(STATUS_MESSAGE_SCROLLING) && ANY(HAS_WIRED_LCD, DWIN_LCD_PROUI)
uint8_t MarlinUI::status_scroll_offset; // = 0
Expand Down Expand Up @@ -932,6 +934,7 @@ void MarlinUI::init() {
void MarlinUI::update() {

static uint16_t max_display_update_time = 0;
static millis_t last_encoder_full_step_movement = 0;
millis_t ms = millis();

#if LED_POWEROFF_TIMEOUT > 0
Expand Down Expand Up @@ -982,7 +985,12 @@ void MarlinUI::init() {
if (!touch_buttons) {
// Integrated LCD click handling via button_pressed
if (!external_control && button_pressed()) {
if (!wait_for_unclick) do_click(); // Handle the click
if (!wait_for_unclick) {
if (ELAPSED(ms, last_encoder_full_step_movement + BLOCK_CLICK_AFTER_MOVEMENT_MS))
do_click(); // Handle the click
else
wait_for_unclick = true;
}
}
else
wait_for_unclick = false;
Expand Down Expand Up @@ -1019,19 +1027,7 @@ void MarlinUI::init() {
uint8_t abs_diff = ABS(encoderDiff);

#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 idle.
// Also check if past half the threshold to compensate for missed single steps.
static int8_t lastEncoderDiff;

// Timeout? No decoder change since last check. 10 or 20 times per second.
if (encoderDiff == lastEncoderDiff && abs_diff <= epps / 2) // Same direction & size but not over a half-step?
encoderDiff = 0; // Clear residual pulses.
else if (WITHIN(abs_diff, epps / 2 + 1, epps - 1)) { // Past half of threshold?
abs_diff = epps; // Treat as a full step size
encoderDiff = (encoderDiff < 0 ? -1 : 1) * abs_diff; // ...in the spin direction.
}
TERN_(HAS_TOUCH_SLEEP, if (lastEncoderDiff != encoderDiff) wakeup_screen());
lastEncoderDiff = encoderDiff;
#endif
Expand All @@ -1045,9 +1041,8 @@ void MarlinUI::init() {
int32_t encoderMultiplier = 1;

if (encoderRateMultiplierEnabled) {
const float encoderMovementSteps = float(abs_diff) / epps;

if (lastEncoderMovementMillis) {
const float encoderMovementSteps = float(abs_diff) / epps;
// Note that the rate is always calculated between two passes through the
// loop and that the abs of the encoderDiff value is tracked.
const float encoderStepRate = encoderMovementSteps / float(ms - lastEncoderMovementMillis) * 1000;
Expand Down Expand Up @@ -1076,9 +1071,14 @@ void MarlinUI::init() {

#endif // ENCODER_RATE_MULTIPLIER

if (can_encode()) encoderPosition += (encoderDiff * encoderMultiplier) / epps;

encoderDiff = 0;
const int8_t fullSteps = encoderDiff / epps;
if (fullSteps != 0) {
last_encoder_full_step_movement = ms;
encoderDiff -= fullSteps * epps;
if (can_encode()) {
encoderPosition += (fullSteps * encoderMultiplier);
}
}
}

reset_status_timeout(ms);
Expand Down Expand Up @@ -1393,9 +1393,10 @@ void MarlinUI::init() {

#if HAS_ENCODER_WHEEL
static uint8_t lastEncoderBits;
bool ignore = false;

// Manage encoder rotation
#define ENCODER_SPIN(_E1, _E2) switch (lastEncoderBits) { case _E1: encoderDiff += encoderDirection; break; case _E2: encoderDiff -= encoderDirection; }
#define ENCODER_SPIN(_E1, _E2) switch (lastEncoderBits) { case _E1: encoderDiff += encoderDirection; break; case _E2: encoderDiff -= encoderDirection; break; default: ignore = true; }

uint8_t enc = 0;
if (buttons & EN_A) enc |= B01;
Expand All @@ -1410,7 +1411,7 @@ void MarlinUI::init() {
#if ALL(HAS_MARLINUI_MENU, AUTO_BED_LEVELING_UBL)
external_encoder();
#endif
lastEncoderBits = enc;
if (!ignore) lastEncoderBits = enc;
}

#endif // HAS_ENCODER_WHEEL
Expand Down
7 changes: 7 additions & 0 deletions Marlin/src/lcd/menu/menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,13 @@ void scroll_screen(const uint8_t limit, const bool is_menu) {
}
else
encoderTopLine = encoderLine;
#ifdef MENU_SCROLL_FEEDBACK
static int8_t last_encoderLine = encoderLine;
if (encoderLine != last_encoderLine) {
BUZZ(2, 15000);
dbuezas marked this conversation as resolved.
Show resolved Hide resolved
last_encoderLine = encoderLine;
}
#endif
}

#if HAS_LINE_TO_Z
Expand Down