#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 5 /* Rotary Encoder A Pin */ #define PCNT_B_PIN 4 /* Rotary Encoder B Pin */ /* Pulse Count Settings */ #define PCNT_HIGH_LIMIT 100 /* 100 total steps */ #define PCNT_LOW_LIMIT -100 static QueueHandle_t pcnt_queue = NULL; static const char *TAG = "RE Demo"; /* logging tag */ pcnt_unit_handle_t pcnt_unit; /* 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); } /* Initialize the pulse counter peripheral */ static void pcnt_init() { /* 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 }; ESP_ERROR_CHECK(pcnt_new_unit(&pcnt_unit_config, &pcnt_unit)); /* Setup glitch filter */ pcnt_glitch_filter_config_t filter_config = { .max_glitch_ns = 1000 }; ESP_ERROR_CHECK(pcnt_unit_set_glitch_filter(pcnt_unit, &filter_config)); /* 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[] = {-10, 10}; 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)); } /* Main Loop */ void app_main(void){ /* Initialize pulse counter */ pcnt_init(); /* 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); } } }