From ae09378b006a4408be4bbbfc7cb43cf985c1c4d2 Mon Sep 17 00:00:00 2001 From: NemesisXB <485436+NemesisXB@users.noreply.github.com> Date: Mon, 13 May 2024 19:27:08 +0200 Subject: [PATCH 1/2] Improve rotary "tick". Misses less ticks. Add Acceleration for rotary encoder. --- components/encoder/Kconfig | 11 ++++++++++ components/encoder/encoder.c | 39 +++++++++++++++++++++++++++++++++--- components/encoder/encoder.h | 9 +++++++++ 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/components/encoder/Kconfig b/components/encoder/Kconfig index d1990a0b..739c855e 100644 --- a/components/encoder/Kconfig +++ b/components/encoder/Kconfig @@ -25,4 +25,15 @@ menu "Rotary encoders" int "Long press timeout, us" default 500000 + config RE_ACCELERATION_MIN_CUTOFF + int "Minimum Acceleration cutoff time (ms)" + default 200 + help + At this time in milliseconds between rotary ticks we want to be at the minimum acceleration + + config RE_ACCELERATION_MAX_CUTOFF + int "Maximum Acceleration cutoff time (ms)" + default 4 + help + At this time in milliseconds between rotary ticks we want to be at the maximum acceleration endmenu diff --git a/components/encoder/encoder.c b/components/encoder/encoder.c index 4be63aa4..93e661c5 100644 --- a/components/encoder/encoder.c +++ b/components/encoder/encoder.c @@ -128,13 +128,33 @@ inline static void read_encoder(rotary_encoder_t *re) re->store = (re->store << 4) | re->code; - if (re->store == 0xe817) inc = 1; - if (re->store == 0xd42b) inc = -1; + if ((re->store == 0xe817)||(re->store == 0x17e8)) inc = 1; + if ((re->store == 0xd42b)||(re->store == 0x2bd4)) inc = -1; if (inc) { - ev.type = RE_ET_CHANGED; ev.diff = inc; + if (re->acceleration.coeff > 1) + { + int64_t nowMicros = esp_timer_get_time(); + // at 200 ms, we want to have minimum acceleration + uint32_t accelerationMinCutoffMillis = CONFIG_RE_ACCELERATION_MIN_CUTOFF; + // at 4 ms, we want to have maximum acceleration + uint32_t accelerationMaxCutoffMillis = CONFIG_RE_ACCELERATION_MAX_CUTOFF; + uint32_t millisAfterLastMotion = (nowMicros - re->acceleration.last_time) / 1000u; + re->acceleration.last_time = nowMicros; + + if (millisAfterLastMotion < accelerationMinCutoffMillis) + { + if (millisAfterLastMotion < accelerationMaxCutoffMillis) + { + millisAfterLastMotion = accelerationMaxCutoffMillis; // limit to maximum acceleration + } + ev.diff = inc * ((int32_t)(re->acceleration.coeff / millisAfterLastMotion) == 0 ? 1 : (int32_t)(re->acceleration.coeff / millisAfterLastMotion)); + } + } + + ev.type = RE_ET_CHANGED; xQueueSendToBack(_queue, &ev, 0); } } @@ -252,3 +272,16 @@ esp_err_t rotary_encoder_remove(rotary_encoder_t *re) xSemaphoreGive(mutex); return ESP_ERR_NOT_FOUND; } + +esp_err_t rotary_encoder_enable_acceleration(rotary_encoder_t *re, uint16_t coeff) +{ + re->acceleration.coeff = coeff; + re->acceleration.last_time = esp_timer_get_time(); + return ESP_OK; +} + +esp_err_t rotary_encoder_disable_acceleration(rotary_encoder_t *re) +{ + re->acceleration.coeff = 0; + return ESP_OK; +} diff --git a/components/encoder/encoder.h b/components/encoder/encoder.h index 1268e983..0b22938c 100644 --- a/components/encoder/encoder.h +++ b/components/encoder/encoder.h @@ -57,6 +57,11 @@ typedef enum { RE_BTN_LONG_PRESSED = 2 //!< Button currently long pressed } rotary_encoder_btn_state_t; +//Rotary encoder acceleration variables +typedef struct { + int64_t last_time; + uint16_t coeff; +} rotary_encoder_acceleration_t; /** * Rotary encoder descriptor */ @@ -68,6 +73,7 @@ typedef struct size_t index; uint64_t btn_pressed_time_us; rotary_encoder_btn_state_t btn_state; + rotary_encoder_acceleration_t acceleration; } rotary_encoder_t; /** @@ -115,6 +121,9 @@ esp_err_t rotary_encoder_add(rotary_encoder_t *re); */ esp_err_t rotary_encoder_remove(rotary_encoder_t *re); +esp_err_t rotary_encoder_enable_acceleration(rotary_encoder_t *re, uint16_t coeff); + +esp_err_t rotary_encoder_disable_acceleration(rotary_encoder_t *re); #ifdef __cplusplus } #endif From e844783567db251aa29af4ff60d895481db98a25 Mon Sep 17 00:00:00 2001 From: NemesisXB <485436+NemesisXB@users.noreply.github.com> Date: Tue, 14 May 2024 09:13:22 +0200 Subject: [PATCH 2/2] Update example with acceleration. Update documentation of rotary_encoder_enable_acceleration and rotary_encoder_disable_acceleration functions --- components/encoder/encoder.c | 2 ++ components/encoder/encoder.h | 14 ++++++++++++++ examples/encoder/default/main/main.c | 4 ++++ 3 files changed, 20 insertions(+) diff --git a/components/encoder/encoder.c b/components/encoder/encoder.c index 93e661c5..ad173387 100644 --- a/components/encoder/encoder.c +++ b/components/encoder/encoder.c @@ -275,6 +275,7 @@ esp_err_t rotary_encoder_remove(rotary_encoder_t *re) esp_err_t rotary_encoder_enable_acceleration(rotary_encoder_t *re, uint16_t coeff) { + CHECK_ARG(re); re->acceleration.coeff = coeff; re->acceleration.last_time = esp_timer_get_time(); return ESP_OK; @@ -282,6 +283,7 @@ esp_err_t rotary_encoder_enable_acceleration(rotary_encoder_t *re, uint16_t coef esp_err_t rotary_encoder_disable_acceleration(rotary_encoder_t *re) { + CHECK_ARG(re); re->acceleration.coeff = 0; return ESP_OK; } diff --git a/components/encoder/encoder.h b/components/encoder/encoder.h index 0b22938c..a7d21259 100644 --- a/components/encoder/encoder.h +++ b/components/encoder/encoder.h @@ -121,9 +121,23 @@ esp_err_t rotary_encoder_add(rotary_encoder_t *re); */ esp_err_t rotary_encoder_remove(rotary_encoder_t *re); +/** + * @brief Enable acceleration on the rotary encoder + * + * @param re Encoder descriptor + * @param coeff Acceleration coefficient. Higher value means faster acceleration + * @return esp_err_t + */ esp_err_t rotary_encoder_enable_acceleration(rotary_encoder_t *re, uint16_t coeff); +/** + * @brief Disable acceleration on the rotary encoder + * + * @param re Encoder descriptor + * @return `ESP_OK` on success + */ esp_err_t rotary_encoder_disable_acceleration(rotary_encoder_t *re); + #ifdef __cplusplus } #endif diff --git a/examples/encoder/default/main/main.c b/examples/encoder/default/main/main.c index db200f20..141ae8c6 100644 --- a/examples/encoder/default/main/main.c +++ b/examples/encoder/default/main/main.c @@ -61,9 +61,13 @@ void test(void *arg) break; case RE_ET_BTN_CLICKED: ESP_LOGI(TAG, "Button clicked"); + rotary_encoder_enable_acceleration(&re, 100); + ESP_LOGI(TAG, "Acceleration enabled"); break; case RE_ET_BTN_LONG_PRESSED: ESP_LOGI(TAG, "Looooong pressed button"); + rotary_encoder_disable_acceleration(&re); + ESP_LOGI(TAG, "Acceleration disabled"); break; case RE_ET_CHANGED: val += e.diff;