4 Commits

5 changed files with 3016 additions and 4 deletions

View File

@@ -15,6 +15,11 @@
## Attention ## Attention
1. If the button is not used, specify any free GPIO in the initial configuration. 1. If the button is not used, specify any free GPIO in the initial configuration.
2. For correct operation, please enable the following settings in the menuconfig:
```text
GPIO_CTRL_FUNC_IN_IRAM
```
## Using ## Using

2981
Schematic.pdf Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -47,7 +47,7 @@ extern "C"
uint8_t a_gpio_number; /*!< Encoder A GPIO number. */ uint8_t a_gpio_number; /*!< Encoder A GPIO number. */
uint8_t b_gpio_number; /*!< Encoder B GPIO number. */ uint8_t b_gpio_number; /*!< Encoder B GPIO number. */
uint8_t s_gpio_number; /*!< Encoder button GPIO number. */ uint8_t s_gpio_number; /*!< Encoder button GPIO number. */
uint8_t encoder_number; /*!< Unique encoder number. */ uint8_t encoder_number; /*!< Unique encoder number. @note Must be greater than 0. */
uint16_t stack_size; /*!< Stack size for task for the encoder isr processing processing. @note The minimum size is configMINIMAL_STACK_SIZE. */ uint16_t stack_size; /*!< Stack size for task for the encoder isr processing processing. @note The minimum size is configMINIMAL_STACK_SIZE. */
} zh_encoder_init_config_t; } zh_encoder_init_config_t;

View File

@@ -1 +1 @@
1.4.0 1.5.0

View File

