Using the “Pulse Count Controller” (PCNT)
CMakeLists.txt REQUIRES
Ensure the following is added to the REQUIRES section of your CMakeLists.txt file in the \main folder:
REQUIRES
driver
Configuring
#include "driver/pulse_cnt.h"
#define PCNT_UNIT1_COUNTER_MAX 1000
//-----------------------------------------------
//----- SETUP PCNT (Pulse Count Controller) -----
//-----------------------------------------------
//pcnt_unit_handle_t PcntUnit1 = NULL; //Create the PCNT handle for our counter
//INSTALL PCNT UNIT
pcnt_unit_config_t unit_config = {
.high_limit = PCNT_UNIT1_COUNTER_MAX, //High limitation of the count unit, should be higher than 0 (int, max 16bit-depends on hardware) The counter will reset to zero automatically when it crosses either the high or low limit.
.low_limit = -100, //Low limitation of the count unit, should be lower than 0 (int, max 16bit-depends on hardware) The counter will reset to zero automatically when it crosses either the high or low limit.
//Other options also available
};
ESP_ERROR_CHECK(pcnt_new_unit(&unit_config, &PcntUnit1));
//SET GLITCH FILTER
pcnt_glitch_filter_config_t filter_config = {
.max_glitch_ns = 10000, //Pulse width smaller than this threshold will be treated as glitch and ignored, in the unit of ns (uint32_t, but seems you can't actually use a massive value)
};
ESP_ERROR_CHECK(pcnt_unit_set_glitch_filter(PcntUnit1, &filter_config));
//INSTALL PCNT CHANNELS
pcnt_chan_config_t chan_a_config = {
.edge_gpio_num = 21, //GPIO number used by the edge signal, input mode with pull up enabled. Set to -1 if unused
.level_gpio_num = -1 //GPIO number used by the level signal, input mode with pull up enabled. Set to -1 if unused
//Other options also available
};
pcnt_channel_handle_t pcnt_chan_a = NULL;
ESP_ERROR_CHECK(pcnt_new_channel(PcntUnit1, &chan_a_config, &pcnt_chan_a));
//SET EDGE AND LEVEL ACTIONS FOR PCNT CHANNELS
//Configure for falling edge increments count
ESP_ERROR_CHECK(pcnt_channel_set_edge_action(pcnt_chan_a, PCNT_CHANNEL_EDGE_ACTION_HOLD, PCNT_CHANNEL_EDGE_ACTION_INCREASE)); //PCNT_CHANNEL_EDGE_ACTION_HOLD, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_DECREASE
//ADD WATCH POINTS AND REGISTER CALLBACKS
//You can use this to trigger a callback when a certain value is reached
//ENABLE PCNT UNIT
ESP_ERROR_CHECK(pcnt_unit_enable(PcntUnit1));
//CLEAR PCNT UNIT
ESP_ERROR_CHECK(pcnt_unit_clear_count(PcntUnit1));
//START PCNT UNIT
ESP_ERROR_CHECK(pcnt_unit_start(PcntUnit1));
Reading value
int PulseCount = 0;
ESP_ERROR_CHECK(pcnt_unit_get_count(PcntUnit1, &PulseCount)); //Returned count value is a signed integer
ESP_LOGI(TAG, "Pulse count: %d", PulseCount);
More useful version
static int PulseCountLast = 0;
int PulseCount;
int PulsesSinceLastTime;
PulseCount = 0;
ESP_ERROR_CHECK(pcnt_unit_get_count(PcntUnit1, &PulseCount)); //Returned count value is a signed integer
if (PulseCount >= PulseCountLast)
PulsesSinceLastTime = PulseCount - PulseCountLast;
else
PulsesSinceLastTime = PulseCount - PulseCountLast + PCNT_UNIT1_COUNTER_MAX;
PulseCountLast = PulseCount;
ESP_LOGI(TAG, "New pulses: %d", PulsesSinceLastTime);
