#define BUTTON1_PIN 14 // Pulsante momentaneo (senza memoria)
#define BUTTON2_PIN 23 // Pulsante toggle (con memoria)
#define LED1_PIN 13 // LED controllato senza memoria
#define LED2_PIN 12 // LED controllato con memoria
#define DEBOUNCETIME 50 // Tempo di debounce in ms
/**
* Struttura Button per gestione avanzata del debounce
*
* Rileva immediatamente cambiamenti di stato e inibisce
* temporaneamente il rilevamento dei fronti successivi
*/
struct Button {
uint8_t pin; // Pin di Arduino collegato al pulsante
uint8_t val0; // Ultimo valore letto
unsigned long debtime; // Tempo di debounce in millisecondi
uint8_t val; // Valore attuale letto
uint8_t val00; // Ultimo stato stabile
unsigned long last; // Timestamp ultimo cambiamento
bool debState; // Flag per stato debounce (true = in debounce)
/**
* Verifica se c'è stato un cambiamento valido dello stato del pulsante.
* Rileva solo il fronte iniziale del cambiamento, non la fine del debounce.
*
* @return true solo al rilevamento del primo fronte, false altrimenti
*/
bool changed() {
bool chg = false; // Default: nessun cambiamento rilevato
val = digitalRead(pin);
if(!debState) { // STATO IDLE: attesa di un cambiamento
if(val != val0) { // Rilevato cambiamento
debState = true; // Attiva stato di debounce
last = millis(); // Memorizza timestamp
chg = true; // Segnala cambiamento (SOLO QUI)
val0 = val; // Aggiorna ultimo valore letto
val00 = val; // Memorizza stato valido
}
} else { // STATO DEBOUNCE: filtraggio rimbalzi
if(val != val0) { // Se lo stato continua a cambiare
last = millis(); // Reset del timer di debounce
val0 = val; // Aggiorna ultimo valore letto
}else if((unsigned long)(millis() - last) > debtime) {
debState = false; // Torna a stato stabile
val0 = val00; // Ripristina stato di riferimento
// chg rimane false quando il debounce termina
}
}
return chg; // Ritorna true solo sul fronte iniziale
}
};
// Inizializzazione pulsanti
Button buttonMomentary = {BUTTON1_PIN, LOW, 1000}; // Pulsante senza memoria
Button buttonToggle = {BUTTON2_PIN, LOW, 50}; // Pulsante con memoria
// Stato per il pulsante con memoria
bool toggleState = false;
void setup() {
Serial.begin(115200);
// Configurazione I/O
pinMode(BUTTON1_PIN, INPUT); // Pulsanti con resistenza pullup
pinMode(BUTTON2_PIN, INPUT);
pinMode(LED1_PIN, OUTPUT); // LED
pinMode(LED2_PIN, OUTPUT);
// Stato iniziale LED
digitalWrite(LED1_PIN, LOW);
digitalWrite(LED2_PIN, LOW);
Serial.println("Sistema di controllo LED inizializzato");
Serial.println("- Pulsante 1: Controllo momentaneo (senza memoria)");
Serial.println("- Pulsante 2: Controllo toggle (con memoria)");
}
void loop() {
// 1. PULSANTE SENZA MEMORIA (momentaneo)
// Accende il LED solo quando il pulsante è premuto
if(buttonMomentary.changed()) {
// Il pulsante ha cambiato stato
if(buttonMomentary.val == HIGH) { // Con pullup, LOW = premuto
digitalWrite(LED1_PIN, HIGH);
Serial.println("Pulsante 1 premuto - LED 1 acceso");
} else {
digitalWrite(LED1_PIN, LOW);
Serial.println("Pulsante 1 rilasciato - LED 1 spento");
}
}
// 2. PULSANTE CON MEMORIA (toggle)
// Cambia lo stato del LED ad ogni pressione
if(buttonToggle.changed()) {
if(buttonToggle.val == HIGH) { // Solo sulla pressione (non sul rilascio)
toggleState = !toggleState; // Inverte lo stato
digitalWrite(LED2_PIN, toggleState);
Serial.print("Pulsante 2 premuto - LED 2 ");
Serial.println(toggleState ? "acceso" : "spento");
}
}
delay(1); // Breve pausa per stabilità
}
esp:VIN
esp:GND.2
esp:D13
esp:D12
esp:D14
esp:D27
esp:D26
esp:D25
esp:D33
esp:D32
esp:D35
esp:D34
esp:VN
esp:VP
esp:EN
esp:3V3
esp:GND.1
esp:D15
esp:D2
esp:D4
esp:RX2
esp:TX2
esp:D5
esp:D18
esp:D19
esp:D21
esp:RX0
esp:TX0
esp:D22
esp:D23
led1:A
led1:C
led2:A
led2:C
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
r1:1
r1:2
r2:1
r2:2
r3:1
r3:2
btn2:1.l
btn2:2.l
btn2:1.r
btn2:2.r
r4:1
r4:2