rotary_encoder_example_main.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /*
  2. * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: CC0-1.0
  5. */
  6. #include "sdkconfig.h"
  7. #include "freertos/FreeRTOS.h"
  8. #include "freertos/task.h"
  9. #include "freertos/queue.h"
  10. #include "esp_log.h"
  11. #include "driver/pulse_cnt.h"
  12. #include "driver/gpio.h"
  13. #include "esp_sleep.h"
  14. static const char *TAG = "example";
  15. #define EXAMPLE_PCNT_HIGH_LIMIT 100
  16. #define EXAMPLE_PCNT_LOW_LIMIT -100
  17. #define EXAMPLE_EC11_GPIO_A 0
  18. #define EXAMPLE_EC11_GPIO_B 2
  19. static bool example_pcnt_on_reach(pcnt_unit_handle_t unit, const pcnt_watch_event_data_t *edata, void *user_ctx)
  20. {
  21. BaseType_t high_task_wakeup;
  22. QueueHandle_t queue = (QueueHandle_t)user_ctx;
  23. // send event data to queue, from this interrupt callback
  24. xQueueSendFromISR(queue, &(edata->watch_point_value), &high_task_wakeup);
  25. return (high_task_wakeup == pdTRUE);
  26. }
  27. void app_main(void)
  28. {
  29. ESP_LOGI(TAG, "install pcnt unit");
  30. pcnt_unit_config_t unit_config = {
  31. .high_limit = EXAMPLE_PCNT_HIGH_LIMIT,
  32. .low_limit = EXAMPLE_PCNT_LOW_LIMIT,
  33. };
  34. pcnt_unit_handle_t pcnt_unit = NULL;
  35. ESP_ERROR_CHECK(pcnt_new_unit(&unit_config, &pcnt_unit));
  36. ESP_LOGI(TAG, "set glitch filter");
  37. pcnt_glitch_filter_config_t filter_config = {
  38. .max_glitch_ns = 1000,
  39. };
  40. ESP_ERROR_CHECK(pcnt_unit_set_glitch_filter(pcnt_unit, &filter_config));
  41. ESP_LOGI(TAG, "install pcnt channels");
  42. pcnt_chan_config_t chan_a_config = {
  43. .edge_gpio_num = EXAMPLE_EC11_GPIO_A,
  44. .level_gpio_num = EXAMPLE_EC11_GPIO_B,
  45. };
  46. pcnt_channel_handle_t pcnt_chan_a = NULL;
  47. ESP_ERROR_CHECK(pcnt_new_channel(pcnt_unit, &chan_a_config, &pcnt_chan_a));
  48. pcnt_chan_config_t chan_b_config = {
  49. .edge_gpio_num = EXAMPLE_EC11_GPIO_B,
  50. .level_gpio_num = EXAMPLE_EC11_GPIO_A,
  51. };
  52. pcnt_channel_handle_t pcnt_chan_b = NULL;
  53. ESP_ERROR_CHECK(pcnt_new_channel(pcnt_unit, &chan_b_config, &pcnt_chan_b));
  54. ESP_LOGI(TAG, "set edge and level actions for pcnt channels");
  55. ESP_ERROR_CHECK(pcnt_channel_set_edge_action(pcnt_chan_a, PCNT_CHANNEL_EDGE_ACTION_DECREASE, PCNT_CHANNEL_EDGE_ACTION_INCREASE));
  56. ESP_ERROR_CHECK(pcnt_channel_set_level_action(pcnt_chan_a, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_INVERSE));
  57. ESP_ERROR_CHECK(pcnt_channel_set_edge_action(pcnt_chan_b, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_DECREASE));
  58. ESP_ERROR_CHECK(pcnt_channel_set_level_action(pcnt_chan_b, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_INVERSE));
  59. ESP_LOGI(TAG, "add watch points and register callbacks");
  60. int watch_points[] = {EXAMPLE_PCNT_LOW_LIMIT, -50, 0, 50, EXAMPLE_PCNT_HIGH_LIMIT};
  61. for (size_t i = 0; i < sizeof(watch_points) / sizeof(watch_points[0]); i++) {
  62. ESP_ERROR_CHECK(pcnt_unit_add_watch_point(pcnt_unit, watch_points[i]));
  63. }
  64. pcnt_event_callbacks_t cbs = {
  65. .on_reach = example_pcnt_on_reach,
  66. };
  67. QueueHandle_t queue = xQueueCreate(10, sizeof(int));
  68. ESP_ERROR_CHECK(pcnt_unit_register_event_callbacks(pcnt_unit, &cbs, queue));
  69. ESP_LOGI(TAG, "enable pcnt unit");
  70. ESP_ERROR_CHECK(pcnt_unit_enable(pcnt_unit));
  71. ESP_LOGI(TAG, "clear pcnt unit");
  72. ESP_ERROR_CHECK(pcnt_unit_clear_count(pcnt_unit));
  73. ESP_LOGI(TAG, "start pcnt unit");
  74. ESP_ERROR_CHECK(pcnt_unit_start(pcnt_unit));
  75. #if CONFIG_EXAMPLE_WAKE_UP_LIGHT_SLEEP
  76. // EC11 channel output high level in normal state, so we set "low level" to wake up the chip
  77. ESP_ERROR_CHECK(gpio_wakeup_enable(EXAMPLE_EC11_GPIO_A, GPIO_INTR_LOW_LEVEL));
  78. ESP_ERROR_CHECK(esp_sleep_enable_gpio_wakeup());
  79. ESP_ERROR_CHECK(esp_light_sleep_start());
  80. #endif
  81. // Report counter value
  82. int pulse_count = 0;
  83. int event_count = 0;
  84. while (1) {
  85. if (xQueueReceive(queue, &event_count, pdMS_TO_TICKS(1000))) {
  86. ESP_LOGI(TAG, "Watch point event, count: %d", event_count);
  87. } else {
  88. ESP_ERROR_CHECK(pcnt_unit_get_count(pcnt_unit, &pulse_count));
  89. ESP_LOGI(TAG, "Pulse count: %d", pulse_count);
  90. }
  91. }
  92. }