Accendere LED con 2 pulsanti?

Salve, avrei in mente di accendere un LED utilizzando 2 pulsanti: premo il primo pulsante, se entro 2 secondi non premo l’altro pulsante non succede nulla altrimenti si accende il LED. Ho provato a scrivere qualcosa del genere ma non funziona:

#include <IRremote.h>
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
IRsend irsend;
decode_results results; 
     int stato_riavvio_router_voip = 1; 
     int lettura_pulsante_riavvio_router_voip; 
     int valore_precedente_pulsante_riavvio_router_voip = LOW; 
     int lettura_pulsante_conferma_azione;
     int valore_precedente_lettura_pulsante_conferma_azione = LOW;
     unsigned long tempo_riavvio_router_voip = 0;
     unsigned long tempoCorrente_riavvio_router_voip;
     
void setup() {
     irrecv.enableIRIn();
     digitalWrite (8, LOW);  
}

void loop(){
     {if (irrecv.decode(&results)) {Serial.println(results.value, HEX); irrecv.resume();}}
     lettura_pulsante_conferma_azione = results.value == 0xFF38C7;
     lettura_pulsante_riavvio_router_voip = results.value == 0xFF906F;

    if (stato_riavvio_router_voip == 1 && lettura_pulsante_riavvio_router_voip == HIGH  ) {stato_riavvio_router_voip = 0;lettura_pulsante_riavvio_router_voip=LOW;tempo_riavvio_router_voip =millis();}
    while (stato_riavvio_router_voip == 0 && tempoCorrente_riavvio_router_voip - tempo_riavvio_router_voip > 2000){ stato_riavvio_router_voip = 1 ;}
    if (stato_riavvio_router_voip == 0 &&  lettura_pulsante_conferma_azione == HIGH ) {digitalWrite(8,HIGH);lettura_pulsante_conferma_azione=LOW;stato_riavvio_router_voip = 1;}
    
}

I pulsanti sarebbero dei tasti di un telecomando ir. Se elimino la stringa

while (stato_riavvio_router_voip == 0 && tempoCorrente_riavvio_router_voip - tempo_riavvio_router_voip > 2000){ stato_riavvio_router_voip = 1 ;}

funziona perfettamente senza però nessun timeout dopo aver premuto il primo interruttore.
Come posso aggiustarlo? Grazie!

mah..... per vedere HIGT LOW BASTEREBBE UN byte, un int mi sembra esagerato

verificare direttamente un pulsante senza un debounce è sempre un errore perché prima o poi darà malfunzionamenti

Ho aggiunto il debounce:

     int stato_riavvio_router_voip = HIGH; 
     int lettura_pulsante_riavvio_router_voip; 
     int valore_precedente_pulsante_riavvio_router_voip = LOW; 
     int lettura_pulsante_conferma_azione;
     int valore_precedente_lettura_pulsante_conferma_azione = LOW;
     unsigned long tempo_riavvio_router_voip = 0;
     unsigned long tempoCorrente_riavvio_router_voip;
     
void setup() {
digitalWrite (8, LOW);  

}



void loop()
     {
     {tempo_riavvio_router_voip =millis();
    if (stato_riavvio_router_voip == 1 && lettura_pulsante_riavvio_router_voip == HIGH && valore_precedente_pulsante_riavvio_router_voip == LOW && tempoCorrente_riavvio_router_voip - tempo_riavvio_router_voip > 200 ) {stato_riavvio_router_voip = 0;}
    tempo_riavvio_router_voip =millis();
    if (stato_riavvio_router_voip == 0 && lettura_pulsante_conferma_azione == HIGH && valore_precedente_pulsante_conferma_azione == LOW && tempoCorrente_riavvio_router_voip - tempo_riavvio_router_voip > 200) {Riavvio_Router_Voip = 1;}
    if ( tempoCorrente_riavvio_router_voip - tempo_riavvio_router_voip > 2000) {stato_riavvio_router_voip = 1;}
    
     }

il codice è ancora da perfezionare... ho utilizzato un int perchè non conosco un altro metodo...
Neanche in questo caso il timeout funziona.

Nessuna idea?

forse non ho capito cosa vuoi fare ma dal tuo codice mi sembra tutto davvero molto complicato, penso sia molto più semplice alla pressione del primo pulsante entrare in un ciclo dove con mills controlli il tempo di 2 secondi e intanto leggi se il secondo pulsante è stato premuto, se si, accende il led, se no esce dal ciclo dopo i 2 secondi e ricomincia daccapo… rimane da decidere una volta che il led è acceso come si deve spegnere

-zef-:
forse non ho capito cosa vuoi fare ma dal tuo codice mi sembra tutto davvero molto complicato, penso sia molto più semplice alla pressione del primo pulsante entrare in un ciclo dove con mills controlli il tempo di 2 secondi e intanto leggi se il secondo pulsante è stato premuto, se si, accende il led, se no esce dal ciclo dopo i 2 secondi e ricomincia daccapo… rimane da decidere una volta che il led è acceso come si deve spegnere

Quello che ho scritto è l’unica cosa che mi è venuta in mente, è complicato ma almeno la metà di quello che vorrei fare lo esegue :smiley:
Quello che hai scritto è esattamente ciò che voglio fare. Alla fine del ciclo il led deve rimanere acceso ma quel pezzo di codice deve continuare a funzionare, cioè accendo il led utilizzando quel codice, poi magari lo spengo con un altro pulsante o in un’altro modo e se voglio riaccenderlo devo premere quella combinazione di tasti.
La cosa che mi blocca è come controllare se sono passati 2 secondi, in tal caso rincomincia il codice dall’inizio altrimenti se viene premuto il secondo pulsante accende il led, mi funziona o uno o l’altro.

per i due secondi di attesa devi per forza utilizzare mills() così puoi controllare se in quei due secondi viene premuto o no il secondo pulsante, se usi un delay hai si la pausa di due secondi ma non hai modo di verificare se il pulsante è stato premuto. Altro modo che penso possa funzionare e senza utilizzare cicli while è di associare ad una variabile il valore di mills() quando viene premuto il primo tasto e poi con un if controlli se mills() ha un valore più basso della variabile+2000 e se il pulsante 2 viene premuto, se entrambe sono vere accendi il led.

Ho scritto questo (riporto solo la parte nel loop, le altre parti rimangono invariate):

   {
     {tempo_riavvio_router_voip =millis();
    if (stato_riavvio_router_voip == 1 && lettura_pulsante_riavvio_router_voip == HIGH && valore_precedente_pulsante_riavvio_router_voip == LOW && tempoCorrente_riavvio_router_voip - tempo_riavvio_router_voip > 200 ) {stato_riavvio_router_voip = 0;tempo_riavvio_router_voip =millis();}  
    if (stato_riavvio_router_voip == 0 && tempoCorrente_riavvio_router_voip - tempo_riavvio_router_voip > 2000){stato_riavvio_router_voip = 1;}
    if (stato_riavvio_router_voip == 0 && lettura_pulsante_conferma_azione == HIGH && valore_precedente_pulsante_conferma_azione == LOW ) {analogWrite (12, LOW);} 
    
     }}

Non funziona lo stesso, se passano i 2 secondi continua a funzionare.
Ho provato anche a fare qualcosa del tipo millis<variabile+2000 (dove variabile è il valore di millis quando viene premuto il primo tasto) ma non va.
Come dovrei scrivere affinché si resetti passati 2 secondi?

la riga con tempo_riavvio_router_voip =millis(); non deve essere nello stesso ciclo con gli if, in tal caso ogni volta che viene rieseguito il ciclo tempo_riavvio_router_voip avrà sempre lo stesso valore di millis() e non avrai mai mills con 2000 millisecondi in più, inoltre continuo a non capire tutto il resto a cosa serve se vuoi solo poter accendere un led se viene premuto un ulteriore pulsante entro due secondi. Prova a realizzare il codice con solo due pulsanti e un led e poi una volta che funziona implementi tutto il resto.

il loop dove controlli i tasti
{

if tasto_uno_premuto == true{
tempo = mills() + 2000
}

if tasto_due_premuto == true and mills() < tempo
accendi_led
}

salvo errori (molto probabili vista l’ora) con solo due if controllo entrambi i pulsanti, verifico se il secondo pulsante viene premuto entro due secondi e in tal caso accendo il led.

P.S. calcola che se devi tenere acceso il tutto 24h su 24 7gg su 7 dopo (non mi ricordo quanti giorni) mills va in overflow e andrebbe gestito di conseguenza ma risolviamo una cosa alla volta :wink:

-zef-:
P.S. calcola che se devi tenere acceso il tutto 24h su 24 7gg su 7 dopo (non mi ricordo quanti giorni) mills va in overflow e andrebbe gestito di conseguenza ma risolviamo una cosa alla volta :wink:

Allora basta fare i calcoli in modo che l’overflow non comporti nulla :wink:

il loop dove controlli i tasti

if tasto_uno_premuto == true{
tempo_iniziale = mills()
}

if tasto_due_premuto == true and mills() - tempo_iniziale < 2000 {
accendi_led
}

A dire il vero ci sarebbe ancora un piccolo “difetto”, se non si preme più il tasto_uno allora ogni quarantanove e fischia giorni la seconda condizione potrebbe tornare vera per due secondi, per cui in quei due secondi basterebbe premere il solo tasto_due :slight_smile:

Claudio_FF:
A dire il vero ci sarebbe ancora un piccolo "difetto", se non si preme più il tasto_uno allora ogni quarantanove e fischia giorni la seconda condizione potrebbe tornare vera per due secondi, per cui in quei due secondi basterebbe premere il solo tasto_due :slight_smile:

quello sarebbe il male minore, temo invece che se si preme il tasto_uno proprio un secondo prima che mills() vada in overflow e quindi riparte da 0 si avrebbe la possibilità di premere il tasto_due per tutti i 49 giorni o almeno finché non venga premuto di nuovo il tasto_uno :o

Con la sottrazione intera senza segno a 32 bit il risultato viene sempre giusto.

Ipotizziamo che manchi un secondo all'overflow, millis() ritorna 4’294’966’296 e lo salviamo in tempo_iniziale.

Passa un secondo e mezzo, rileggiamo millis() e otteniamo 500

Ora (500 - 4’294’966’296) & 0xFFFFFFFF = 1500

L' and con 0xFFFFFFFF è implicito in ogni operazione intera a 32 bit.

interessante questa non la sapevo, grazie! :slight_smile: