Pages: [1]   Go Down
Author Topic: Antirimbalzo avanzato - Buffer circolare  (Read 899 times)
0 Members and 1 Guest are viewing this topic.
Fidenza (PR)
Offline Offline
Full Member
***
Karma: 3
Posts: 143
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao, volevo condividere con voi questo piccolo sketch per gestire in un modo un po alternativo l'antirimbalzo di un bottone. Sembra una cosa da poco ma una gestione del genere potrebbe essere utile per gestire poi con Arduino anche una piccola tastiera perchè in questo modo evito degli stalli del codice.

In pratica creo un buffer circolare per evitare di attendere anche poco tempo in un applicazione embedded. Si tratta di creare un piccolo automa che viene richiamato ad intervalli di tempo fissi, ad esempio lo richiamo all’interno di una routine di interrupt di un timer o cose simili. Ad ogni interrupt viene letto lo stato dell’ingresso, supponiamo che con il pulsante non premuto sia a 0. Lo stato del pulsante viene memorizzato in una variabile intera, es. un byte non prima di aver shiftato il suo contenuto a sx di una posizione (0)00000000. Quando il pulsante viene premuto viene premuto e per la prima volta viene letto lo stato a 1, il contenuto del byte diventa (1)000001.  Se al passaggio successivo per un rimbalzo lo stato è a zero si avrà (2)00000010. Se al passaggio successivo lo stato viene riconosciuto a 1 si avrà (3)00000101. Ne passaggi successivi ad ogni passo l’evoluzione risulta:
(4 ) 00001011
(5)  00010111
(6)  00101111
(7)  01011111
(smiley-cool  10111111
(9)  01111111
(10)11111111
Se ad ogni passo verifichi se il contenuto del byte risulta pari a 01111111 e assegni a questo valore il riconoscimento del pulsante premuto ti  rendi conto che solamente al passaggio (9) riconosci la pressione del pulsante.
Analogamente se vuoi rilevare il rilascio del pulsante senza rimbalzo puoi controllare che il contenuto sia ad esempio 11111110.

per l'esempio non ho utilizzato l'interrupt ma una chiamata in polling.

Code:

#define KEY_OFF 1000
#define KEY_PRESS 1001
#define KEY_HOLD 1011
#define KEY_REL 1010
#define btnPin 3
#define ledPin 13

//byte per lo stato del bottone
byte btnStatus = 0x0;

void setup(){
   pinMode(btnPin, INPUT);
   pinMode(ledPin, OUTPUT);
}

void loop(){
  if(getInputSwitchStatus() == KEY_PRESS){
    digitalWrite(ledPin, HIGH);
  }
  if(getInputSwitchStatus() == KEY_HOLD){
    //BOTTONE PREMUTO
  }
  if(getInputSwitchStatus() == KEY_REL){
    digitalWrite(ledPin, LOW);
  }
}

int getInputSwitchStatus(){
  //SFHIT stato tasto
  btnStatus <<= 1;
  if(digitalRead(btnPin)){
    btnStatus |= 0x01;
    delay(10);
  }
  if( btnStatus == 0 ) return KEY_OFF;
  else if( btnStatus == 0x7F ) return KEY_PRESS;
  else if( btnStatus == 0xFF ) return KEY_HOLD;
  else if( btnStatus == 0xFE ) return KEY_REL;
  else return "KEY_NO_PRESS";
}


che ve ne pare?
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Personalmente adotto 2 letture digitali intervallate da un delay(30), tecnica che non ha mai fallito (almeno per me).
Logged


Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 120
Posts: 9158
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Personalmente adotto 2 letture digitali intervallate da un delay(30), tecnica che non ha mai fallito (almeno per me).

Sopratutto se il delay è ottenuto tramite un controllo non bloccante, p.e. con la millis, semplice, funzionale e perfettamente funzionante, a seconda del tipo di contatti può essere necessario portare il tempo di attesa fino a 100 ms.
Usare un buffer circolare per l'antirimbalzo è una complicazione inutile, la tecnica del ritardo dal momento del primo cambio di stato è più sufficiente e non comporta nessun blocco nel programma se gestito tramite millis()/timer.

Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Personalmente adotto 2 letture digitali intervallate da un delay(30), tecnica che non ha mai fallito (almeno per me).

Sopratutto se il delay è ottenuto tramite un controllo non bloccante, p.e. con la millis, semplice, funzionale e perfettamente funzionante, a seconda del tipo di contatti può essere necessario portare il tempo di attesa fino a 100 ms.
Sì, con i pulsanti non switch basta un intervallo leggermente maggiore.
Logged


Fidenza (PR)
Offline Offline
Full Member
***
Karma: 3
Posts: 143
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ma se devo gestire una tastiera forse conviene questa soluzione, cosi evito stalli inutili (anche quei 30ms fanno la differenza)
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Usando i millis non hai stalli.
Logged


Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 120
Posts: 9158
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ma se devo gestire una tastiera forse conviene questa soluzione, cosi evito stalli inutili (anche quei 30ms fanno la differenza)

Non esistono stalli inutili se gestisci i ritardi tramite timer/millis, in tutti i casi i rimbalzi esistono per un determinato tempo e devi comunque aspettare che terminano, anche utilizzando 100 ms come ritardo vuol dire poter premere 10 tasti, o 10 volte lo stesso tasto, al secondo, per un essere umano è quasi impossibile farlo.
Logged

Genova
Offline Offline
Faraday Member
**
Karma: 37
Posts: 3233
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Personalmente preferisco un " Pre-Antirimbalzo avanzato" hardware.
Logged

no comment

Pages: [1]   Go Up
Jump to: