lettura Encoder in quadratura (veloce)

Buona Domenica a tutti,
ho scritto questo codice per conoscere la posizione di un encoder in quadratura
il canale A e connesso con il PIN 2 che richiama un interrupt ogni volta che cambia stato
il canale B e connesso con il PIN 4 per determinare la direzione

volatile int encoder0Pos = 0; // posizione attuale

void setup(){
  Serial.begin(57600);
  pinMode(2, INPUT); 
  pinMode(4, INPUT);
  attachInterrupt(0, doEncoderA, CHANGE); // encoder A channel on interrupt 0 (arduino's pin 2)                       

}
void loop(){ 
  Serial.println(encoder0Pos); 
  }

void doEncoderA() { // pin no 2
  digitalRead(2) ^ digitalRead(4) ? encoder0Pos -- :   encoder0Pos  ++ ; // se i due segnali sono uguali  decremente, altrimenti incrementa
//PIND & _BV(2) ^ PIND & _BV(4)  ?  encoder0Pos -- :       encoder0Pos  ++ ;
}

il codice funziona, ma per rendere la routine interrupt più veloce volevo cambiare questa riga

digitalRead(2) ^ digitalRead(4) ? encoder0Pos -- :   encoder0Pos  ++ ;

con questa

 PIND & _BV(2) ^ PIND & _BV(4)  ?  encoder0Pos -- :    encoder0Pos  ++ ;

andando a leggere direttamente lo stato dei PIN
in questo caso girando l'encoder in un senso encoder0Pos diminuisce, girando nell'altro senso varia da 0 a 1 poi 0 poi 1 .......

Mi sfugge qualcosa? cosa non và?
grazzie a tutti

Non vorri sbagliare, ma se inserisci anche il pin 4 sotto interrupt avresti la moltiplicazione x4 della risoluzione dell'encoder.

Ettore Massimo Albani

prova a sostituire i _BV con 1<<

lo so è la stessa cosa ma mi pareva di aver letto che non si estende a tutti i chip o una roba simile.

Così dovrebbe funzionare:

( PIND & _BV(2) ) ^ ( PIND & _BV(4) )  ?  encoder0Pos-- :  encoder0Pos++ ;

Se il risultato della operazione xor (^ or esclusivo) è vero viene eseguito il codice subito dopo il "?", se è falso viene eseguito il codice dopo il ":"

Lo xor risulta vero se solo uno dei due operandi è vero, ritorna falso se gli operandi sono entrambe identici, non importa se sono veri o falsi entrambe.

Ciao.

o provato con le parentesi ma niente da fare.
l'unico sistema è cambiare CHANGE con FALLING

attachInterrupt(0, doEncoderA, FALLING );

però in questa maniera si ottiene una lettura 1X

deve esserci qualche problema di tempo di salita del segnale
grazie a tutti per le risposte

calzand:
o provato con le parentesi ma niente da fare.
l'unico sistema è cambiare CHANGE con FALLING

attachInterrupt(0, doEncoderA, FALLING );

però in questa maniera si ottiene una lettura 1X

deve esserci qualche problema di tempo di salita del segnale
grazie a tutti per le risposte

hai provato mettendo delle resistenze di pullup?

@calzand:
la funzione attachInterrupt, anche se sul reference c'è scritto diversamente, gestisce solo FALLING, RASING e LOW. Se vuoi usare lo stato CHANGE, devi usare la libreria PinChangeInt:
http://code.google.com/p/arduino-pinchangeint/

leo72:
@calzand:
la funzione attachInterrupt, anche se sul reference c'è scritto diversamente, gestisce solo FALLING, RASING e LOW. Se vuoi usare lo stato CHANGE, devi usare la libreria PinChangeInt:
Google Code Archive - Long-term storage for Google Code Project Hosting.

Questo non è vero sui pin 2 e 3 (INT0 e INT1) CHANGE funziona!
mettendo CHANGE conto sia i fronti di salita che di discesa e ottengo il doppio dei conteggi rispetto a FALLING o RISING
questo facendo la lettura con digitalRead

se faccio la lettura direttamente dal registro PIND & _BV(2) o PIND &(1<<PIND2) (che è la stessa cosa) funziona solo con FALLING (lettura 1x) e non con RISING e CHANGE.

Ho attivato le resistenze di PULL-UP interne ma non cambia niente.
Ho provato a scrivere codice direttamente da AVRstudio poi a caricare .hex nell'arduino, stesso comportamento.

digitalRead che altre operazioni fà oltre che a scrivere sulla porta???