Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

Chiarimenti debouncing con Timer0

Raccolta di codici sorgenti

Moderatore: Foto UtentePaolino

0
voti

[11] Re: Chiarimenti debouncing con Timer0

Messaggioda Foto Utentegrandegiove » 29 dic 2015, 9:08

Ciao Foto Utenteobiuan,
non ho capito l'approccio che suggerisci: è solo una questione di entità dello scheduling (10 ms ti sembrano troppi?) o suggerisci proprio un diverso approccio?

obiuan ha scritto: L'approccio comune è mettere l'antirimbalzo nella ISR associata all'interrupt del pulsante stesso (metodo + e - suggerito da lelerelele :ok: )


Mi serve comunque una base dei tempi fornita da un timer o da un ISR?

Mi sembra che l'approccio al quale era arrivato Foto UtenteDavide90 correggendo un po' il tiro rispetto all'ipotesi iniziale non fosse male ovvero:
- ISR che rileva fronti di salita e discesa (discriminandoli) del pulsante.
- Variabile incrementale nella ISR di un timer (nel suo caso 10 ms ma si potrebbe correggere il tiro abbassando la base dei tempi) che mi permette di contare il tempo fra i fronti rilevati.

In questo modo può (eventualmente su base empirica facendo qualche prova col suo tasto) decidere di tener buona una pressione se si è scatenato un evento di fronte di salita e per un certo tempo il valore è rimasto alto senza che occorressero altri fronti.

In ogni caso mi sembra che con questo approccio avesse tutti gli elementi per stabilire un criterio di rilevazione di una reale pressione senza alcuna interruzione del flusso principale.

Al contrario nell'approccio proposto da Foto Utentelelerelele

lelerelele ha scritto:Non è necessario, implementi una routine che deve essere ritardata, la richiami dal main (o chi per esso),
una volta ogni N passaggi, hai gia implementato un ritardo senza per questo interrompere lo scorrimento del programma principale.
in più occasioni l'ho realizzato caricando una variabile in + ogni volta che il contatto è alto, in - quando leggo il contatto in basso, determinando se è sopra o sotto sai se è premuto oppure no, devi solo impostare i limiti del conteggio, diciamo +-100..
saluti.


Sbaglio o in questo caso se cambia il tempo di esecuzione del main (per esempio perché ho la necessità di aggiungere del codice che gestisce una nuova periferica) cambia anche l'entità del filtro antirimbalzo? Mi sembra che questo sia poco auspicabile.

Se mi sfugge qualcosa mi scuso :oops:

Buona giornata!
Avatar utente
Foto Utentegrandegiove
1.072 1 4 8
Expert
Expert
 
Messaggi: 513
Iscritto il: 18 ott 2010, 9:59

-1
voti

[12] Re: Chiarimenti debouncing con Timer0

Messaggioda Foto Utentelelerelele » 29 dic 2015, 10:52

grandegiove ha scritto:Al contrario nell'approccio proposto da Foto Utentelelerelele
--------
Sbaglio o in questo caso se cambia il tempo di esecuzione del main (per esempio perché ho la necessità di aggiungere del codice che gestisce una nuova periferica) cambia anche l'entità del filtro antirimbalzo? Mi sembra che questo sia poco auspicabile.

Certamente, il tempo così ottenuto dipende dai cicli di programma eseguiti, quindi cambia a seconda del programma che esegua una funzione in più od in meno, a seconda che un salto venga eseguito una volta oppure più volte.
Certamente questo approccio non va bene se si deve misurare con precisione un tempo tra due eventi, in questo caso si deve usare l'hardware del controllore, CTMU, oppure CAPTURE tramite contatore e latch hardware.
In questo caso stiamo parlando di rimbalzi di un contatto meccanico, il quale può avere tempi che variano anche di 10 volte, secondo me il tempo di così ottenuto non effetti negativi in questo caso.

saluti.
Avatar utente
Foto Utentelelerelele
2.196 3 7 8
Expert EY
Expert EY
 
Messaggi: 2514
Iscritto il: 8 giu 2011, 8:57
Località: Reggio Emilia

0
voti

[13] Re: Chiarimenti debouncing con Timer0

Messaggioda Foto Utentegrandegiove » 29 dic 2015, 12:40

lelerelele ha scritto:Certamente, il tempo così ottenuto dipende dai cicli di programma eseguiti, quindi cambia a seconda del programma che esegua una funzione in più od in meno, a seconda che un salto venga eseguito una volta oppure più volte.
saluti.



Ciao Foto Utentelelerelele, grazie della risposta
Non riesco a capire questo passaggio.

Con questo codice:

Codice: Seleziona tutto
void Main (void){
UINT8 r=1000;

while(1){
//.......
//cicli che vengono eseguiti a tutta velocità
//........

if (r==0){
Ritardo_sub();//ciclo che viene eseguito una volta ogni 1000 passaggi per il main
r=1000;}
else r--;

}
}


