Pressione pulsante.

Buon giorno, sto diventando matto con il pulsante...nn sembra difficile eppure...vi spiego cosa devo fare:ho un pulsante che a riposo è pull up, quando lo premo entro in una voce di un menù una volta dentro, ho una variabile che va on o off premendo lo stesso pulsante. A questo punto per uscire premo lungo-più di 1 sec. Ho provato diverse soluzioni, Ma nulla...quando premo lungo nn mi deve cambiare lo stato della variabile impostata... qualche suggerimento?? Grazie

Ciao! Utilizzando un unico pulsante ti complichi la vita, comunque se è quello che vuoi :wink:

Come dovresti fare “il codice si complica e prevede l’uso di millis()”

  1. Alla pressione del pulsante inizio a conteggiare il tempo
  2. Rilasciato il pulsante faccio un controllo, se il tempo di pressione è inferiore al secondo cambio stato, altrimenti se il tempo di pressione è superiore al secondo esco dal menu.

Esempio:

unsigned long tempo=0;

unsigned long risulatato=0;

if(digitalRead(pulsante)==LOW){

       tempo=millis();
       while(digitalRead(pulsante)==LOW){//Finché il pulsante è premuto

             risultato=millis()-tempo;

       }
}

// Rilasciando il pulsante termina il while e esce dall'if


if(risultato<=1000)
    stato=!stato;
else if(risultato>1000)// E' stato premuto per più di un secondo

      // Esco dal menù

Se vuoi la vita facile: https://github.com/mathertel/OneButton

manolomao: Buon giorno, sto diventando matto con il pulsante...nn sembra difficile eppure...

La difficoltà dipende anche da come si struttura il codice (bloccante / non bloccante ecc).

In un loop che gira senza blocchi non è difficile usare due variabili impulsive 'onClick' e 'onPress' che diventano vere per un ciclo quando vengono rilevati gli eventi con una piccola macchinetta a stati:

void loop()
{
    onClick = false;
    onLongPress = false;

    if      ((0 == s) && (digitalRead(PULSANTE) == LOW))  { s = 1;  t = millis();       }
    else if ((1 == s) && (digitalRead(PULSANTE) == HIGH)) { s = 0;  onClick = true;     }
    else if ((1 == s) && ((millis() - t) >= 1000))        { s = 2;  onLongPress = true; }
    else if ((2 == s) && (digitalRead(PULSANTE) == HIGH)) { s = 0;                      }
    else                                                  {                             }

    ...qui il resto del programma (non bloccante) che usa onClick e onLongPress...

}

L’ azione del pulsante premuto corto devi farla partire non alla pressione del pulsante ma al suo rilascio. L’ azione del pulsante premuto a lungo puoi farla partire al tempo scaduto dopo la pressione del pulsante.

esempi:
pulsante premuto per 0,3s. L’azione corta la fai partire dopo il ripascio dopo 0,3s.
Pulsante premuto per 3s. L’ azione lunga la fai pertire dopo 1 s.

Ciao Uwe

Claudio_FF il tuo esempio è super, e soprattutto non è bloccante... Questa cosa della macchina a stati finiti ancora non riesco a capirla... Ad ogni modo ho ancora una cosa da chiederti: ho fatto come hai scritto tu

 onClick = false;
    onLongPress = false;
    val = digitalRead(encoderSW);
    if      ((0 == s) && (val == LOW))  { s = 1;  tempo = millis();       }
    else if ((1 == s) && (val == HIGH)) { s = 0;  onClick = true;     }
    else if ((1 == s) && ((millis() - tempo) >= 1000))        { s = 2;  onLongPress = true; }
    else if ((2 == s) && (val == HIGH)) { s = 0;                      }

    if (onClick==true && abilito==false){abilito=true;}
    if (onLongPress==true && abilito==true){abilito=false;}

abilito serve a discriminare se entro nella voce del menu o se entro nella selezione on off della variabile.

if (abilito) {
if (onClick==true){if(bitRead(flag,i)==0){bitSet(flag,i);}
                                                                       else{bitClear(flag,i);}}

a questo punto dopo essere entrato nella voce ripremendo brevemente il pulsante seleziono on off la variabile flag. Pressione lunga esce dalla voce e passa alla successiva. Tutto funziona bene, solo una cosa un po' fastidioa che non mi piace e ti chiedo come fare... Quando entro nella voce mi cambia stato subito alla variabile, mentre io vorrei aspettare di ripremere il pulsante.... Grazie per l'aiuto

Come sopra, bisogna solo distinguere tra diversi stati:

if      ((0 == z) && onClick())     { z = 1;                               }
else if ((1 == z) && onClick())     { ...cambia variabile ad ogni click... }
else if ((1 == z) && onLongPress()) { z = 0;                               }
else                                {                                      }

Claudio_FF, ho fatto come dici ma fa uguale... Premo e entra nella voce e subito cambia lo stato della variabile..... :confused:

Dare un'occhiata a quello che ho consigliato io costa troppo? A quest'ora avresti già risolto.

Fate perdere la voglia di rispondere, se non fate nemmeno lo sforzo di guardare quel che vi si dice.

SukkoPera: Se vuoi la vita facile: https://github.com/mathertel/OneButton

Libreria salvata! Interessante, anche solo leggere gli esempi.

Scusa sukkopera, ma pensavo di seguire la strada di Claudio xche mi sembrava più semplice... Provo di guardarci e vedo cosa riesco a fare... Ma il tempo della pressione lunga è fisso o variabile?? Se fisso a quanto? Se variabile come si setta?

Claudio_FF, trovato l'inghippo

    else if ((2 == s) && (val == HIGH)) { s = 0;  z=0;}

aggiungendo z=0 durante il lungo resetto il controllo e fa quello che volevo. Grazie. Sukkopera, studierò la libreria grazie anche a te.

manolomao: aggiungendo z=0 durante il lungo resetto il controllo e fa quello che volevo.

In teoria non doveva servire, evidentemente il resto della tua logica è strutturata in un certo modo tale da richiedere al processo del pulsante di controllare direttamente lo stato del processo gestito con la variabile 'z'.