feat: added status enumeration
This commit is contained in:
1 parent
d9872c8e94
commit
fb87e98189
6 files changed
+48
-26
No files matched your search
@@ -192,12 +192,12 @@ void zh_encoder_event_handler(void *arg, esp_event_base_t event_base, int32_t ev
|
|||||||
if (event_id == ZH_BUTTON_EVENT)
|
if (event_id == ZH_BUTTON_EVENT)
|
||||||
{
|
{
|
||||||
zh_encoder_button_event_on_isr_t *button_event = (zh_encoder_button_event_on_isr_t *)event_data;
|
zh_encoder_button_event_on_isr_t *button_event = (zh_encoder_button_event_on_isr_t *)event_data;
|
||||||
printf("Encoder %d button %s\n", button_event->encoder_number, button_event->button_status ? "released" : "pressed");
|
printf("Encoder %d button %s\n", button_event->encoder_number, button_event->button_status == ZH_ENCODER_BUTTON_STATUS_RELEASED ? "released" : "pressed");
|
||||||
}
|
}
|
||||||
else if (event_id == ZH_ENCODER_EVENT)
|
else if (event_id == ZH_ENCODER_EVENT)
|
||||||
{
|
{
|
||||||
zh_encoder_event_on_isr_t *encoder_event = (zh_encoder_event_on_isr_t *)event_data;
|
zh_encoder_event_on_isr_t *encoder_event = (zh_encoder_event_on_isr_t *)event_data;
|
||||||
printf("Encoder %d position %0.3f %s\n", encoder_event->encoder_number, encoder_event->encoder_position, encoder_event->encoder_status ? "increased" : "reduced");
|
printf("Encoder %d position %0.3f %s\n", encoder_event->encoder_number, encoder_event->encoder_position, encoder_event->encoder_status == ZH_ENCODER_STATUS_INCREASED ? "increased" : "reduced");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
description: ESP32 ESP-IDF component for rotary encoder
|
description: ESP32 ESP-IDF component for rotary encoder
|
||||||
url: https://github.com/aZholtikov/zh_encoder
|
url: https://github.com/aZholtikov/zh_encoder
|
||||||
version: "3.1.0"
|
version: "3.2.0"
|
||||||
license: "Apache-2.0"
|
license: "Apache-2.0"
|
||||||
maintainers:
|
maintainers:
|
||||||
- "Alexey Zholtikov <alexey.zholtikov@yandex.ru>"
|
- "Alexey Zholtikov <alexey.zholtikov@yandex.ru>"
|
||||||
|
|||||||
+22
-2
@@ -20,6 +20,8 @@
|
|||||||
*
|
*
|
||||||
* @note All public functions require a valid handle pointer obtained through zh_encoder_init().
|
* @note All public functions require a valid handle pointer obtained through zh_encoder_init().
|
||||||
* @note Rotation and button events are posted from task context (shared processing task and timer callback).
|
* @note Rotation and button events are posted from task context (shared processing task and timer callback).
|
||||||
|
* @note Button state semantics: with pull-up enabled (default), the pressed level is read as 0
|
||||||
|
* (ZH_ENCODER_BUTTON_STATUS_PRESSED) and the released level as 1 (ZH_ENCODER_BUTTON_STATUS_RELEASED).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -121,6 +123,15 @@ extern "C"
|
|||||||
|
|
||||||
ESP_EVENT_DECLARE_BASE(ZH_ENCODER);
|
ESP_EVENT_DECLARE_BASE(ZH_ENCODER);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Encoder rotation direction reported in rotation events.
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
ZH_ENCODER_STATUS_DECREASED, /*!< Encoder position decreased */
|
||||||
|
ZH_ENCODER_STATUS_INCREASED /*!< Encoder position increased */
|
||||||
|
} zh_encoder_status_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Event data structure for encoder rotation events.
|
* @brief Event data structure for encoder rotation events.
|
||||||
*
|
*
|
||||||
@@ -132,9 +143,18 @@ extern "C"
|
|||||||
{
|
{
|
||||||
float encoder_position; /*!< Encoder current position */
|
float encoder_position; /*!< Encoder current position */
|
||||||
uint8_t encoder_number; /*!< Encoder unique number */
|
uint8_t encoder_number; /*!< Encoder unique number */
|
||||||
bool encoder_status; /*!< true if position increased, false if reduced */
|
zh_encoder_status_t encoder_status; /*!< Rotation direction */
|
||||||
} zh_encoder_event_on_isr_t;
|
} zh_encoder_event_on_isr_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Encoder push-button state reported in button events.
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
ZH_ENCODER_BUTTON_STATUS_PRESSED, /*!< Button is pressed */
|
||||||
|
ZH_ENCODER_BUTTON_STATUS_RELEASED /*!< Button is released */
|
||||||
|
} zh_encoder_button_status_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Event data structure for encoder button events.
|
* @brief Event data structure for encoder button events.
|
||||||
*
|
*
|
||||||
@@ -146,7 +166,7 @@ extern "C"
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint8_t encoder_number; /*!< Encoder unique number */
|
uint8_t encoder_number; /*!< Encoder unique number */
|
||||||
bool button_status; /*!< Encoder button status */
|
zh_encoder_button_status_t button_status; /*!< Debounced button state */
|
||||||
} zh_encoder_button_event_on_isr_t;
|
} zh_encoder_button_event_on_isr_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
3.1.0
|
3.2.0
|
||||||
+19
-17
@@ -23,7 +23,7 @@
|
|||||||
Внутренняя структура энкодера (opaque-хэндл, доступен только через API компонента):
|
Внутренняя структура энкодера (opaque-хэндл, доступен только через API компонента):
|
||||||
|
|
||||||
| Поле | Тип | Описание |
|
| Поле | Тип | Описание |
|
||||||
| ------ | ----- | ---------- |
|
| ----------------------- | ----------------------- | ----------------------------------------------------------------------- |
|
||||||
| `s_gpio_status` | `bool` | Текущее состояние кнопки (обновляется только колбэком таймера дребезга) |
|
| `s_gpio_status` | `bool` | Текущее состояние кнопки (обновляется только колбэком таймера дребезга) |
|
||||||
| `encoder_number` | `uint8_t` | Уникальный номер энкодера, передаётся в событиях |
|
| `encoder_number` | `uint8_t` | Уникальный номер энкодера, передаётся в событиях |
|
||||||
| `s_gpio_number` | `gpio_num_t` | GPIO кнопки (`GPIO_NUM_MAX`, если кнопка отключена) |
|
| `s_gpio_number` | `gpio_num_t` | GPIO кнопки (`GPIO_NUM_MAX`, если кнопка отключена) |
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
Передаётся из ISR точки наблюдения PCNT в общую задачу обработки:
|
Передаётся из ISR точки наблюдения PCNT в общую задачу обработки:
|
||||||
|
|
||||||
| Поле | Тип | Описание |
|
| Поле | Тип | Описание |
|
||||||
|------|-----|----------|
|
| -------- | ----------------------- | ---------------------------------------------------------- |
|
||||||
| `count` | `int32_t` | Знаковое значение счётчика PCNT, прочитанное перед сбросом |
|
| `count` | `int32_t` | Знаковое значение счётчика PCNT, прочитанное перед сбросом |
|
||||||
| `handle` | `zh_encoder_handle_t *` | Указатель на хэндл энкодера-источника |
|
| `handle` | `zh_encoder_handle_t *` | Указатель на хэндл энкодера-источника |
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
### Общие (статические) ресурсы
|
### Общие (статические) ресурсы
|
||||||
|
|
||||||
| Ресурс | Тип | Описание |
|
| Ресурс | Тип | Описание |
|
||||||
| -------- | ----- | ---------- |
|
| --------------- | -------------------- | ----------------------------------------------------------------- |
|
||||||
| `zh_encoder` | `TaskHandle_t` | Дескриптор общей задачи обработки, создаётся для первого энкодера |
|
| `zh_encoder` | `TaskHandle_t` | Дескриптор общей задачи обработки, создаётся для первого энкодера |
|
||||||
| `_queue_handle` | `QueueHandle_t` | Общая очередь сообщений от ISR PCNT к задаче обработки |
|
| `_queue_handle` | `QueueHandle_t` | Общая очередь сообщений от ISR PCNT к задаче обработки |
|
||||||
| `_spinlock` | `portMUX_TYPE` | Спинлок для защиты общих данных энкодеров |
|
| `_spinlock` | `portMUX_TYPE` | Спинлок для защиты общих данных энкодеров |
|
||||||
@@ -76,7 +76,7 @@
|
|||||||
### Инициализация и освобождение
|
### Инициализация и освобождение
|
||||||
|
|
||||||
| Функция | Описание |
|
| Функция | Описание |
|
||||||
| --------- | ---------- |
|
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `zh_encoder_init()` | Создаёт энкодер по конфигурации: проверяет параметры, регистрирует номер в векторе, при необходимости создаёт общую очередь и задачу, инициализирует PCNT и GPIO кнопки. Позиция устанавливается в середину диапазона. Требует, чтобы входной `*handle` был равен `NULL`. |
|
| `zh_encoder_init()` | Создаёт энкодер по конфигурации: проверяет параметры, регистрирует номер в векторе, при необходимости создаёт общую очередь и задачу, инициализирует PCNT и GPIO кнопки. Позиция устанавливается в середину диапазона. Требует, чтобы входной `*handle` был равен `NULL`. |
|
||||||
| `zh_encoder_deinit()` | Останавливает PCNT, удаляет каналы и единицу, снимает обработчик GPIO прерываний и таймер кнопки, удаляет номер из вектора. При удалении последнего энкодера удаляет общую задачу, очередь и вектор. Устанавливает входной указатель в `NULL`. |
|
| `zh_encoder_deinit()` | Останавливает PCNT, удаляет каналы и единицу, снимает обработчик GPIO прерываний и таймер кнопки, удаляет номер из вектора. При удалении последнего энкодера удаляет общую задачу, очередь и вектор. Устанавливает входной указатель в `NULL`. |
|
||||||
| `zh_encoder_reinit()` | Меняет диапазон (`min`, `max`) и шаг (`step`) без перераспределения ресурсов, сбрасывает позицию в середину нового диапазона и обнуляет счётчик PCNT. |
|
| `zh_encoder_reinit()` | Меняет диапазон (`min`, `max`) и шаг (`step`) без перераспределения ресурсов, сбрасывает позицию в середину нового диапазона и обнуляет счётчик PCNT. |
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
### Управление позицией
|
### Управление позицией
|
||||||
|
|
||||||
| Функция | Описание |
|
| Функция | Описание |
|
||||||
|---------|----------|
|
| -------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `zh_encoder_set()` | Устанавливает позицию в заданное значение (в пределах настроенного диапазона), обнуляет аккумулятор и счётчик PCNT. |
|
| `zh_encoder_set()` | Устанавливает позицию в заданное значение (в пределах настроенного диапазона), обнуляет аккумулятор и счётчик PCNT. |
|
||||||
| `zh_encoder_get()` | Читает текущую позицию энкодера. |
|
| `zh_encoder_get()` | Читает текущую позицию энкодера. |
|
||||||
| `zh_encoder_reset()` | Сбрасывает позицию в середину диапазона `(min + max) / 2` и обнуляет счётчик PCNT. |
|
| `zh_encoder_reset()` | Сбрасывает позицию в середину диапазона `(min + max) / 2` и обнуляет счётчик PCNT. |
|
||||||
@@ -92,20 +92,22 @@
|
|||||||
### Статистика
|
### Статистика
|
||||||
|
|
||||||
| Функция | Описание |
|
| Функция | Описание |
|
||||||
|---------|----------|
|
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `zh_encoder_get_stats()` | Возвращает read-only указатель на глобальную структуру статистики `zh_encoder_stats_t`. Указатель действителен до вызова `zh_encoder_reset_stats()`. |
|
| `zh_encoder_get_stats()` | Возвращает read-only указатель на глобальную структуру статистики `zh_encoder_stats_t`. Указатель действителен до вызова `zh_encoder_reset_stats()`. |
|
||||||
| `zh_encoder_reset_stats()` | Обнуляет все счётчики статистики. |
|
| `zh_encoder_reset_stats()` | Обнуляет все счётчики статистики. |
|
||||||
|
|
||||||
### Типы и события
|
### Типы и события
|
||||||
|
|
||||||
| Элемент | Описание |
|
| Тип | Конструктор значений | Значения |
|
||||||
| --------- | ---------- |
|
| ---------------------------------- | ---------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||||
| `zh_encoder_init_config_t` | Конфигурация инициализации: GPIO, диапазон, шаг, параметры задачи и уникальный номер. Значения по умолчанию задаёт `ZH_ENCODER_INIT_CONFIG_DEFAULT()`. |
|
| `zh_encoder_init_config_t` | `ZH_ENCODER_INIT_CONFIG_DEFAULT()` | Конфигурация инициализации: GPIO, диапазон, шаг, параметры задачи и уникальный номер |
|
||||||
| `zh_encoder_stats_t` | Статистика: `event_post_error`, `queue_overflow_error`, `min_stack_size`. |
|
| `zh_encoder_stats_t` | — | Статистика: `event_post_error`, `queue_overflow_error`, `min_stack_size` |
|
||||||
| `zh_encoder_event_on_isr_t` | Данные события поворота: позиция, номер энкодера, направление (`true` — увеличение). |
|
| `zh_encoder_event_id_t` | — | Идентификаторы событий: `ZH_BUTTON_EVENT`, `ZH_ENCODER_EVENT` |
|
||||||
| `zh_encoder_button_event_on_isr_t` | Данные события кнопки: номер энкодера, состояние. |
|
| `zh_encoder_status_t` | — | Направление поворота: `ZH_ENCODER_STATUS_DECREASED`, `ZH_ENCODER_STATUS_INCREASED` |
|
||||||
| `zh_encoder_event_id_t` | Идентификаторы событий: `ZH_BUTTON_EVENT`, `ZH_ENCODER_EVENT`. |
|
| `zh_encoder_button_status_t` | — | Состояние кнопки: `ZH_ENCODER_BUTTON_STATUS_PRESSED` (уровень 0), `ZH_ENCODER_BUTTON_STATUS_RELEASED` (уровень 1) |
|
||||||
| `ZH_ENCODER` | База событий `esp_event`, в которую компонент постит все сообщения. |
|
| `zh_encoder_event_on_isr_t` | — | Данные события поворота: позиция, номер энкодера, направление (`zh_encoder_status_t`) |
|
||||||
|
| `zh_encoder_button_event_on_isr_t` | — | Данные события кнопки: номер энкодера, состояние (`zh_encoder_button_status_t`) |
|
||||||
|
| `ZH_ENCODER` | `ESP_EVENT_DEFINE_BASE` | База событий `esp_event`, в которую компонент постит все сообщения |
|
||||||
|
|
||||||
## Потокобезопасность
|
## Потокобезопасность
|
||||||
|
|
||||||
@@ -161,11 +163,11 @@ void zh_encoder_event_handler(void *arg, esp_event_base_t event_base, int32_t ev
|
|||||||
if (event_id == ZH_ENCODER_EVENT) {
|
if (event_id == ZH_ENCODER_EVENT) {
|
||||||
zh_encoder_event_on_isr_t *rot = (zh_encoder_event_on_isr_t *)event_data;
|
zh_encoder_event_on_isr_t *rot = (zh_encoder_event_on_isr_t *)event_data;
|
||||||
printf("Encoder %d: position %0.3f (%s)\n", rot->encoder_number,
|
printf("Encoder %d: position %0.3f (%s)\n", rot->encoder_number,
|
||||||
rot->encoder_position, rot->encoder_status ? "up" : "down");
|
rot->encoder_position, rot->encoder_status == ZH_ENCODER_STATUS_INCREASED ? "up" : "down");
|
||||||
} else if (event_id == ZH_BUTTON_EVENT) {
|
} else if (event_id == ZH_BUTTON_EVENT) {
|
||||||
zh_encoder_button_event_on_isr_t *btn = (zh_encoder_button_event_on_isr_t *)event_data;
|
zh_encoder_button_event_on_isr_t *btn = (zh_encoder_button_event_on_isr_t *)event_data;
|
||||||
printf("Encoder %d: button %s\n", btn->encoder_number,
|
printf("Encoder %d: button %s\n", btn->encoder_number,
|
||||||
btn->button_status ? "released" : "pressed");
|
btn->button_status == ZH_ENCODER_BUTTON_STATUS_RELEASED ? "released" : "pressed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,7 +262,7 @@ esp_log_level_set("zh_encoder", ESP_LOG_ERROR);
|
|||||||
## Ошибки
|
## Ошибки
|
||||||
|
|
||||||
| Код | Описание |
|
| Код | Описание |
|
||||||
| ----- | ---------- |
|
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `ESP_OK` | Операция выполнена успешно |
|
| `ESP_OK` | Операция выполнена успешно |
|
||||||
| `ESP_ERR_INVALID_ARG` | NULL-аргументы, неверные параметры конфигурации (диапазон, шаг, номер, GPIO), дублирование номера энкодера, позиция вне диапазона |
|
| `ESP_ERR_INVALID_ARG` | NULL-аргументы, неверные параметры конфигурации (диапазон, шаг, номер, GPIO), дублирование номера энкодера, позиция вне диапазона |
|
||||||
| `ESP_ERR_INVALID_STATE` | Энкодер по входному хэндлу уже инициализирован (`*handle != NULL`) |
|
| `ESP_ERR_INVALID_STATE` | Энкодер по входному хэндлу уже инициализирован (`*handle != NULL`) |
|
||||||
|
|||||||
+3
-3
@@ -618,7 +618,7 @@ static void _zh_encoder_isr_processing_task(void *pvParameter)
|
|||||||
{
|
{
|
||||||
zh_encoder_handle_t *handle = encoder_queue.handle;
|
zh_encoder_handle_t *handle = encoder_queue.handle;
|
||||||
bool position_changed = false;
|
bool position_changed = false;
|
||||||
bool encoder_status = false;
|
zh_encoder_status_t encoder_status = ZH_ENCODER_STATUS_DECREASED;
|
||||||
float encoder_position = 0.0;
|
float encoder_position = 0.0;
|
||||||
uint8_t encoder_number = 0;
|
uint8_t encoder_number = 0;
|
||||||
taskENTER_CRITICAL(&handle->lock);
|
taskENTER_CRITICAL(&handle->lock);
|
||||||
@@ -644,7 +644,7 @@ static void _zh_encoder_isr_processing_task(void *pvParameter)
|
|||||||
{
|
{
|
||||||
handle->encoder_position = candidate;
|
handle->encoder_position = candidate;
|
||||||
position_changed = true;
|
position_changed = true;
|
||||||
encoder_status = full_steps > 0 ? true : false;
|
encoder_status = full_steps > 0 ? ZH_ENCODER_STATUS_INCREASED : ZH_ENCODER_STATUS_DECREASED;
|
||||||
encoder_position = candidate;
|
encoder_position = candidate;
|
||||||
encoder_number = handle->encoder_number;
|
encoder_number = handle->encoder_number;
|
||||||
}
|
}
|
||||||
@@ -672,7 +672,7 @@ static void _zh_encoder_button_timer_cb(TimerHandle_t xTimer)
|
|||||||
encoder_handle->s_gpio_status = s_gpio_status;
|
encoder_handle->s_gpio_status = s_gpio_status;
|
||||||
zh_encoder_button_event_on_isr_t encoder_data = {0};
|
zh_encoder_button_event_on_isr_t encoder_data = {0};
|
||||||
encoder_data.encoder_number = encoder_handle->encoder_number;
|
encoder_data.encoder_number = encoder_handle->encoder_number;
|
||||||
encoder_data.button_status = s_gpio_status;
|
encoder_data.button_status = s_gpio_status == true ? ZH_ENCODER_BUTTON_STATUS_RELEASED : ZH_ENCODER_BUTTON_STATUS_PRESSED;
|
||||||
ZH_ERROR_CHECK_CONT(esp_event_post(ZH_ENCODER, ZH_BUTTON_EVENT, &encoder_data, sizeof(encoder_data), pdMS_TO_TICKS(10)) == ESP_OK, ++_stats.event_post_error, "Encoder button isr processing failed. Failed to post interrupt event.");
|
ZH_ERROR_CHECK_CONT(esp_event_post(ZH_ENCODER, ZH_BUTTON_EVENT, &encoder_data, sizeof(encoder_data), pdMS_TO_TICKS(10)) == ESP_OK, ++_stats.event_post_error, "Encoder button isr processing failed. Failed to post interrupt event.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user