#include "stdio.h" // Library STDIO
#include "driver/ledc.h" // Library ESP32 LEDC
#include "driver/pcnt.h" // Library ESP32 PCNT
#include "driver/gpio.h"
#include "soc/pcnt_struct.h"
#include "freertos/FreeRTOS.h"
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("Hello, ESP32-S3!");
uint32_t f = getCpuFrequencyMhz();
Serial.println(f);
init_osc_freq();
init_PCNT();
init_GPIO();
}
uint32_t multPulses = 0;
int16_t pulses = 0;
float frequency = 0.0f;
bool low_signal_periode_begin = false;
void loop() {
if (low_signal_periode_begin) {
low_signal_periode_begin = false;
low_periode_triggered();
// printf( "frequency %f\n", frequency );
}
}
void init_osc_freq () // Initialize Oscillator to test Freq Meter
{
ledc_timer_config_t ledc_timer = {}; // LEDC timer config instance
ledc_timer.duty_resolution = LEDC_TIMER_1_BIT; // Set resolution
ledc_timer.freq_hz = 8000000; // Set Oscillator frequency
ledc_timer.speed_mode = LEDC_LOW_SPEED_MODE; // Set low speed mode ESP32-S3
ledc_timer.timer_num = LEDC_TIMER_0; // Set LEDC timer index - 0
ledc_timer.clk_cfg = LEDC_AUTO_CLK;
ledc_timer_config(&ledc_timer); // Set LEDC Timer config
ledc_channel_config_t ledc_channel = {}; // LEDC Channel config instance
ledc_channel.channel = LEDC_CHANNEL_0; // Set HS Channel - 0
ledc_channel.duty = 1; // Set Duty Cycle 50%
ledc_channel.gpio_num = 4; // LEDC Oscillator output GPIO 33
ledc_channel.intr_type = LEDC_INTR_DISABLE; // LEDC Fade interrupt disable
ledc_channel.speed_mode = LEDC_LOW_SPEED_MODE; // Set LEDC high speed mode
ledc_channel.timer_sel = LEDC_TIMER_0; // Set timer source of channel - 0
ledc_channel_config(&ledc_channel); // Config LEDC channel
}
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
//----------------------------------------------------------------------------------
static void IRAM_ATTR pcnt_intrrupt_handler(void *arg) // Counting overflow pulses
{
portENTER_CRITICAL_ISR(&timerMux); // disabling the interrupts
multPulses++; // increment Overflow counter
PCNT.int_clr.val = BIT(PCNT_UNIT_0); // Clear Pulse Counter interrupt bit
portEXIT_CRITICAL_ISR(&timerMux); // enabling the interrupts
printf( "E\n");
}
//----------------------------------------------------------------------------------
void init_PCNT(void) // Initialize and run PCNT unit
{
pcnt_config_t pcnt_config = { }; // PCNT unit instance
pcnt_config.pulse_gpio_num = GPIO_NUM_5; // Pulse input GPIO 5 LEDC
pcnt_config.ctrl_gpio_num = GPIO_NUM_6; // Control signal input GPIO 6
pcnt_config.unit = PCNT_UNIT_0; //
pcnt_config.channel = PCNT_CHANNEL_0; // PCNT unit number - 0
pcnt_config.counter_h_lim = 20000; // 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
esp_err_t error = pcnt_unit_config(&pcnt_config); // Initialize PCNT unit
if (error = ESP_ERR_INVALID_STATE)
{
printf( "ESP_ERR_INVALID_STATE\n");
}
pcnt_counter_pause(PCNT_UNIT_0); // Pause PCNT unit
pcnt_counter_clear(PCNT_UNIT_0); // Clear PCNT unit
pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_H_LIM); // Enable event to watch - max count
pcnt_isr_register(pcnt_intrrupt_handler, NULL, 0, NULL); // Setup Register ISR handler
pcnt_intr_enable(PCNT_UNIT_0); // Enable interrupts for PCNT unit
pcnt_counter_resume(PCNT_UNIT_0); // Resume PCNT unit - starts count
}
void low_periode_triggered( void )
{
esp_err_t error = pcnt_get_counter_value(PCNT_UNIT_0, &pulses);
if (error = ESP_ERR_INVALID_STATE)
{
// printf( "ESP_ERR_INVALID_STATE\n");
}
frequency = (pulses + (multPulses * 20000)) / 2;
}
static void IRAM_ATTR gpio_isr_handler_gpio7(void* arg)
{
low_signal_periode_begin = true;
}
void init_GPIO()
{
gpio_num_t gpio_num = GPIO_NUM_7;
gpio_install_isr_service(0);
gpio_reset_pin(gpio_num);
gpio_set_direction(gpio_num, GPIO_MODE_INPUT);
gpio_pullup_en(gpio_num);
gpio_set_intr_type(gpio_num, GPIO_INTR_POSEDGE);
gpio_isr_handler_add(gpio_num, gpio_isr_handler_gpio7, NULL);
}