Se la durata dei "cicli che vengono eseguiti a tutta velocità" durasse 1 microsecondo, finisco per tener buono gli impulsi lunghi almeno 1 millisecondo. Se durasse 10 volte tanto 10 millisecondi e via dicendo. Ogni incremento del tempo di esecuzione del main si ripercuote moltiplicato per mille sul coefficiente del filtro. Se paradossalmente avessi una scrittura su un lcd che dura 10 ms nel main, la pressione minima diventerebbe di 10 secondi.

Credo che sia assolutamente opportuno utilizzare una base dei tempi svincolata dal main come l'interrupt di un timer, come peraltro l'utente ha detto di aver usato con successo già dai primi messaggi

ho riscritto la routine debouncing e funziona alla perfezione, simulando il tutto, bisognerà poi vedere nella realtà!


Non vedo quali siano i limiti della soluzione proposta da lui (rivista alla luce di evitare l'overflow delle variabili di conteggio temporale) e vedo poco auspicabile utilizzare un debouncing con coefficiente che dipende totalmente dal ciclo di esecuzione.
Avatar utente
Foto Utentegrandegiove
1.072 1 4 8
Expert
Expert
 
Messaggi: 513
Iscritto il: 18 ott 2010, 9:59

0
voti

[14] Re: Chiarimenti debouncing con Timer0

Messaggioda Foto Utentelelerelele » 29 dic 2015, 13:34

io non ho mai realizzato un sistema del genere, in quanto non mi pare indispensabile andare a campionare in modo così preciso la lettura di ingresso....ho sempre preferito usare un sistema ad accumulo, riesci a mediare con precisione un valore letto all'ingresso.
L'ho usato anche per filtrare la lettura di un sensore touch, con una marea di letture,ed il risultato è stato buono.

Non ho affermato che sia migliore il mio metodo rispetto al suo, lo scopo era solamente proporne un altro. Alla fine è utile trovare il sistema migliore in riferimento all'impiego specifico.

Saluti.
Avatar utente
Foto Utentelelerelele
2.196 3 7 8
Expert EY
Expert EY
 
Messaggi: 2514
Iscritto il: 8 giu 2011, 8:57
Località: Reggio Emilia

0
voti

[15] Re: Chiarimenti debouncing con Timer0

Messaggioda Foto Utentemarioursino » 17 feb 2016, 14:59

Io spesso faccio così se ho un timer libero:

Alla pressione del pulsante:

- Setto un flag
- Avvio un timer
- Al rollover del timer disabilito il flag

In questo modo se si verificano altre commutazioni durante lo scorrere del timer non si esegue alcuna istruzione (basta controllare il flag).

In XC8, supponendo di usare Timer0:

Codice: Seleziona tutto
char debouncing = 0;

void main()
{
   // Loop principale
}

void interrupt routine()
{
   if(RBIF)
   {
      RBIF = 0;
     
      if(debouncing)
         return;

      TMR0 = 0;
      T0IF = 0;
      T0IE = 1;
      debouncing = 1;

      // Gestisci la pressione del pulsante
   }

   if(T0IF)
   {
      debouncing = 0;
      T0IE = 0;
      T0IF = 0;
   }
}


PS: gli interrupt sono comunque catturati durante le routine __delay_ms() e __delay_us(), sia nelle XC8 che con le librerie vecchie (a meno che, chiaramente, non si disabiliti GIE o PEIE).
Avatar utente
Foto Utentemarioursino
3.687 3 9 13
G.Master EY
G.Master EY
 
Messaggi: 1314
Iscritto il: 5 dic 2009, 4:32

0
voti

[16] Re: Chiarimenti debouncing con Timer0

Messaggioda Foto Utenteluxinterior » 17 feb 2016, 15:35

Io di solito uso un timer lento che c'è già per altri scopi (io lo chiamo basic timer)
Faccio letture periodiche ogni 10/20ms come già suggerito da altri
Memorizzo le ultime tre letture RD1 RD2 RD3
e lo stato dei tasti filtrati è dato da
Codice: Seleziona tutto
Keyflt1 = (RD1 & RD2) | (RD2 & RD3) | (RD1 & RD3)

in pratica devo fare almeno due delle tre letture alte per dichiarare l'ingresso letto alto

Se poi memorizzi anche lo stato precedente dei tasti filtrati quind fai così
Codice: Seleziona tutto
keyflt2 = keyflt1
Keyflt1 = (RD1 & RD2) | (RD2 & RD3) | (RD1 & RD3)

puoi ricavare
Codice: Seleziona tutto
frontup = (keyflt1 ^ keyflt2) & keyflt1
frontdn = (keyflt1 ^ keyflt2) & keyflt2
keypress = (keyflt1 & keyflt2)

e hai tutte le condizioni possibili per la tua tastiera
Avatar utente
Foto Utenteluxinterior
2.507 2 4 8
Expert EY
Expert EY
 
Messaggi: 1474
Iscritto il: 6 gen 2016, 17:48

Precedente

Torna a Firmware e programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite