Compare commits
	
		
			2 Commits
		
	
	
		
			e60224662e
			...
			main
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b4c8220284 | |||
| 80a1b45746 | 
							
								
								
									
										107
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										107
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,20 +1,44 @@ | |||||||
| # esp_component_template | # ESP32 ESP-IDF and ESP8266 RTOS SDK component for rotary encoder | ||||||
|  |  | ||||||
| esp_component_template | ## Tested on | ||||||
|  |  | ||||||
|  | 1. [ESP8266 RTOS_SDK v3.4](https://docs.espressif.com/projects/esp8266-rtos-sdk/en/latest/index.html#) | ||||||
|  | 2. [ESP32 ESP-IDF v5.4](https://docs.espressif.com/projects/esp-idf/en/release-v5.4/esp32/index.html) | ||||||
|  |  | ||||||
|  | ## Features | ||||||
|  |  | ||||||
|  | 1. Support some encoders on one device. | ||||||
|  |  | ||||||
|  | ## Note | ||||||
|  |  | ||||||
|  | 1. Encoder pins must be pull up to the VCC via 0.1 µf capacitors. | ||||||
|  |  | ||||||
|  | ## Using | ||||||
|  |  | ||||||
|  | In an existing project, run the following command to install the components: | ||||||
|  |  | ||||||
|  | ```text | ||||||
|  | cd ../your_project/components | ||||||
|  | git clone http://git.zh.com.ru/alexey.zholtikov/zh_encoder | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | In the application, add the component: | ||||||
|  |  | ||||||
|  | ```c | ||||||
|  | #include "zh_encoder.h" | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ## Examples | ||||||
|  |  | ||||||
|  | One encoder on device: | ||||||
|  |  | ||||||
|  | ```c | ||||||
| #include "zh_encoder.h" | #include "zh_encoder.h" | ||||||
|  |  | ||||||
| zh_encoder_handle_t encoder_handle = {0}; | zh_encoder_handle_t encoder_handle = {0}; | ||||||
|  |  | ||||||
| void zh_encoder_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data); | void zh_encoder_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data); | ||||||
|  |  | ||||||
| // #define ROT_ENC_A_GPIO (CONFIG_ROT_ENC_A_GPIO) |  | ||||||
| // #define ROT_ENC_B_GPIO (CONFIG_ROT_ENC_B_GPIO) |  | ||||||
|  |  | ||||||
| // #define ENABLE_HALF_STEPS false  // Set to true to enable tracking of rotary encoder at half step resolution |  | ||||||
| // #define RESET_AT          0      // Set to a positive non-zero number to reset the position if this value is exceeded |  | ||||||
| // #define FLIP_DIRECTION    false  // Set to true to reverse the clockwise/counterclockwise sense |  | ||||||
|  |  | ||||||
| void app_main(void) | void app_main(void) | ||||||
| { | { | ||||||
|     esp_log_level_set("zh_encoder", ESP_LOG_NONE); // For ESP8266 first enable "Component config -> Log output -> Enable log set level" via menuconfig. |     esp_log_level_set("zh_encoder", ESP_LOG_NONE); // For ESP8266 first enable "Component config -> Log output -> Enable log set level" via menuconfig. | ||||||
| @@ -25,64 +49,23 @@ void app_main(void) | |||||||
|     esp_event_handler_instance_register(ZH_ENCODER, ESP_EVENT_ANY_ID, &zh_encoder_event_handler, NULL, NULL); |     esp_event_handler_instance_register(ZH_ENCODER, ESP_EVENT_ANY_ID, &zh_encoder_event_handler, NULL, NULL); | ||||||
| #endif | #endif | ||||||
|     zh_encoder_init_config_t encoder_init_config = ZH_ENCODER_INIT_CONFIG_DEFAULT(); |     zh_encoder_init_config_t encoder_init_config = ZH_ENCODER_INIT_CONFIG_DEFAULT(); | ||||||
|     encoder_init_config.a_gpio_number = GPIO_NUM_26; |     encoder_init_config.a_gpio_number = GPIO_NUM_27; | ||||||
|     encoder_init_config.b_gpio_number = GPIO_NUM_27; |     encoder_init_config.b_gpio_number = GPIO_NUM_26; | ||||||
|     encoder_init_config.encoder_min_value = -10; // Just for example. |     // encoder_init_config.encoder_min_value = -10; // Just for example. | ||||||
|     encoder_init_config.encoder_max_value = 20;  // Just for example. |     // encoder_init_config.encoder_max_value = 20;  // Just for example. | ||||||
|     encoder_init_config.encoder_step = 0.1;      // Just for example. |     // encoder_init_config.encoder_step = 0.1;      // Just for example. | ||||||
|     encoder_init_config.encoder_number = 1; |     encoder_init_config.encoder_number = 1; | ||||||
|     zh_encoder_init(&encoder_init_config, &encoder_handle); |     zh_encoder_init(&encoder_init_config, &encoder_handle); | ||||||
|     zh_encoder_reset(&encoder_handle);  // Just for example. |     double position = 0; | ||||||
|     zh_encoder_set(&encoder_handle, 5); // Just for example. |     zh_encoder_get(&encoder_handle, &position); | ||||||
|  |     printf("Encoder position %0.2f.\n", position); // For ESP8266 first disable "Component config -> Newlib -> Enable ‘nano’ formatting options for printf/scanf family" via menuconfig. | ||||||
|     // esp32-rotary-encoder requires that the GPIO ISR service is installed before calling rotary_encoder_register() |     // zh_encoder_set(&encoder_handle, 5); // Just for example. | ||||||
|     //     ESP_ERROR_CHECK(gpio_install_isr_service(0)); |     // zh_encoder_reset(&encoder_handle);  // Just for example. | ||||||
|  |  | ||||||
|     //     // Initialise the rotary encoder device with the GPIOs for A and B signals |  | ||||||
|     //     rotary_encoder_info_t info = { 0 }; |  | ||||||
|     //     ESP_ERROR_CHECK(rotary_encoder_init(&info, ROT_ENC_A_GPIO, ROT_ENC_B_GPIO)); |  | ||||||
|     //     ESP_ERROR_CHECK(rotary_encoder_enable_half_steps(&info, ENABLE_HALF_STEPS)); |  | ||||||
|     // #ifdef FLIP_DIRECTION |  | ||||||
|     //     // ESP_ERROR_CHECK(rotary_encoder_flip_direction(&info)); |  | ||||||
|     // #endif |  | ||||||
|  |  | ||||||
|     //     // Create a queue for events from the rotary encoder driver. |  | ||||||
|     //     // Tasks can read from this queue to receive up to date position information. |  | ||||||
|     //     QueueHandle_t event_queue = rotary_encoder_create_queue(); |  | ||||||
|     //     ESP_ERROR_CHECK(rotary_encoder_set_queue(&info, event_queue)); |  | ||||||
|  |  | ||||||
|     //     while (1) |  | ||||||
|     //     { |  | ||||||
|     //         // Wait for incoming events on the event queue. |  | ||||||
|     //         rotary_encoder_event_t event = { 0 }; |  | ||||||
|     //         if (xQueueReceive(event_queue, &event, portMAX_DELAY) == pdTRUE) |  | ||||||
|     //         { |  | ||||||
|     //             ESP_LOGI(TAG, "Event: position %ld, direction %s", event.state.position, |  | ||||||
|     //                      event.state.direction ? (event.state.direction == ROTARY_ENCODER_DIRECTION_CLOCKWISE ? "CW" : "CCW") : "NOT_SET"); |  | ||||||
|     //         } |  | ||||||
|     //         // else |  | ||||||
|     // { |  | ||||||
|     //     // Poll current position and direction |  | ||||||
|     //     rotary_encoder_state_t state = { 0 }; |  | ||||||
|     //     ESP_ERROR_CHECK(rotary_encoder_get_state(&info, &state)); |  | ||||||
|     //     ESP_LOGI(TAG, "Poll: position %ld, direction %s", state.position, |  | ||||||
|     //              state.direction ? (state.direction == ROTARY_ENCODER_DIRECTION_CLOCKWISE ? "CW" : "CCW") : "NOT_SET"); |  | ||||||
|  |  | ||||||
|     //     // Reset the device |  | ||||||
|     //     if (RESET_AT && (state.position >= RESET_AT || state.position <= -RESET_AT)) |  | ||||||
|     //     { |  | ||||||
|     //         ESP_LOGI(TAG, "Reset"); |  | ||||||
|     //         ESP_ERROR_CHECK(rotary_encoder_reset(&info)); |  | ||||||
|     //     } |  | ||||||
|     // } |  | ||||||
|     // } |  | ||||||
|     // ESP_LOGE(TAG, "queue receive failed"); |  | ||||||
|  |  | ||||||
|     // ESP_ERROR_CHECK(rotary_encoder_uninit(&info)); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void zh_encoder_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) | void zh_encoder_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) | ||||||
| { | { | ||||||
|     zh_encoder_event_on_isr_t *event = event_data; |     zh_encoder_event_on_isr_t *event = event_data; | ||||||
|     printf("Uncoder number %d position %f.\n", event->encoder_number, event->encoder_position); |     printf("Encoder number %d position %0.2f.\n", event->encoder_number, event->encoder_position); // For ESP8266 first disable "Component config -> Newlib -> Enable ‘nano’ formatting options for printf/scanf family" via menuconfig. | ||||||
| } | } | ||||||
|  | ``` | ||||||
|   | |||||||
| @@ -40,9 +40,9 @@ 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. | ||||||
|         int32_t encoder_min_value; // Encoder min value. @note Must be less than encoder_max_value. |         int32_t encoder_min_value; // Encoder min value. | ||||||
|         int32_t encoder_max_value; // Encoder max value. @note Must be greater than encoder_min_value. |         int32_t encoder_max_value; // Encoder max value. | ||||||
|         double encoder_step;       // Encoder step. @note Must be greater than 0. |         double encoder_step;       // Encoder step. | ||||||
|         double encoder_position;   // Encoder position. |         double encoder_position;   // Encoder position. | ||||||
|         uint8_t encoder_number;    // Encoder unique number. |         uint8_t encoder_number;    // Encoder unique number. | ||||||
|         uint8_t encoder_state;     // Encoder internal state. |         uint8_t encoder_state;     // Encoder internal state. | ||||||
| @@ -83,6 +83,16 @@ extern "C" | |||||||
|      */ |      */ | ||||||
|     esp_err_t zh_encoder_set(zh_encoder_handle_t *handle, double position); |     esp_err_t zh_encoder_set(zh_encoder_handle_t *handle, double position); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @brief Get encoder position. | ||||||
|  |      * | ||||||
|  |      * @param[in] handle Pointer to unique encoder handle. | ||||||
|  |      * @param[out] position Encoder position. | ||||||
|  |      * | ||||||
|  |      * @return ESP_OK if success or an error code otherwise. | ||||||
|  |      */ | ||||||
|  |     esp_err_t zh_encoder_get(const zh_encoder_handle_t *handle, double *position); | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * @brief Reset encoder position. |      * @brief Reset encoder position. | ||||||
|      * |      * | ||||||
|   | |||||||
| @@ -80,6 +80,15 @@ esp_err_t zh_encoder_set(zh_encoder_handle_t *handle, double position) | |||||||
|     return ESP_OK; |     return ESP_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | esp_err_t zh_encoder_get(const zh_encoder_handle_t *handle, double *position) | ||||||
|  | { | ||||||
|  |     ZH_ENCODER_LOGI("Encoder get position started."); | ||||||
|  |     ZH_ENCODER_CHECK(handle->is_initialized == true, ESP_FAIL, "Encoder get position failed. Encoder not initialized."); | ||||||
|  |     *position = handle->encoder_position; | ||||||
|  |     ZH_ENCODER_LOGI("Encoder get position completed successfully."); | ||||||
|  |     return ESP_OK; | ||||||
|  | } | ||||||
|  |  | ||||||
| esp_err_t zh_encoder_reset(zh_encoder_handle_t *handle) | esp_err_t zh_encoder_reset(zh_encoder_handle_t *handle) | ||||||
| { | { | ||||||
|     ZH_ENCODER_LOGI("Encoder reset started."); |     ZH_ENCODER_LOGI("Encoder reset started."); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user