Reading Quadrature Encoder

I am trying to read a quadrature Encoder by using an interrupt , the encoder count incrementally very well when the wheel moves forward , when reverse wheel moving to backward the encoder decrements correctly but when reach to 1 suddenly jump to 65535 , 65534, 65533 ..... so on . Any help ?

my code :

#define encoder0PinA 2  // interrupt 0

#define encoder0PinB 18  // interrupt 5

volatile unsigned int encoder0Pos = 0;

void setup() {

  pinMode(encoder0PinA, INPUT); 
  pinMode(encoder0PinB, INPUT); 
// encoder pin on interrupt 0 (pin 2)

  attachInterrupt(0, doEncoderA, CHANGE);
// encoder pin on interrupt 5 (pin 3)

  attachInterrupt(5, doEncoderB, CHANGE);  
  Serial.begin (9600);
}

void loop()

{ 


doEncoderA();
doEncoderB();


}

void doEncoderA(){

  // look for a low-to-high on channel A
  if (digitalRead(encoder0PinA) == HIGH) { 
    // check channel B to see which way encoder is turning
    if (digitalRead(encoder0PinB) == LOW) {  
      encoder0Pos = encoder0Pos + 1;         // CW
    } 
    else {
      encoder0Pos = encoder0Pos - 1;         // CCW
    }
  }
  else   // must be a high-to-low edge on channel A                                       
  { 
    // check channel B to see which way encoder is turning  
    if (digitalRead(encoder0PinB) == HIGH) {   
      encoder0Pos = encoder0Pos + 1;          // CW
    } 
    else {
      encoder0Pos = encoder0Pos - 1;          // CCW
    }
  }
  Serial.println (encoder0Pos, DEC);          
  // use for debugging - remember to comment out
}

void doEncoderB(){

  // look for a low-to-high on channel B
  if (digitalRead(encoder0PinB) == HIGH) {   
   // check channel A to see which way encoder is turning
    if (digitalRead(encoder0PinA) == HIGH) {  
      encoder0Pos = encoder0Pos + 1;         // CW
    } 
    else {
      encoder0Pos = encoder0Pos - 1;         // CCW
    }
  }
  // Look for a high-to-low on channel B
  else { 
    // check channel B to see which way encoder is turning  
    if (digitalRead(encoder0PinA) == LOW) {   
      encoder0Pos = encoder0Pos + 1;          // CW
    } 
    else {
      encoder0Pos = encoder0Pos - 1;          // CCW
    }
  }
}

Use a signed integer, rather than an unsigned integer to store the position.

Before the discussion gets into "do not use interrupts" mode.
You are initiating the interrupts service routine (ISR - fancy name for the interrupt processing function ) on "change" , hence both high to low and low to high transitions and also in the loop itself. Assuming the encoder puts out Gray code you will get some strange pattern.
Just do simple Serial print of both A and B channels to see if you are getting correct Gray code pattern.
If you are just interested in "revolutions count" - you realize that triggering on "change" will double the count, right?
BTW Gray code is by itself directional - if you keep track of the old and new code - again both A and B.
Good luck.
Cheers Vaclav

Assuming that you are getting a gray code, I found a very neat idea on keeping track of a (rotary) encoder at one point and adapted it into a small library (see my libraries below). It is very efficient in both code and space and does not get fooled by intermediate states by explointing the gray code output from the encoder.

My implementation is for polled mode only but, from memory, the original source had code for interrupt driven code as well.

Marco,
very nice description on how to read Gray code in the MD_REncoder header file. It still seem to me, OMG personal opinion, that people just don't get the properties of the code thus making their code so convoluted. For example - if one keeps track of old and new code the direction can be calculated just from the value increasing or decreasing. Sooo simple. Unfortunately it is somehow too much of a challenge for most of the users to note that the code can CHANGE only one channel at a time to.
I really feel this is almost classic example of "cut and paste" without trying to figure out how it works.
Off my soap box.
Again, thanks for the links.

Cheers Vaclav

Also, don't forget that mechanical switches have "bounce", hence the need to "debounce" the signal. Relative to the computer, the switches open and close very slowly, and there are times when the transition will be very "noisy", that is, instead of "on" you will see "on, off, on, off, on, off, onnnnnnnnnnnnnnnn......" but the "on, off" even could potentially happen dozens or hundreds of times. With a Gray code (named after its inventor, Frank Gray), you are fairly impervious to switch noise, so if you do the code right, you are implicitly "debounced". Doing this interrupt-driven means you will get your ISR invoked on every bounce event, and if you don't handle the decoding right, yoyo are in deep trouble.

I am also curious why reading encoder B uses the encoder0pos variable. It will cause the current position of one encoder to be misinterpreted based on the last event that happened on the other encoder.

Note that if you subtract 1 from 0 you get 65535 if you have an unsigned int, and if you add 1 to a signed int that has 32767, you will get -32768. It is your responsibility to ensure these things don't happen.
joe

Looking thru hardware description of ( Due) SAM ...8E chip I found that ALL I/O pins are "debouced" (internally and how??) and also there are DEDICATED I/O pins for Gray code. I have not look if these (Gray code ) I/O pins are actually accessible on Due board.
There is a 1000 pages plus spec I'll take a look next to see how is the Gray code I/O implemented in hardware. Fun.