rilevare 3 tipi di pressioni di un pulsante

Ciao, volevo chiedere se qualcuno aveva già provato a gestire 3 sequenze di pressioni di un pulsante, tipo:

a - una pressione unica e veloce

b - una pressione unica, ma prolungata

c - due pressioni veloci in breve tempo

Ho trovato una libreria che rileva se è una pressione corta oppure lunga, ma basta

Questa ottima libreria fa esattamente quel che vuoi: https://github.com/mathertel/OneButton.

Grazie, evito di dover reinventare la ruota :)

Ottima idea! Poi se vuoi capire come funziona è sempre interessante ;).

andrea86: Ciao, volevo chiedere se qualcuno aveva già provato a gestire 3 sequenze di pressioni di un pulsante, tipo:

a - una pressione unica e veloce

b - una pressione unica, ma prolungata

c - due pressioni veloci in breve tempo

Ho trovato una libreria che rileva se è una pressione corta oppure lunga, ma basta

personalmente "risolverei" senza librerie anche perché quello che intendi tu per veloce non lo è per un altro

se "scrivi tu " hai la possibilità di intervenire con il debouce se necesssario

La libreria proposta gestisce già il debounce, inoltre permette di configurare facilmente il tempo "lungo".

È una libreria ben fatta, non c'è motivo di non usarla e di crearne, debuggarne e testarne un'altra. Tra l'altro è anche molto ben documentata e spiega chiaramente la macchina a stati che utilizza internamente.

Premesso che non credo di avere le competenze necessarie ad “inventare” una libreria … ma che bisogno c’e’ di farlo ? … non bastano alcuni if ?

Ad esempio, il mio vecchio esempio di rilevazione per la pressione lunga o corta, non potrebbe essere modificato per rilevare anche un paio di pressioni corte ?

// Esempio per diverse operazioni con pressioni di durata diversa (piu o meno 
// di mezzo secondo, in questo esempio, ma puo essere qualsiasi intervallo di tempo)
// Ovviamente, in questo caso le operazioni sono eseguite solo al rilascio del tasto

   st = digitalRead(pin)	 //leggi ingresso pulsante
   if ((st != stp) && (stp == 0)) // pulsante appena premuto
   {
      stp = st; 	//setta flag per pulsante premuto
      millis_p = millis();	//setta variabile controllo tempo
   }
   if ((st != stp) && (stp == 1)) //pulsante appena rilasciato
   {
      stp = st; 	//resetta flag per pulsante rilasciato
      if (millis() - millis_prec <= 500) //pulsante premuto per meno di mezzo secondo
      {
      //qui ci vanno tutte le operazioni da compiere al RILASCIO del tasto, 
      //UNA SOLA VOLTA, se il tasto e' rimasto premuto per meno di 500mS
      }
      else
      {
      //qui vanno tutte le operazioni da compiere al RILASCIO del tasto, 
      //UNA SOLA VOLTA, se il tasto e' rimasto premuto per piu di 500mS
      }
   }
   
// puo essere usato anche per piu intervalli di tempo diversi, non solo due tempi

secondo me’ basta aggiungere un’altro ciclo if che controlla se il pulsante viene ripremuto entro “tot” millisecondi quando la prima pressione e’ breve (altrimenti non verrebbero considerate due pressioni consecutive … ovviamente questo introdurrebbe un ritardo nell’esecuzione delle istruzioni pari alla pausa massima richiesta fra le due pressioni brevi, ma da questo non ci si scappa, altrimenti non sarebbe possibile rilevare la differenza fra una e due pressioni brevi), e mettere delle semplici flag al posto delle istruzioni, poi una volta terminati gli if principali, si controllano le flag e si agisce di conseguenza … o no ?

Ognuno è libero di fare come preferisce, ma mettere in piedi questa cosa sembra più facile di quel che è in realtà. La libreria proposta usa una macchina a stati adatta allo scopo è facilmente estendibile se servisse anche triplo click o altro. Ad esempio nel mio NES++ ho scritto io il codice, perché mi serviva il doppio click con tasto mantenuto premuto al secondo, ma l'ho fatto usando la stessa macchina a stati un po' estesa. Secondo me è l'approccio corretto.

