#include "driver/pcnt.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
//#define INTERRUPT_PIN2 14
#define INTERRUPT_PIN 12 // Pino de entrada para pulsos
#define LED1_PIN 23 // LED 1
#define LED2_PIN 22 // LED 2
#define PCNT_UNIT PCNT_UNIT_0 // Unidade PCNT
#define PCNT_H_LIM 1000 // Limite superior do contador
#define MEASURE_INTERVAL 1000 // Intervalo de medição em milissegundos (1 segundo)
volatile long long lastInterruptTime = 0; // Marca o tempo da última interrupção
volatile bool messageFlag = false; // Flag para controlar a exibição da mensagem
volatile int16_t pulseCount = 0; // Contador de pulsos
// Configura o PCNT
void configurePCNT() {
pcnt_config_t pcntConfig = {
.pulse_gpio_num = INTERRUPT_PIN, // Pino de entrada
.ctrl_gpio_num = -1, // Sem controle
.lctrl_mode = PCNT_MODE_KEEP, // Ignorar controle inferior
.hctrl_mode = PCNT_MODE_KEEP, // Ignorar controle superior
.pos_mode = PCNT_COUNT_INC, // Incrementar em bordas de subida
.neg_mode = PCNT_COUNT_DIS, // Ignorar bordas de descida
.counter_h_lim = PCNT_H_LIM, // Limite superior
.counter_l_lim = 0, // Sem limite inferior
.unit = PCNT_UNIT, // Unidade PCNT
.channel = PCNT_CHANNEL_0 // Canal do contador
};
pcnt_unit_config(&pcntConfig);
pcnt_counter_pause(PCNT_UNIT); // Pausa para configuração
pcnt_counter_clear(PCNT_UNIT); // Zera o contador
pcnt_counter_resume(PCNT_UNIT); // Retoma o contador
}
// Função para exibir frequência
void measureFrequencyTask(void* arg) {
int16_t currentCount = 0; // Variável temporária para armazenar o valor do contador
while (1) {
vTaskDelay(pdMS_TO_TICKS(MEASURE_INTERVAL)); // Aguarda o intervalo de medição
// Obtém o valor do contador
pcnt_get_counter_value(PCNT_UNIT, ¤tCount);
// Calcula a diferença em relação à última leitura
int16_t pulseDifference = currentCount - pulseCount;
pulseCount = currentCount; // Atualiza o valor armazenado
// Calcula a frequência em Hz
float frequency = pulseDifference / (MEASURE_INTERVAL / 1000.0);
Serial.printf("Frequência medida: %.2f Hz\n", frequency);
// Reseta o contador se necessário
if (currentCount >= PCNT_H_LIM) {
pcnt_counter_clear(PCNT_UNIT);
}
}
}
// Função de interrupção
void IRAM_ATTR handleInterrupt() {
if (!messageFlag) {
digitalWrite(LED2_PIN, HIGH); // Acende o LED 2
lastInterruptTime = millis(); // Atualiza o tempo da interrupção
messageFlag = true; // Sinaliza para exibir mensagem
}
}
void setup() {
Serial.begin(115200); // Inicializa o monitor serial
Serial.println("Iniciando sistema...");
pinMode(INTERRUPT_PIN, INPUT_PULLUP); // Configura o pino como entrada com pull-up
pinMode(LED1_PIN, OUTPUT); // Configura o pino do LED 1 como saída
pinMode(LED2_PIN, OUTPUT); // Configura o pino do LED 2 como saída
// Configura interrupções
attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), handleInterrupt, FALLING);
// Configura o PCNT
configurePCNT();
// Inicia a tarefa de medição de frequência
xTaskCreate(measureFrequencyTask, "MeasureFrequencyTask", 2048, NULL, 5, NULL);
}
void loop() {
// Exibe mensagem de interrupção no console
if (messageFlag) {
Serial.println("Interrupção detectada! Botão pressionado.");
messageFlag = false; // Reseta a flag
}
// Apaga o LED após 100 ms do último evento
if (millis() - lastInterruptTime > 100) {
digitalWrite(LED2_PIN, LOW); // Apaga o LED 2
// Faz o LED 1 piscar
digitalWrite(LED1_PIN, HIGH);
delay(250);
digitalWrite(LED1_PIN, LOW);
delay(250);
}
}