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);
USEFUL?
We benefit hugely from resources on the web so we decided we should try and give back some of our knowledge and resources to the community by opening up many of our company’s internal notes and libraries through mini sites like this. We hope you find the site helpful.
Please feel free to comment if you can add help to this page or point out issues and solutions you have found, but please note that we do not provide support on this site. If you need help with a problem please use one of the many online forums.