Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

Debounce software interrupt esterno

Progetti, interfacciamento, discussioni varie su questa piattaforma.

Moderatori: Foto UtenteMassimoB, Foto Utentexyz, Foto UtenteWALTERmwp

0
voti

[1] Debounce software interrupt esterno

Messaggioda Foto Utentelucaking » 26 ago 2022, 19:51

Ciao a tutti,
sto cercando di far funzionare decentemente un encoder tipo questo:
rotary-encoder.jpg

collegnadolo ad un arduino uno usando gli interrupt esterni disponibili sui pin 2 e 3.
Ho scritto questo codice:
Codice: Seleziona tutto
#define SW_PIN 2
#define CLK_PIN 3
#define DRCT_PIN 4

volatile int encoder_count = 0;
volatile boolean state;
boolean last_state;

void button_handler ()
{
   state = !state;
   Serial.println ();
   Serial.println ("Ora inverto senso rotazione.");
}

void encoder_handler ()
{
   static unsigned long last_encoder_time;
   unsigned long encoder_time = millis();
   if ((encoder_time - last_encoder_time) > 300) {
      state = !state;
      if (digitalRead (DRCT_PIN)) {
         encoder_count ++;
      }
      else {
         encoder_count --;
      }
      last_encoder_time = encoder_time;
   }
}

void setup() {
   pinMode (SW_PIN, INPUT);
  pinMode (CLK_PIN, INPUT);
  pinMode (DRCT_PIN, INPUT);
  attachInterrupt (0, button_handler, FALLING); // encoder SW_PIN.
  attachInterrupt (1, encoder_handler, FALLING); // encoder CLK_PIN.
   Serial.begin (9600);
}

void loop() {
   if (state != last_state) {
    Serial.print (encoder_count);
    Serial.print (" ");
   }
   last_state = state;
}

con l' idea di incremetare la variabile encoder_count quando ruoto in un senso e decrementarla quando ruoto nell' altro.
Ho provato anche a variare il tempo di debounce ma i risultati non mi sembrano un gran che.
Questo è cio che ottengo ruotando abbastanza lentamente l' encoder:

1 1 3 3 4 5 4 3 2 3 4 6 7 7 6 5 6 5 6 8 7 8 10 12 11 12 11
Ora inverto senso rotazione.
11 10 9 8 9 8 9 8 7 4 3 2 3 2 3 2 1 1 0 -1
Ora inverto senso rotazione.
-1 1 2 3 2 2 3 4 3 2 3 2 1 0 -1 0 1 2 4 3 4 4 4 3 4 5 6 7 7 6 7 6 7 8


Sono tutto orecchie.
Avatar utente
Foto Utentelucaking
1.443 3 5 8
Expert
Expert
 
Messaggi: 1284
Iscritto il: 29 mag 2015, 14:28

1
voti

[2] Re: Debounce software interrupt esterno.

Messaggioda Foto UtenteWALTERmwp » 27 ago 2022, 1:23

Ciao @lucaking, perché consideri il segnale SW ?
Come si comporta quando inverti la rotazione ?
Poi, non sarebbe sufficiente l'interrupt che rileva la discesa di CLK ?
Senza un filtro temporale hai problemi di rimbalzo ?

Forse ci sono anche delle complicazioni.
Ad esempio, cosa impedisce che la chiamata interrupt per "button_handler ()" possa avvenire tra il test "if (state != last_state)" e la assegnazione "last_state = state;" ?
C'è poi l'impegno per quell'elaborazione sui millisecondi che può falsare il conteggio.
Comunque, in generale, all'interno d'una routine di interrupt quell'elaborazione non andrebbe inserita; in alternativa esegui l'assegnazione di una variabile da controllare a livello principale, direttamente all'interno del loop, e in funzione dell'esito esegui le operazioni che necessitano.

Saluti
W - U.H.F.
Avatar utente
Foto UtenteWALTERmwp
27,2k 4 8 13
G.Master EY
G.Master EY
 
Messaggi: 8103
Iscritto il: 17 lug 2010, 18:42
Località: le 4 del mattino

0
voti

[3] Re: Debounce software interrupt esterno.

Messaggioda Foto Utentelucaking » 27 ago 2022, 8:51

Anzitutto grazie per le risposte/domande :D, ora cerco di rispondere per quelle che sono le mie scarse capacità.


