From 58702666f220ecabe00c7c4d6e54b04d0f956bb5 Mon Sep 17 00:00:00 2001 From: rkcf Date: Tue, 7 Feb 2023 17:05:15 -0600 Subject: [PATCH] Add: main rotary encoder c file with basic counting --- main/esp32_rgb_rotary_encoder.c | 101 ++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 main/esp32_rgb_rotary_encoder.c diff --git a/main/esp32_rgb_rotary_encoder.c b/main/esp32_rgb_rotary_encoder.c new file mode 100644 index 0000000..50fc7c4 --- /dev/null +++ b/main/esp32_rgb_rotary_encoder.c @@ -0,0 +1,101 @@ +#include + +#include "esp_err.h" +#include "freertos/FreeRTOS.h" +#include "freertos/portmacro.h" +#include "freertos/projdefs.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "esp_log.h" +#include "driver/pulse_cnt.h" +#include "hal/pcnt_types.h" + +/* Pinouts */ +#define PCNT_A_PIN 1 /* Rotary Encoder A Pin */ +#define PCNT_B_PIN 2 /* Rotary Encoder B Pin */ + +/* Pulse Count Settings */ +#define PCNT_HIGH_LIMIT 100 +#define PCNT_LOW_LIMIT -100 + +static QueueHandle_t pcnt_queue = NULL; + +static const char *TAG = "RE Demo"; /* logging tag */ + +/* Pulse Counter Callback */ +static bool pcnt_cb(pcnt_unit_handle_t unit, const pcnt_watch_event_data_t *edata, void *user_ctx) { + BaseType_t high_task_wakeup; + /* Put the watchpoint value in a queue to be handled later */ + xQueueSendFromISR(pcnt_queue, &(edata->watch_point_value), &high_task_wakeup); + return (high_task_wakeup == pdTRUE); +} + +/* Main Loop */ +void app_main(void){ + + /* Configure the PCNT unit and get a handle */ + ESP_LOGI(TAG, "Setting up Pulse Counter Unit"); + pcnt_unit_config_t pcnt_unit_config = { + .high_limit = PCNT_HIGH_LIMIT, + .low_limit = PCNT_LOW_LIMIT + }; + pcnt_unit_handle_t pcnt_unit = NULL; + ESP_ERROR_CHECK(pcnt_new_unit(&pcnt_unit_config, &pcnt_unit)); + + /* Configure PCNT A & B channels and get handles */ + ESP_LOGI(TAG, "Setting up Pulse Counter Channels"); + pcnt_chan_config_t pcnt_chan_a_config = { + .edge_gpio_num = PCNT_A_PIN, + .level_gpio_num = PCNT_B_PIN + }; + pcnt_channel_handle_t pcnt_chan_a = NULL; + ESP_ERROR_CHECK(pcnt_new_channel(pcnt_unit, &pcnt_chan_a_config, &pcnt_chan_a)); + + pcnt_chan_config_t pcnt_chan_b_config = { + .edge_gpio_num = PCNT_B_PIN, + .level_gpio_num = PCNT_A_PIN + }; + pcnt_channel_handle_t pcnt_chan_b = NULL; + ESP_ERROR_CHECK(pcnt_new_channel(pcnt_unit, &pcnt_chan_b_config, &pcnt_chan_b)); + + /* Configure edge/level actions on channels */ + ESP_ERROR_CHECK(pcnt_channel_set_edge_action(pcnt_chan_a, PCNT_CHANNEL_EDGE_ACTION_DECREASE, PCNT_CHANNEL_EDGE_ACTION_INCREASE)); + ESP_ERROR_CHECK(pcnt_channel_set_level_action(pcnt_chan_a, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_INVERSE)); + ESP_ERROR_CHECK(pcnt_channel_set_edge_action(pcnt_chan_b, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_DECREASE)); + ESP_ERROR_CHECK(pcnt_channel_set_level_action(pcnt_chan_b, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_INVERSE)); + + /* Install watch points */ + ESP_LOGI(TAG, "Installing watch points and callback handler"); + int watch_points[] = {PCNT_LOW_LIMIT, -50, 0, 50, PCNT_HIGH_LIMIT}; + for (size_t i = 0; i < sizeof(watch_points) / sizeof(watch_points[0]); i++) { + ESP_ERROR_CHECK(pcnt_unit_add_watch_point(pcnt_unit, watch_points[i])); + } + + /* Initialize pcnt event queue */ + pcnt_queue = xQueueCreate(10, sizeof(int)); + + /* Install callback */ + pcnt_event_callbacks_t cbs = { + .on_reach = pcnt_cb + }; + ESP_ERROR_CHECK(pcnt_unit_register_event_callbacks(pcnt_unit, &cbs, NULL)); + + /* Enable, clear, and start pcnt Unit */ + ESP_LOGI(TAG, "Starting Pulse Counter"); + ESP_ERROR_CHECK(pcnt_unit_enable(pcnt_unit)); + ESP_ERROR_CHECK(pcnt_unit_clear_count(pcnt_unit)); + ESP_ERROR_CHECK(pcnt_unit_start(pcnt_unit)); + + /* Log counter value */ + int pulse_count = 0; + int event_count = 0; + + while (1) { + if (xQueueReceive(pcnt_queue, &event_count, pdMS_TO_TICKS(1000))) { + ESP_LOGI(TAG, "Watch point event, count: %d", event_count); + } else { + ESP_ERROR_CHECK(pcnt_unit_get_count(pcnt_unit, &pulse_count)); + ESP_LOGI(TAG, "Pulse count: %d", pulse_count); + } + } +}