/*
Exemplo: Timer de hardware no ESP32 + debounce por polling
- LED no GPIO 27 alterna a cada 100 ms via interrupção de timer (ISR).
- Botão 1 (GPIO 26, com pull-up) alterna o pisca do LED3 (GPIO 12) a cada 250 ms.
- LED1 (GPIO 14) pisca a cada 1 s.
- LED2 (GPIO 13) pisca a cada 5 s.
Observações:
* Este código é para ESP32 (Arduino core). No UNO há INT0/INT1 (pinos 2 e 3),
mas aqui usamos apenas polling + timer de hardware do ESP32.
* Debounce simples com atraso curto. Para aplicações críticas, prefira debounce por tempo (millis).
*/
#include <Arduino.h>
// ---------------------- Pinos ----------------------
const uint8_t LED = 27; // LED piscado pelo timer (ISR)
const uint8_t Led1 = 14; // Pisca a cada 1 s
const uint8_t Led2 = 13; // Pisca a cada 5 s
const uint8_t Led3 = 12; // Pisca a cada 250 ms quando habilitado por Botao1
const uint8_t Botao1 = 26; // INPUT_PULLUP
const uint8_t Botao2 = 22; // INPUT_PULLUP (reservado para uso futuro)
// ---------------------- Configs ----------------------
const uint16_t debounceDelay = 10; // ms
// ---------------------- Estados de botões ----------------------
bool bt1_pressionado = false; // estado lógico do recurso controlado pelo Botao1
bool bt1_estadoAtual = true; // repouso = HIGH (pull-up)
bool bt1_ultimoEstado = true;
bool bt2_estadoAtual = true; // mantido para expansão
bool bt2_ultimoEstado = true;
// ---------------------- Temporização por millis ----------------------
unsigned long tempoAtual = 0;
unsigned long tempoAnterior1 = 0; // LED1 (1 s)
unsigned long tempoAnterior2 = 0; // LED2 (5 s)
unsigned long tempoAnterior3 = 0; // LED3 (250 ms quando habilitado)
// ---------------------- Timer de hardware ----------------------
hw_timer_t* My_timer = nullptr;
// Debounce simples por atraso curto (bloqueante).
bool debounce(int pin, bool ultimoEstado) {
bool atual = digitalRead(pin);
if (ultimoEstado != atual) {
delay(debounceDelay);
atual = digitalRead(pin);
}
return atual;
}
// ISR do timer: alterna o LED rapidamente (100 ms)
void IRAM_ATTR onTimer() {
digitalWrite(LED, !digitalRead(LED));
}
void setup() {
Serial.begin(115200);
pinMode(Led1, OUTPUT);
pinMode(Led2, OUTPUT);
pinMode(Led3, OUTPUT);
pinMode(LED, OUTPUT);
pinMode(Botao1, INPUT_PULLUP);
pinMode(Botao2, INPUT_PULLUP);
// --------- Timer de hardware (compatível v3.x e v2.x) ---------
// v3.x (ex.: 3.1.1): timerBegin(frequencyHz) -> 10 Hz = 100 ms por interrupção
// v2.x: timerBegin(timer, prescaler, countUp) + alarm (100000 us)
#if defined(ESP_ARDUINO_VERSION) && (ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3,0,0))
My_timer = timerBegin(10); // 10 Hz -> 100 ms
timerAttachInterrupt(My_timer, &onTimer); // nova assinatura (sem 3º parâmetro)
timerStart(My_timer); // inicia o timer
#else
My_timer = timerBegin(/*timer*/ 0, /*presc*/ 80, /*countUp*/ true); // 1 tick = 1 us
timerAttachInterrupt(My_timer, &onTimer, /*edge*/ true);
timerAlarmWrite(My_timer, /*ticks*/ 100000, /*auto-reload*/ true); // 100 ms
timerAlarmEnable(My_timer);
#endif
// Estado inicial dos LEDs
digitalWrite(Led1, LOW);
digitalWrite(Led2, LOW);
digitalWrite(Led3, LOW);
Serial.println("Inicializado.");
}
void loop() {
// -------- Leitura com debounce e detecção de borda do Botao1 --------
bt1_estadoAtual = debounce(Botao1, bt1_ultimoEstado);
// Borda de descida (HIGH -> LOW) indica "pressionado" em INPUT_PULLUP
if (bt1_ultimoEstado == true && bt1_estadoAtual == false) {
bt1_pressionado = !bt1_pressionado; // alterna função vinculada ao Botao1
Serial.println(bt1_pressionado ? "Botao1: pressionado (modo ON)" : "Botao1: liberado (modo OFF)");
}
bt1_ultimoEstado = bt1_estadoAtual;
// (Opcional) leitura do Botao2 para futuras funções
bt2_estadoAtual = debounce(Botao2, bt2_ultimoEstado);
// if (bt2_ultimoEstado == true && bt2_estadoAtual == false) { /* ação futura */ }
bt2_ultimoEstado = bt2_estadoAtual;
// -------- Temporizações baseadas em millis --------
tempoAtual = millis();
// LED3: pisca a cada 250 ms SOMENTE quando bt1_pressionado == true
if (bt1_pressionado) {
if (tempoAtual - tempoAnterior3 >= 250) {
tempoAnterior3 = tempoAtual;
digitalWrite(Led3, !digitalRead(Led3));
Serial.print("tempoAnterior3: ");
Serial.println(tempoAnterior3);
}
} else {
if (digitalRead(Led3) != LOW) {
digitalWrite(Led3, LOW);
}
}
// LED2: pisca a cada 5 s
if (tempoAtual - tempoAnterior2 >= 5000) {
tempoAnterior2 = tempoAtual;
digitalWrite(Led2, !digitalRead(Led2));
Serial.print("tempoAnterior2: ");
Serial.println(tempoAnterior2);
}
// LED1: pisca a cada 1 s
if (tempoAtual - tempoAnterior1 >= 1000) {
tempoAnterior1 = tempoAtual;
digitalWrite(Led1, !digitalRead(Led1));
Serial.print("tempoAnterior1: ");
Serial.println(tempoAnterior1);
}
}