WALTERmwp ha scritto:Ciao @lucaking, perché consideri il segnale SW ?
Come si comporta quando inverti la rotazione ?
In realtà al momento sono solo delle prove, il segnale del pulsante dell' encoder (SW_PIN) vorrei in futuro usarlo per confermare il valore ottenuto col conteggio dell' ecoder.
Al momento gli ho fatto scrivere su seriale "Ora inverto senso rotazione." solo per lasciare un riferimento sull' output della seriale.
Nell' esempio da me postato, ho ruotato in un senso l' encoder, che è arrivato a contare fino a 12/11 #-o, poi ho premuto il bottone ed ho cominciato a ruotarlo nel verso opposto cercando di decrementare il valore di encoder_count.
Come si comporta lo lascio giudicare a te.... :D
All' incirca funziona, ma come si puo notare, a volte non vengono stampati dei valori che però vengono conteggiati,
7 8 10 12
altre volte, pur ruotado sempre nella stessa direzione il valore viene incremetato, decrementato e poi reincremetato, come se stessi invertendo il senso di rotazione.
Altre volte ancora, viene stampato due volte lo stesso valore, e questo proprio non mi torna, considerato che ogni volta che loop rileva un cambio di state ad opera dell' ISR encoder_handler, il valore di encoder_count è stato per forza di cose modificato.