@@ -35,6 +35,7 @@ static volatile uint64_t _prev_us = 0;
static uint8_t _encoder_counter = 0; static uint8_t _encoder_counter = 0;
static bool _is_prev_gpio_isr_handler = false; static bool _is_prev_gpio_isr_handler = false;
static zh_encoder_stats_t _stats = {0}; static zh_encoder_stats_t _stats = {0};
static uint8_t _encoder_number_matrix[10] = {0};
static esp_err_t _zh_encoder_validate_config(const zh_encoder_init_config_t *config); static esp_err_t _zh_encoder_validate_config(const zh_encoder_init_config_t *config);
static esp_err_t _zh_encoder_gpio_init(const zh_encoder_init_config_t *config, zh_encoder_handle_t *handle); static esp_err_t _zh_encoder_gpio_init(const zh_encoder_init_config_t *config, zh_encoder_handle_t *handle);
@@ -102,6 +103,14 @@ esp_err_t zh_encoder_init(const zh_encoder_init_config_t *config, zh_encoder_han
handle->encoder_position = (handle->encoder_min_value + handle->encoder_max_value) / 2; handle->encoder_position = (handle->encoder_min_value + handle->encoder_max_value) / 2;
handle->is_initialized = true; handle->is_initialized = true;
++_encoder_counter; ++_encoder_counter;
for (uint8_t i = 0; i < sizeof(_encoder_number_matrix); ++i)
{
if (_encoder_number_matrix[i] == 0)
{
_encoder_number_matrix[i] = handle->encoder_number;
break;
}
}
ZH_LOGI("Encoder initialization completed successfully."); ZH_LOGI("Encoder initialization completed successfully.");
return ESP_OK; return ESP_OK;
} }
@@ -128,11 +137,19 @@ esp_err_t zh_encoder_deinit(zh_encoder_handle_t *handle)
} }
handle->is_initialized = false; handle->is_initialized = false;
--_encoder_counter; --_encoder_counter;
for (uint8_t i = 0; i < sizeof(_encoder_number_matrix); ++i)
{
if (_encoder_number_matrix[i] == handle->encoder_number)
{
_encoder_number_matrix[i] = 0;
break;
}
}
ZH_LOGI("Encoder deinitialization completed successfully."); ZH_LOGI("Encoder deinitialization completed successfully.");
return ESP_OK; return ESP_OK;
} }
esp_err_t zh_encoder_reinit(zh_encoder_handle_t *handle, double min, double max, double step) esp_err_t zh_encoder_reinit(zh_encoder_handle_t *handle, double min, double max, double step) // -V2008
{ {
ZH_LOGI("Encoder reinitialization started."); ZH_LOGI("Encoder reinitialization started.");
ZH_ERROR_CHECK(handle != NULL, ESP_ERR_INVALID_ARG, NULL, "Encoder reinitialization failed. Invalid argument."); ZH_ERROR_CHECK(handle != NULL, ESP_ERR_INVALID_ARG, NULL, "Encoder reinitialization failed. Invalid argument.");
@@ -155,7 +172,9 @@ esp_err_t zh_encoder_set(zh_encoder_handle_t *handle, double position)
ZH_ERROR_CHECK(handle != NULL, ESP_ERR_INVALID_ARG, NULL, "Encoder set position failed. Invalid argument."); ZH_ERROR_CHECK(handle != NULL, ESP_ERR_INVALID_ARG, NULL, "Encoder set position failed. Invalid argument.");
ZH_ERROR_CHECK(handle->is_initialized == true, ESP_FAIL, NULL, "Encoder set position failed. Encoder not initialized."); ZH_ERROR_CHECK(handle->is_initialized == true, ESP_FAIL, NULL, "Encoder set position failed. Encoder not initialized.");
ZH_ERROR_CHECK(position <= handle->encoder_max_value && position >= handle->encoder_min_value, ESP_ERR_INVALID_ARG, NULL, "Encoder set position failed. Invalid argument."); ZH_ERROR_CHECK(position <= handle->encoder_max_value && position >= handle->encoder_min_value, ESP_ERR_INVALID_ARG, NULL, "Encoder set position failed. Invalid argument.");
taskENTER_CRITICAL(&_spinlock);
handle->encoder_position = position; handle->encoder_position = position;
taskEXIT_CRITICAL(&_spinlock);
ZH_LOGI("Encoder set position completed successfully."); ZH_LOGI("Encoder set position completed successfully.");
return ESP_OK; return ESP_OK;
} }
@@ -175,7 +194,9 @@ esp_err_t zh_encoder_reset(zh_encoder_handle_t *handle)
ZH_LOGI("Encoder reset started."); ZH_LOGI("Encoder reset started.");
ZH_ERROR_CHECK(handle != NULL, ESP_ERR_INVALID_ARG, NULL, "Encoder reset failed. Invalid argument."); ZH_ERROR_CHECK(handle != NULL, ESP_ERR_INVALID_ARG, NULL, "Encoder reset failed. Invalid argument.");
ZH_ERROR_CHECK(handle->is_initialized == true, ESP_FAIL, NULL, "Encoder reset failed. Encoder not initialized."); ZH_ERROR_CHECK(handle->is_initialized == true, ESP_FAIL, NULL, "Encoder reset failed. Encoder not initialized.");
taskENTER_CRITICAL(&_spinlock);
handle->encoder_position = (handle->encoder_min_value + handle->encoder_max_value) / 2; handle->encoder_position = (handle->encoder_min_value + handle->encoder_max_value) / 2;
taskEXIT_CRITICAL(&_spinlock);
ZH_LOGI("Encoder reset completed successfully."); ZH_LOGI("Encoder reset completed successfully.");
return ESP_OK; return ESP_OK;
} }
@@ -194,13 +215,18 @@ void zh_encoder_reset_stats(void)
ZH_LOGI("Error statistic reset successfully."); ZH_LOGI("Error statistic reset successfully.");
} }
static esp_err_t _zh_encoder_validate_config(const zh_encoder_init_config_t *config) static esp_err_t _zh_encoder_validate_config(const zh_encoder_init_config_t *config) // -V2008
{ {
ZH_ERROR_CHECK(config != NULL, ESP_ERR_INVALID_ARG, NULL, "Invalid configuration."); ZH_ERROR_CHECK(config != NULL, ESP_ERR_INVALID_ARG, NULL, "Invalid configuration.");
ZH_ERROR_CHECK(config->task_priority >= 1 && config->stack_size >= configMINIMAL_STACK_SIZE, ESP_ERR_INVALID_ARG, NULL, "Invalid task settings."); ZH_ERROR_CHECK(config->task_priority >= 1 && config->stack_size >= configMINIMAL_STACK_SIZE, ESP_ERR_INVALID_ARG, NULL, "Invalid task settings.");
ZH_ERROR_CHECK(config->queue_size >= 1, ESP_ERR_INVALID_ARG, NULL, "Invalid queue size."); ZH_ERROR_CHECK(config->queue_size >= 1, ESP_ERR_INVALID_ARG, NULL, "Invalid queue size.");
ZH_ERROR_CHECK(config->encoder_max_value > config->encoder_min_value, ESP_ERR_INVALID_ARG, NULL, "Invalid encoder min/max value."); ZH_ERROR_CHECK(config->encoder_max_value > config->encoder_min_value, ESP_ERR_INVALID_ARG, NULL, "Invalid encoder min/max value.");
ZH_ERROR_CHECK(config->encoder_step > 0, ESP_ERR_INVALID_ARG, NULL, "Invalid encoder step."); ZH_ERROR_CHECK(config->encoder_step > 0, ESP_ERR_INVALID_ARG, NULL, "Invalid encoder step.");
ZH_ERROR_CHECK(config->encoder_number > 0, ESP_ERR_INVALID_ARG, NULL, "Invalid encoder number.");
for (uint8_t i = 0; i < sizeof(_encoder_number_matrix); ++i)
{
ZH_ERROR_CHECK(config->encoder_number != _encoder_number_matrix[i], ESP_ERR_INVALID_ARG, NULL, "Encoder number already present.");
}
return ESP_OK; return ESP_OK;
} }