Pulsanti analogici e cambio di stato relè

Buon giorno a tutti!
Per un progetto che sto sviluppando sto avendo la necessità di collegare dei pulsanti ad Arduino Uno tramite un ingresso analogico, come nello schema seguente:

In questo modo risparmio parecchi pin digitali che utilizzerò per altri collegamenti.
Fin quì tutto bene, ma ho anche la necessità che ogni volta che premo il primo pulsante 1, che come valore analogico restituisce 0, il relè1 si accenda, e se ripremo il pulsante il relè si spenga.

Questo significa che ho bisogno di un sistema che memorizzi lo stato del pulsante, lo stato del relè, e gli stati precedenti di entrambi, altrimenti avrò un relè che si accende e spegne in continuazione.

Per questo ho utilizzato il seguente codice di prova, ispirato da quello scritto da Michele Mafucci per una funzione analoga, ma non funziona come dovrebbe e dopo mille prove non so più dove sbattere la testa..

Potreste darmi una mano ad individuare il problema?
Grazie mille a chi potrà aiutarmi :slight_smile:

Link codice originale: Arduino – lezione 03: controlliamo un led con un pulsante | Michele Maffucci
Ecco il mio codice:

// Esempio 02: accendi il led appena è premuto il pulsante mantenendolo acceso quando si rilascia  
// premendo una seconda volta il pulsante spegne il led  
  
#define relay1 11                // relè collegato al pin 11
#define pin_buttons A2              // pin analogico di input dove è collegato il pulsante  
int val = 0;                  // si userà val per conservare lo stato del pin di input  
int vecchio_val = 0;          // si userà vecchio_val per conservare lo stato del pin di input al passo precedente  
int stato = 0;                // ricorda lo stato in cui si trova il relè, stato = 0 relè spento, stato = 1 relè acceso  
  
void setup() {  
  pinMode(relay1, OUTPUT);       // imposta il pin digitale come output  
  digitalWrite(relay1, HIGH); // spengo il relè
}  
  
void loop() {  
 ///////////////////////// SEZIONE PULSANTI E CONTATTI 
  int read_buttons = analogRead(pin_buttons);
  Serial.println(read_buttons);
  
 // controlla se è accaduto qualcosa  
  if ((read_buttons == 0) && (vecchio_val == LOW)){  
    stato = 1 - stato;  
    delay(15);                // attesa di 15 millisecondi  
  }   
  
  vecchio_val = val;            // ricordiamo il valore precedente di val  
  
    if (stato == 1) {  
    digitalWrite(relay1, LOW);   // accende il led  
  }   
  else {  
    digitalWrite(relay1, HIGH);    //spegne il led  
  }
}

Per me quel codice non ha proprio senso.

Leggi e stampa la variabile 'read_button', osserva come varia in base alla pressione del pulsante.
Considera anche che una variazione della tensione di alimentazione si riflette sul valore di 'read_button'.

Ciao.

Prima di tutto, personalmente ti consiglierei di usare lo schema che ti allego, non quello che hai postato ... perche' i pulsanti, per quanto buoni siano, tendono sempre a generare rimbalzi, a meno di non usare pulsanti con contatti in gomma (che pero' in quella configurazione non puoi usare, perche' la loro resistenza di contatto varia in funzione dell'intensita' della pressione), quindi la resisitenza da 100 ohm ed il condensatore da 10nF tendono ad eliminare il piu possibile i rimbalzi ...

Seconda cosa, consiglierei di effettuare una lettura ritardata, per evitare di leggere la rampa di carica e scarica del condensatore, per quanto veloce sia (dovrebbe bastare un delay di 2 o 3 ms, che non dovrebbe influire sul funzionamento dello sketch) ... oppure campionare per variazione (quando il valore cambia, accetta il dato solo se almeno due o tre delle letture consecutive sono simili)

Per poi fare in modo che lo stesso rele' risponda allo stesso pulsante, devi usare delle variabili flag (o segnaposto), una diversa per ogni rele' ovviamente, che puoi chiamare come vuoi ed alle quali cambi stato insieme ai rele', cosi lo sketch sa in che stato e' il rele', ed il relativo ciclo if di controllo risponde solo al pulsante associato a quella flag ...

Grazie ad entrambi per avere risposto!
Non avevo pensato ai rimbalzi che potrebbero essere generati...
diciamo che mi sono chiarito un po le idee e grazie alle vostre precisazioni sono riuscito a risolvere, ecco il codice di base funzionante:

// Esempio 04: antirimbalzo2 - accendi il led appena è premuto il pulsante mantenendolo acceso quando si rilascia  
// premendo una seconda volta il pulsante spegne il led  
  
#define LED 11                // LED collegato al pin digitale 13  
#define BUTTON A2              // pin di input dove è collegato il pulsante  
int val = 0;                  // si userà val per conservare lo stato del pin di input  
int vecchio_val = 1023;          // si userà vecchio_val per conservare lo stato del pin di input al passo precedente  
int stato = 0;                // ricorda lo stato in cui si trova il led, stato = 0 led spento, stato = 1 led acceso  
  
void setup() { 
  Serial.begin(9600);
  pinMode(LED, OUTPUT);       // imposta il pin digitale come output  
  pinMode(BUTTON, INPUT);     // imposta il pin digitale come input  
}  
  
void loop() {  
  val = analogRead(BUTTON);
  Serial.print(val);
    Serial.print("\n");
  
  // controlla se è accaduto qualcosa  
  if ((val == 0) && (vecchio_val == 1023)){  
    stato = 1 - stato;  
    delay(15);                // attesa di 15 millisecondi  
  }   
  vecchio_val = val;            // ricordiamo il valore precedente di val  
  Serial.print("VECCHIO VAL 1:");
    Serial.print(vecchio_val);

  
    if (stato == 1) {  
    digitalWrite(LED, LOW);   // accende il led  
  }   
  else {  
    digitalWrite(LED, HIGH);    //spegne il led  
  }    
}

Grazie mile :slight_smile: