Non c'è un po' troppa roba in quella funzione di interrupt?... Addirittura ci sono una dozzina di digitalRead!
Per evitare i rimbalzi basta leggere la sequenza Gray che esce dall'encoder!
In un verso:
00
01
11
10
00
Nel verso opposto:
00
10
11
01
00
Se fa 00-01-11 è stato ruotato in un verso; se fa 00-10-11 è stato ruotato nell'altro.
Questo è il blocchetto di codice che uso abitualmente:
int E; // Risultato della routine encoder(): 1, -1, 0.
byte S; // Lettura dei due valori dell'encoder.
byte So;// Lettura precedente dell'encoder.
int X; // Usato in encoder() per evitare letture multiple.
void encoder()
{
// PD 76543210
// S=3-PIND &B00000011; Gli I/O 0 e 1 sono PD0 e PD1, perciò non devo scorrere a destra.
// S=3-(PIND>>3) &B00000011; Serviva per l'encoder su PD3 e PD4.
// S=3-((PIND>>4)&B00000011); // Gli I/O 4 e 5 erano PD4 e PD5, perciò dovevo scorrere a destra di 4 bit.
S=3-((PIND>>2) &B00000011); // Uso PD2 e PD3, quindi scorro a destra di 2 bit per farli diventare 0 e 1.
// Il valore binario di S rappresenta A e B. Il centrale dell'encoder è a massa, quindi faccio complemento a 3 (11).
S^=S>>1; // Faccio XOR (^) fra S (gray) e il suo bit 1, facendolo scorrere a Dx: AB XOR A,
// ottenendo un binario che per ogni scatto fa 0-1-2-3-0 oppure 0-3-2-1-0.
E=0;
if (S!=So && S==0) X=0;
if (X==0)
{
if (So==1&&S==2)
{E=1; X=1;
// Bip();
}
if (So==3&&S==2)
{E=-1; X=1;
// Bip();
}
if (S==0)
{E=0; X=0;}
So=S;
}
}
Sì, si potrebbe ottimizzare un po'...
int E; // Risultato della routine encoder(): 1, -1, 0.
byte S; // Lettura dei due valori dell'encoder.
byte So;// Lettura precedente dell'encoder.
int X; // Usato in encoder() per evitare letture multiple.
void encoder()
{
// PD 76543210
// S=3-PIND &B00000011; Gli I/O 0 e 1 sono PD0 e PD1, perciò non devo scorrere a destra.
// S=3-(PIND>>3) &B00000011; Serviva per l'encoder su PD3 e PD4.
// S=3-((PIND>>4)&B00000011); // Gli I/O 4 e 5 erano PD4 e PD5, perciò dovevo scorrere a destra di 4 bit.
S=3-((PIND>>2) &B00000011); // Uso PD2 e PD3, quindi scorro a destra di 2 bit per farli diventare 0 e 1.
// Il valore binario di S rappresenta A e B. Il centrale dell'encoder è a massa, quindi faccio complemento a 3 (11).
S^=S>>1; // Faccio XOR (^) fra S (gray) e il suo bit 1, facendolo scorrere a Dx: AB XOR A,
// ottenendo un binario che per ogni scatto fa 0-1-2-3-0 oppure 0-3-2-1-0.
E=0;
if (S!=So && S==0)
{
X=0;
if (S==2)
{
X=1;
if (So==1)
{
E=1;
// Bip();
}
else if (So==3)
{
E=-1;
// Bip();
}
}
else if (S==0)
{
E=0;
X=0;
}
So=S;
}
}
Solitamente non uso l'interrupt, perché il loop è abbastanza veloce oppure faccio le impostazioni in un while apposito, che attende la pressione del pulsante.