// Configurações
#define BUTTON_PIN 4 // Botão no GPIO4 (pull-up interno)
#define LED_PIN 2 // LED no GPIO2
#define DEBOUNCE_MS 50 // Debounce de 50ms
// Fila para comunicação ISR -> Tarefa
QueueHandle_t xQueue;
// Variáveis para debounce com timer HW
volatile bool buttonPressed = false;
esp_timer_handle_t debounceTimer = NULL;
// Função de callback do timer HW (chamada após DEBOUNCE_MS)
void IRAM_ATTR timerCallback(void* arg) {
if (buttonPressed) {
int buttonState = digitalRead(BUTTON_PIN);
xQueueSendFromISR(xQueue, &buttonState, NULL);
buttonPressed = false;
}
}
// Função de Interrupção do Botão (GPIO ISR)
void IRAM_ATTR buttonISR() {
buttonPressed = true;
esp_timer_start_once(debounceTimer, DEBOUNCE_MS * 1000); // Reinicia o timer (em µs)
}
// Tarefa que processa a fila (acende/apaga LED)
void taskProcessButton(void *pvParameters) {
int receivedState;
while (1) {
if (xQueueReceive(xQueue, &receivedState, portMAX_DELAY) == pdTRUE) {
digitalWrite(LED_PIN, !receivedState);
Serial.printf("Botão: %d | LED: %d\n", receivedState, digitalRead(LED_PIN));
}
}
}
void setup() {
Serial.begin(115200);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
// Cria a fila para 10 inteiros
xQueue = xQueueCreate(10, sizeof(int));
// Configura o timer HW para debounce
esp_timer_create_args_t timerArgs = {
.callback = &timerCallback,
.arg = NULL,
.dispatch_method = ESP_TIMER_TASK,
.name = "debounceTimer"
};
esp_timer_create(&timerArgs, &debounceTimer);
// Configura a interrupção do botão (borda de descida)
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), buttonISR, FALLING);
// Cria a tarefa que processa a fila
xTaskCreate(taskProcessButton, "ButtonTask", 2048, NULL, 1, NULL);
Serial.println("Sistema iniciado. Pressione o botão...");
}
void loop() {
vTaskDelay(portMAX_DELAY);
}