Mah, non so come funzioni quella libreria, ma ho provato a buttare giu due righe al volo (non posso provarle, ma in teoria sembrano relativamente corrette) … si potrebbe creare una funzione da richiamare ogni volta che serve, con dentro una cosa del genere, e che all’uscita restituisca una variabile “press” …

   st = digitalRead(pin)	 //leggi ingresso pulsante
   if ((st != stp) && (stp == 0) && (numpres == 0)) // pulsante appena premuto prima volta
   {
      stp = st; 	//setta flag per pulsante premuto
	  numpres = 1;  //setta flag per prima pressione
      millis_p = millis();	//setta variabile controllo tempo pulsante
   }
   if ((st != stp) && (stp == 1) && (numpres == 1)) //pulsante rilasciato prima volta
   {
      millis_r = millis();	//setta variabile controllo tempo rilascio
      stp = st; 	//resetta flag per pulsante rilasciato
      if (millis() - millis_p <= 500) //pulsante premuto per meno di mezzo secondo
      {
      press = 1;  //prima pressione breve
      }
      else
      {
      press = 2;  //prima pressione lunga
      }
   }
   if ((millis() - millis_r <= 510) && (press == 1))  //controllo per 510ms se nel frattempo viene ripremuto il pulsante
   {                                                  //ma solo in caso di prima pressione breve, altrimenti esco
      if ((st != stp) && (stp == 0) && (numpres == 1)) // pulsante appena premuto seconda volta entro 500ms dal primo rilascio
      {
         stp = st; 	//setta flag per pulsante premuto
         numpres = 3;  //setta flag per seconda pressione breve
         millis_p = millis();	//setta variabile controllo tempo pulsante
      }
      if ((st != stp) && (stp == 1) && (numpres == 3)) //pulsante rilasciato seconda volta
      {
         stp = st; 	//resetta flag per pulsante rilasciato
         press = 3;  //due pressioni brevi
      }
   }

all’uscita, press dovrebbe valere 1 se c’e’ stata una sola pressione breve (meno di mezzo secondo), oppure 2 se la pressione e’ stata piu lunga di mezzo secondo, oppure 3 se ci sono state due pressioni brevi intervallate da meno di mezzo secondo … ovviamente in caso di singola pressione breve il valore valido lo si avra’ solo dopo il mezzo secondo di attesa, che serve per controllare che non ci sia la seconda pressione breve, mentre gli altri due sarebbero validi dal momento dell’ultimo rilascio del tasto … il vantaggio, se e’ vero che quella libreria rileva solo se c’e’ stata una pressione lunga o breve, e’ che con questo sistema potresti rilevarci anche differenti combinazioni di lunghezze e pressioni, basterebbe cambiare i tempi e/o aggiungere cicli di controllo all’occorrenza …

… chissa’ se la si puo addirittura trasformare in una libreria piu completa di quella :smiley:

La libreria rileva singolo click, doppio click e pressione prolungata.

Quel che ho fatto io è qua: https://github.com/SukkoPera/NESPlusPlus/blob/master/NESPlusPlus.ino, funzione handle_reset_button().

Io devo rilevare questi 3 tipi di pressioni su 8 ingressi digitali:

a) singola veloce -> commuta accesa/spenta la lampadina impostata per quell'ingresso b) doppia veloce -> spegni tutto il gruppo c) prolungata -> aumenta di 1/5 la luminosità della lampadina impostata per quell'ingresso (raggiunto il max ricomincia dal min)

Le lampadine sono dei modelli HUE della Philips e per comandarle devo inviare delle richieste HTTP al loro bridge.

Con questa libreria mi sono trovato parecchia pappa pronta, ma se qualcuno vuole condividere qualcosa di migliore non posso che ringraziarlo.