WALTERmwp ha scritto:Poi, non sarebbe sufficiente l'interrupt che rileva la discesa di CLK ?
Ma, io pensavo di aver gia fatto quello, lo stato di DRCT_PIN (essendo un encoder con i due segnali d' uscita in quadratura) lo leggo solo per stabilire il senso di rotazione.


WALTERmwp ha scritto:Senza un filtro temporale hai problemi di rimbalzo ?
Sembrerebbe di si, il comportamento diventa quasi casuale.
Non l' ho smontato, ma credo sia un encoder a contatti meccanici.


WALTERmwp ha scritto:Ad esempio, cosa impedisce che la chiamata interrupt per "button_handler ()" possa avvenire tra il test "if (state != last_state)" e la assegnazione "last_state = state;" ?
Questo in realtà ha lasciato qualche dubbio anche a me, ma al momento non ho saputo fare di meglio. :oops:


WALTERmwp ha scritto:Comunque, in generale, all'interno d'una routine di interrupt quell'elaborazione non andrebbe inserita; in alternativa esegui l'assegnazione di una variabile da controllare a livello principale, direttamente all'interno del loop, e in funzione dell'esito esegui le operazioni che necessitano.
Intendi di fare il debounce, la lettura dello stato di DRCT_PIN (per stabilire il senso di rotazione) e la conseguente modifica del valore di encoder_count, fuori dall' ISR, direttamente in loop() e lasciare che l' ISR cambi solo il valore di state e prenda il tempo di quado c' è scattato l' interrupt?
Avatar utente
Foto Utentelucaking
1.443 3 5 8
Expert
Expert
 
Messaggi: 1284
Iscritto il: 29 mag 2015, 14:28

0
voti

[4] Re: Debounce software interrupt esterno.

Messaggioda Foto UtenteGioArca67 » 27 ago 2022, 10:51

È sicuramente meccanico a contatti striscianti.

Anche a me sembra strano il comportamento.
Avatar utente
Foto UtenteGioArca67
2.213 3 4 9
Master
Master
 
Messaggi: 2030
Iscritto il: 12 mar 2021, 9:36

0
voti

[5] Re: Debounce software interrupt esterno.

Messaggioda Foto Utentestefanopc » 27 ago 2022, 11:24

Sono d'accordo per una gestione più lineare dell' interrupt.
Da principiante io farei così.
-Quando Clk_pin cambia si genera l'interrupt con cui viene eseguita la lettura di Drct_pin.
-In base al suo stato viene incrementato o decremento il contatore.
-vengono disabilitati gli interrupt.
-il sistema aspetta 300 ms durante i quali gli interrupt sono disabitati.
-vengono riabilitati gli interrupt.
Ciao
600 Elettra
Avatar utente
Foto Utentestefanopc
7.886 4 8 13
Master EY
Master EY
 
Messaggi: 2655
Iscritto il: 4 ago 2020, 9:11

0
voti

[6] Re: Debounce software interrupt esterno.

Messaggioda Foto UtenteEtemenanki » 27 ago 2022, 14:12

Ciao, io sono piu un maniscalco che un notaio (hardwaristi e softwaristi :mrgreen: ), pero' sconsiglierei sempre a prescindere l'uso di debounce software, specialmente per i pin di interrupt, che per loro natura dovrebbero essere liberi di intervenire in qualsiasi momento, senza essere condizionati da altre routine di attesa.

Poi francamente 300mS mi sembrano un po tantini, ma questo e' un altro discorso.

Hai provato ad usare dei semplici RC come debounce ?

Mi sembra che tu stia usando un'encoder che chiude i contatti verso massa quando ruotato (usi falling), quindi una semplice resistenza di pullup da 10k fra pin e VCC, un condensatore da 47n fra pin e GND, e se proprio vogliamo esagerare, una resistenza da 100 ohm fra pin ed encoder (ripetuti su tutti e tre i pin ovviamente) dovrebbero essere piu che sufficenti per eliminarti i rimbalzi senza impedire la corretta lettura degli impulsi (considerando che quegli encoder di solito non li si ruotano piu veloci di tanto)

Poi nel programma ti limiti a leggere con l'interrupt uno dei due contatti, quando senti la variazione entri nella ISR, e secondo lo stato dell'altro contatto incrementi o decrementi la variabile (meno cose ci sono nelle ISR e meglio e' ;-) )
"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.
Avatar utente
Foto UtenteEtemenanki
3.422 3 4 9
Master
Master
 
Messaggi: 2270
Iscritto il: 2 apr 2021, 23:42
Località: Dalle parti di un grande lago ... :)

0
voti

[7] Re: Debounce software interrupt esterno.

Messaggioda Foto Utentelelerelele » 27 ago 2022, 16:18

Per esperienza personale, su questi tipo di encoder, dipende molto dal produttore dell'encoder, ma comunque i contatti hanno sempre dei rimabzi, e questo genera sempre dei problemi, come quelli descritti.

Con un buon filtro RC all'ingresso funziona bene, (prendi spunto dal datasheets oppure application note, non farlo a caso), io ho risolto così sulle schede problematiche, senza problemi apprezzabili.

Prorpongo un link ad un thread sull'argomento, link, in cui Foto UtentePietroBaima affermava se non ricordo male, che in ambito professionale si usa sempre un antirimbalzo software.

saluti.
Avatar utente
Foto Utentelelerelele
3.292 3 7 9
Master
Master
 
Messaggi: 3812
Iscritto il: 8 giu 2011, 8:57
Località: Reggio Emilia

0
voti

[8] Re: Debounce software interrupt esterno.

Messaggioda Foto UtentePietroBaima » 27 ago 2022, 16:28

lelerelele ha scritto:Prorpongo un link ad un thread sull'argomento, link, in cui Foto UtentePietroBaima affermava se non ricordo male, che in ambito professionale si usa sempre un antirimbalzo software.

Sì, risparmiare HW è fondamentale.
Generatore codice per articoli:
nomi
Sul forum:
[pigreco]=π
[ohm]=Ω
[quadrato]=²
[cubo]=³
Avatar utente
Foto UtentePietroBaima
86,4k 7 12 13
G.Master EY
G.Master EY
 
Messaggi: 11589
Iscritto il: 12 ago 2012, 1:20
Località: Londra

0
voti

[9] Re: Debounce software interrupt esterno.

Messaggioda Foto Utentelucaking » 27 ago 2022, 17:18

lelerelele ha scritto:Prorpongo un link ad un thread sull'argomento, link, in cui Foto UtentePietroBaima affermava se non ricordo male, che in ambito professionale si usa sempre un antirimbalzo software.
E' proprio grazie a questo thread che mi sono complicato la vita, maledetto Foto UtentePietroBaima.... :D :mrgreen:
In passato avevo gia fatto qualcosa di semplice con dei filtri RC (per muoversi all' interno di dei menu) che funzionava dignitosamente a patto di non ruotare troppo velocemente l' encoder, ma ora, volendo impostare un valore tra 0 e 255, vorrei riuscire ad andare avanti e indietro velocemente all' occorenza.


Etemenanki ha scritto:Mi sembra che tu stia usando un'encoder che chiude i contatti verso massa quando ruotato (usi falling), quindi una semplice resistenza di pullup da 10k fra pin e VCC
Ci sono gia sul retro del modulino dell' encoder tre pullup SMD da 10k.


Etemenanki ha scritto:Poi francamente 300mS mi sembrano un po tantini, ma questo e' un altro discorso.
Anche a me, ma erano solo prove, e in preda alla disperazione, ho cominciato a provare valori un po' a caso.

Domani attacco l' oscilloscopio alle uscite dell' encoder e cerco di procedere in maniera un po' piu sensata.
Avatar utente
Foto Utentelucaking
1.443 3 5 8
Expert
Expert
 
Messaggi: 1284
Iscritto il: 29 mag 2015, 14:28

0
voti

[10] Re: Debounce software interrupt esterno.

Messaggioda Foto UtenteEtemenanki » 27 ago 2022, 17:43

Se proprio si vuole farlo per forza software ... se si tratta di pulsanti (incluso quello dell'encoder), i rimbalzi in media potrebbero durare fra i 5 ed i 10 mS, dipende da quanto e' "malvagia" la costruzione dei contatti, quindi 25 / 30 mS dovrebbero bastare in teoria, se si tratta dei contatti dell'encoder ed invece che a lamina sono striscianti, come ormai in quasi tutti quegli encoder (e' piu economico farli cosi), e se il materiale dei contatti e' ossidato o di cattiva qualita', i rimbalzi potrebbero essere presenti anche per tutta la lunghezza della striscia conduttiva nel peggiore dei casi, in quel caso potresti fare una prova un po empirica, vedere con un'oscilloscopio quanto dura la chiusura del contatto alla massima velocita' a cui vuoi far ruotare l'encoder, e poi impostare il tempo poco piu alto, pero' non garantirebbe in caso di velocita' di rotazione piu bassa, per cui suggerirei di aggiungere anche un minimo di hardware come suggeriscono proprio i costruttori degli encoder.

Per il fatto che vuoi poter incrementare e decrementare un'intervallo di valori ampio (0-255) ci potrebbe essere una soluzione alternativa (piu semplice da usare con i debounce hardware), che pero' complicherebbe un po il software, cioe' considerare anche la velocita' a cui ruoti l'encoder ... se ad esempio lo ruoti lentamente, tipo uno scatto ogni mezzo secondo o meno (valore a caso, poi metti quello che vuoi tu), fuori dalla ISR incrementi o decrementi di uno, se invece ruoti piu velocemente, incrementi o decrementi di 10, pero' come ho detto complicherebbe il software.

Non essendo un programmatore, posso solo cercare di immaginare un sistema (ma sicuramente altri che se ne intendono piu di me ne troveranno di migliori), come ad esempio nella ISR con FALLING setto una flag da 0 ad 1 se incremento oppure a 2 se decremento piu un unsigned long a millis(), con RISING in una seconda ISR setto una seconda flag ad 1 (per dire al micro che ora puo effettuare un controllo nel loop) ed un secondo unsigned long a millis(), poi a quel punto nel loop puoi confrontare i due unsigned long, se differenza maggiore di 250mS incrementi o decrementi (secondo lo stato della prima flag) di uno, se minore di 10, ed azzeri le due flag ... non e' il massimo, ma forse potrebbe perfino funzionare :mrgreen: .

EDIT: un secondo sistema forse piu semplice potrebbe essere sentire se il pulsante dell'encoder e' premuto mentre lo ruoti ... cerco di spiegarmi , fai le azioni relative alla pressione del pulsante nel momento in cui lo rilasci invece che in quello in cui lo premi, quindi se premi il pulsante e lo rilasci senza aver ruotato l'encoder fai le tue funzioni standard, se lo premi e ruoti mentre e' premuto, incrementi o decrementi di 10 invece che di 1 ad ogni scatto per tutto il tempo in cui lo tieni premuto, ma quando lo rilasci non fai altro.
"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.
Avatar utente
Foto UtenteEtemenanki
3.422 3 4 9
Master
Master
 
Messaggi: 2270
Iscritto il: 2 apr 2021, 23:42
Località: Dalle parti di un grande lago ... :)

Prossimo

Torna a Arduino

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite