Best Frequency Meter ever made with ESP32 - awesome!
- jgustavoam
- Posts: 164
- Joined: Thu Feb 01, 2018 2:43 pm
- Location: Belo Horizonte , Brazil
- Contact:
Re: Best Frequency Meter ever made with ESP32 - awesome!
Thanks Armin,
You are correct = sample_time = 1000000; ( one million microseconds)
"I am not very familiar with interrups, but is it possible to read and count 2-3 frequency signals from different GPIOs at the same time?"
Perhaps it is possible, yes.
Using other counters and other interrupts. If you need, using secondary processor.
You are correct = sample_time = 1000000; ( one million microseconds)
"I am not very familiar with interrups, but is it possible to read and count 2-3 frequency signals from different GPIOs at the same time?"
Perhaps it is possible, yes.
Using other counters and other interrupts. If you need, using secondary processor.
Retired IBM Brasil
Electronic hobbyist since 1976.
Electronic hobbyist since 1976.
Re: Best Frequency Meter ever made with ESP32 - awesome!
Hi Gustava,
Thank you for posting this great Frequency Meter. It is very accurate and works well. I would like to modify your version to measure the frequency of a second input, but am having some difficulties with processing the second input. I am using the one second timer output for the control signal for two separate PCNT units. I have two ISR routines to accumulate pulses. I can get each channel to work independently, but not together. Are there any pitfalls to trying to process multiple inputs?
Thanks,
MotoDan
Thank you for posting this great Frequency Meter. It is very accurate and works well. I would like to modify your version to measure the frequency of a second input, but am having some difficulties with processing the second input. I am using the one second timer output for the control signal for two separate PCNT units. I have two ISR routines to accumulate pulses. I can get each channel to work independently, but not together. Are there any pitfalls to trying to process multiple inputs?
Thanks,
MotoDan
Re: Best Frequency Meter ever made with ESP32 - awesome!
Thank you so much. I will use this code for firebeetle esp32 iot. I even uploaded it. However, I guess I'll have to make a change to the schema. I need to define a differential input. I don't know how to do this with this card. Also, is external adc used in your project?
Re: Best Frequency Meter ever made with ESP32 - awesome!
Also, I think the sample_time is a bit too much since the frequency range I want to measure is at most three digits for now. Can you tell me about the changes I can make to the code in this case?
Re: Best Frequency Meter ever made with ESP32 - awesome!
Hello all.
I am receiving "'PCNT' was not declared in this scope" when trying to compile this on my ESP32. It seems I have the library but if not, is this library provided by default or do i need to download it from somewhere?
Thanks all
Kilo
Update: I found the answer on the authors website.
Adding: #include "soc/pcnt_struct.h" fixed my issue.
Thanks
I am receiving "'PCNT' was not declared in this scope" when trying to compile this on my ESP32. It seems I have the library but if not, is this library provided by default or do i need to download it from somewhere?
Thanks all
Kilo
Update: I found the answer on the authors website.
Adding: #include "soc/pcnt_struct.h" fixed my issue.
Thanks
Last edited by k7ilo1 on Thu May 19, 2022 8:36 pm, edited 2 times in total.
Re: Best Frequency Meter ever made with ESP32 - awesome!
exit status 1
'LEDC_HIGH_SPEED_MODE' was not declared in this scope
'LEDC_HIGH_SPEED_MODE' was not declared in this scope
-
- Posts: 1
- Joined: Mon May 23, 2022 2:06 am
Re: Best Frequency Meter ever made with ESP32 - awesome!
Hi, sorry, I have a problem with the structure:
PCNT.int_clr.val = BIT(PCNT_COUNT_UNIT);
I get an alert: 'PCNT' was not declared in this scope
Could you help me to solve it?
PCNT.int_clr.val = BIT(PCNT_COUNT_UNIT);
I get an alert: 'PCNT' was not declared in this scope
Could you help me to solve it?
Re: Best Frequency Meter ever made with ESP32 - awesome!
Fantastic!
Why are pins 32 and 35 tied together? Is there a hardware reason... I thought any interrupt lock could be done in software?
Why are pins 32 and 35 tied together? Is there a hardware reason... I thought any interrupt lock could be done in software?
Re: Best Frequency Meter ever made with ESP32 - awesome!
Dear jgustavoam,
Thank you very much for the code! It works like a champ!
I am using this module: https://www.az-delivery.de/en/products/ ... pmentboard.
I need to expand the capability to count the frequency from two independent signals. I tried defining a second pulse counter unit on Arduino framework but only the first one works. The two pulse counter units work fine when executed in different sketches. Could you please help me identify the error? Here is my code below:
Many thanks!
Best,
Christoforos
Thank you very much for the code! It works like a champ!
I am using this module: https://www.az-delivery.de/en/products/ ... pmentboard.
I need to expand the capability to count the frequency from two independent signals. I tried defining a second pulse counter unit on Arduino framework but only the first one works. The two pulse counter units work fine when executed in different sketches. Could you please help me identify the error? Here is my code below:
Code: Select all
Hardware connections PCNT 1:
- ESP32 GPIO 34 - signal input
- ESP32 GPIO 35 - ESP32 GPIO 32
* * Hardware connections PCNT 2:
- ESP32 GPIO 12 - signal input
- ESP32 GPIO 14 - ESP32 GPIO 27
*/
//==================================================================================================================
// Import libraries
//-----------------
#include "driver/pcnt.h" // Library ESP32 PCNT
// Definitions
//------------
#define PCNT_COUNT_UNIT PCNT_UNIT_0 // Set Pulse Counter Unit - 0
#define PCNT_COUNT_CHANNEL PCNT_CHANNEL_0 // Set Pulse Counter channel - 0
#define PCNT_INPUT_SIG_IO GPIO_NUM_34 // Set Pulse Counter input - Freq Meter Input GPIO 34
#define PCNT_INPUT_CTRL_IO GPIO_NUM_35 // Set Pulse Counter Control GPIO pin - HIGH = count up, LOW = count down
#define OUTPUT_CONTROL_GPIO GPIO_NUM_32 // Timer output control port - GPIO_32
#define IN_BOARD_LED GPIO_NUM_2 // ESP32 native LED - GPIO 2
// No2
#define PCNT_COUNT_UNIT1 PCNT_UNIT_1 // Set Pulse Counter Unit - 0
#define PCNT_COUNT_CHANNEL1 PCNT_CHANNEL_1 // Set Pulse Counter channel - 0
#define PCNT_INPUT_SIG_IO1 GPIO_NUM_12 // Set Pulse Counter input - Freq Meter Input GPIO 34
#define PCNT_INPUT_CTRL_IO1 GPIO_NUM_14 // Set Pulse Counter Control GPIO pin - HIGH = count up, LOW = count down
#define OUTPUT_CONTROL_GPIO1 GPIO_NUM_27 // Timer output control port - GPIO_32
// Variables
//----------
bool flag = true; // Flag to enable print frequency reading
uint32_t overflow = 20000; // Max Pulse Counter value
int16_t pulses = 0; // Pulse Counter value
uint32_t multPulses = 0; // Quantidade de overflows do contador PCNT
uint32_t scale = 10; // scale factor to change sampling time
uint32_t sample_time = 1000000 / scale; // Sample time of t ms to count pulses
uint32_t resolution = 0; // Resolution value
float frequency = 0; // frequency value
char buf[32]; // Buffer
// No2
bool flag1 = true; // Flag to enable print frequency reading
uint32_t overflow1 = 20000; // Max Pulse Counter value
int16_t pulses1 = 0; // Pulse Counter value
uint32_t multPulses1 = 0; // Quantidade de overflows do contador PCNT
uint32_t scale1 = 10; // scale factor to change sampling time
uint32_t sample_time1 = 1000000/scale1; // Sample time of t ms to count pulses
uint32_t resolution1 = 0; // Resolution value
float frequency1 = 0; // frequency value
char buf1[32]; // Buffer
esp_timer_create_args_t create_args; // Create an esp_timer instance
esp_timer_handle_t timer_handle; // Create an single timer
// No2
esp_timer_create_args_t create_args1; // Create an esp_timer instance
esp_timer_handle_t timer_handle1; // Create an single timer
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED; // portMUX_TYPE to do synchronism
// No2
portMUX_TYPE timerMux1 = portMUX_INITIALIZER_UNLOCKED; // portMUX_TYPE to do synchronism
//----------------------------------------------------------------------------------------
void setup()
{
Serial.begin(115200); // Serial Console Arduino 115200 Bps
init_frequencyMeter (); // Initialize Frequency Meter
init_frequencyMeter1 (); // Initialize Frequency Meter
}
//----------------------------------------------------------------------------------
static void IRAM_ATTR pcnt_intr_handler(void *arg) // Counting overflow pulses
{
portENTER_CRITICAL_ISR(&timerMux); // disabling the interrupts
multPulses++; // increment Overflow counter
PCNT.int_clr.val = BIT(PCNT_COUNT_UNIT); // Clear Pulse Counter interrupt bit
portEXIT_CRITICAL_ISR(&timerMux); // enabling the interrupts
}
// No2
static void IRAM_ATTR pcnt_intr_handler1(void *arg) // Counting overflow pulses
{
portENTER_CRITICAL_ISR(&timerMux1); // disabling the interrupts
multPulses1++; // increment Overflow counter
PCNT.int_clr.val = BIT(PCNT_COUNT_UNIT1); // Clear Pulse Counter interrupt bit
portEXIT_CRITICAL_ISR(&timerMux1); // enabling the interrupts
}
//----------------------------------------------------------------------------------
void init_PCNT(void) // Set up and run PCNT unit
{
pcnt_config_t pcnt_config = { }; // Create PCNT unit instance
// Set up PCNT unit
pcnt_config.pulse_gpio_num = PCNT_INPUT_SIG_IO; // Pulse input GPIO 34 - Freq Meter Input
pcnt_config.ctrl_gpio_num = PCNT_INPUT_CTRL_IO; // Control signal input GPIO 35
pcnt_config.unit = PCNT_COUNT_UNIT; // Counting unit PCNT - 0
pcnt_config.channel = PCNT_COUNT_CHANNEL; // PCNT unit number - 0
pcnt_config.counter_h_lim = overflow; // Maximum counter value - 20000
pcnt_config.pos_mode = PCNT_COUNT_INC; // PCNT positive edge count mode - inc
pcnt_config.neg_mode = PCNT_COUNT_INC; // PCNT negative edge count mode - inc
pcnt_config.lctrl_mode = PCNT_MODE_DISABLE; // PCNT low control mode - disable
pcnt_config.hctrl_mode = PCNT_MODE_KEEP; // PCNT high control mode - won't change counter mode
pcnt_unit_config(&pcnt_config); // Initialize PCNT unit
// Initialise PCNT unit
pcnt_counter_pause(PCNT_COUNT_UNIT); // Pause PCNT unit
pcnt_counter_clear(PCNT_COUNT_UNIT); // Clear PCNT unit
// Interrupts
pcnt_event_enable(PCNT_COUNT_UNIT, PCNT_EVT_H_LIM); // Enable event to watch - max count
pcnt_isr_register(pcnt_intr_handler, NULL, 0, NULL); // Setup Register Interrupt Service Routine handler
pcnt_intr_enable(PCNT_COUNT_UNIT); // Enable INTERRUPTS for PCNT unit
pcnt_counter_resume(PCNT_COUNT_UNIT); // Resume PCNT unit - starts count
}
// No2
void init_PCNT1(void) // Set up and run PCNT unit
{
pcnt_config_t pcnt_config1 = { }; // Create PCNT unit instance
// Set up PCNT unit
pcnt_config1.pulse_gpio_num = PCNT_INPUT_SIG_IO1; // Pulse input GPIO 34 - Freq Meter Input
pcnt_config1.ctrl_gpio_num = PCNT_INPUT_CTRL_IO1; // Control signal input GPIO 35
pcnt_config1.unit = PCNT_COUNT_UNIT1; // Counting unit PCNT - 0
pcnt_config1.channel = PCNT_COUNT_CHANNEL1; // PCNT unit number - 0
pcnt_config1.counter_h_lim = overflow1; // Maximum counter value - 20000
pcnt_config1.pos_mode = PCNT_COUNT_INC; // PCNT positive edge count mode - inc
pcnt_config1.neg_mode = PCNT_COUNT_INC; // PCNT negative edge count mode - inc
pcnt_config1.lctrl_mode = PCNT_MODE_DISABLE; // PCNT low control mode - disable
pcnt_config1.hctrl_mode = PCNT_MODE_KEEP; // PCNT high control mode - won't change counter mode
pcnt_unit_config(&pcnt_config1); // Initialize PCNT unit
// Initialise PCNT unit
pcnt_counter_pause(PCNT_COUNT_UNIT1); // Pause PCNT unit
pcnt_counter_clear(PCNT_COUNT_UNIT1); // Clear PCNT unit
// Interrupts
pcnt_event_enable(PCNT_COUNT_UNIT1, PCNT_EVT_H_LIM); // Enable event to watch - max count
pcnt_isr_register(pcnt_intr_handler1, NULL, 0, NULL); // Setup Register Interrupt Service Routine handler
pcnt_intr_enable(PCNT_COUNT_UNIT1); // Enable INTERRUPTS for PCNT unit
pcnt_counter_resume(PCNT_COUNT_UNIT1); // Resume PCNT unit - starts count
}
//----------------------------------------------------------------------------------
void read_PCNT(void *p) { // Read Pulse Counter
gpio_set_level(OUTPUT_CONTROL_GPIO, 0); // Stop counter - output control LOW (same as digitalWrite() but faster)
pcnt_get_counter_value(PCNT_COUNT_UNIT, &pulses); // Read Pulse Counter value
flag = true; // Change flag to enable print
}
// No2
void read_PCNT1(void *p){ // Read Pulse Counter
gpio_set_level(OUTPUT_CONTROL_GPIO1, 0); // Stop counter - output control LOW (same as digitalWrite() but faster)
pcnt_get_counter_value(PCNT_COUNT_UNIT1, &pulses1); // Read Pulse Counter value
flag1 = true; // Change flag to enable print
}
//---------------------------------------------------------------------------------
void init_frequencyMeter ()
{
init_PCNT(); // Initialize and run PCNT unit
gpio_pad_select_gpio(OUTPUT_CONTROL_GPIO); // Set GPIO pad
gpio_set_direction(OUTPUT_CONTROL_GPIO, GPIO_MODE_OUTPUT); // Set GPIO 32 as output (same as pinMode)
create_args.callback = read_PCNT; // Set esp-timer argument
esp_timer_create(&create_args, &timer_handle); // Create esp-timer instance
gpio_set_direction(IN_BOARD_LED, GPIO_MODE_OUTPUT); // Set LED inboard as output
gpio_matrix_in(PCNT_INPUT_SIG_IO, SIG_IN_FUNC226_IDX, false); // Set GPIO matrin IN - Freq Meter input
gpio_matrix_out(IN_BOARD_LED, SIG_IN_FUNC226_IDX, false, false); // Set GPIO matrix OUT - to inboard LED
}
// No 2
void init_frequencyMeter1 ()
{
init_PCNT1(); // Initialize and run PCNT unit
gpio_pad_select_gpio(OUTPUT_CONTROL_GPIO1); // Set GPIO pad
gpio_set_direction(OUTPUT_CONTROL_GPIO1, GPIO_MODE_OUTPUT); // Set GPIO 32 as output (same as pinMode)
create_args1.callback = read_PCNT1; // Set esp-timer argument
esp_timer_create(&create_args1, &timer_handle1); // Create esp-timer instance
gpio_set_direction(IN_BOARD_LED, GPIO_MODE_OUTPUT); // Set LED inboard as output
gpio_matrix_in(PCNT_INPUT_SIG_IO1, SIG_IN_FUNC226_IDX, false); // Set GPIO matrin IN - Freq Meter input
gpio_matrix_out(IN_BOARD_LED, SIG_IN_FUNC226_IDX, false, false); // Set GPIO matrix OUT - to inboard LED
}
//---------------------------------------------------------------------------------
void loop()
{
if (flag == true) // If count has ended
{
flag = false; // change flag to disable print
frequency = (pulses + (multPulses * overflow)) / 2 * scale; // Calculation of frequency
Serial.print(frequency);
Serial.println(" Hz");
multPulses = 0; // Clear overflow counter
pcnt_counter_clear(PCNT_COUNT_UNIT); // Clear Pulse Counter
esp_timer_start_once(timer_handle, sample_time); // Initialize High resolution timer (1 sec)
gpio_set_level(OUTPUT_CONTROL_GPIO, 1); // Set enable PCNT count (same as digitalWrite() but faster)
}
delay(1);
if (flag1 == true) // If count has ended
{
flag1 = false; // change flag to disable print
frequency1 = (pulses1 + (multPulses1 * overflow1)) / 2 * scale1 ; // Calculation of frequency
Serial.print(frequency1);
Serial.println(" Hz");
multPulses1 = 0; // Clear overflow counter
pcnt_counter_clear(PCNT_COUNT_UNIT1); // Clear Pulse Counter
esp_timer_start_once(timer_handle1, sample_time1); // Initialize High resolution timer (1 sec)
gpio_set_level(OUTPUT_CONTROL_GPIO1, 1); // Set enable PCNT count (same as digitalWrite() but faster)
}
delay(1);
}
Best,
Christoforos
Re: Best Frequency Meter ever made with ESP32 - awesome!
Adding: #include "soc/pcnt_struct.h" fixed my issue.Mario Eric wrote: ↑Mon May 23, 2022 2:09 amHi, sorry, I have a problem with the structure:
PCNT.int_clr.val = BIT(PCNT_COUNT_UNIT);
I get an alert: 'PCNT' was not declared in this scope
Could you help me to solve it?
Kilo
Who is online
Users browsing this forum: No registered users and 58 guests