Debouncing a rotary encoder

Hello all!
Im trying to program a rotary encoder to drive a stepper motor via an easy driver. so far its not going bad. I can read the encoder and get the stepper to follow the movement. I am finding however that the signal is not 100% clear, perticually if turned quickly. Im assuming this is due to switch bounce inside the encoder. Im trying to remove this so the encoder is read exactly as it is. I used the debounce example and transfered that into my code, however it hasnt really improved. any help would be GREATLY appreciated.

Here is the origonal code:

const int EncoderA = 0;
const int EncoderB = 2;
const int Direction = 8;
const int StepOut = 9;


int ACurrent = 0;
int BCurrent = 0; 
int APrevious = digitalRead(EncoderA); //Read starting posion of encoder
int BPrevious = digitalRead(EncoderB); //Read startung position of encorder


void setup() {
  Serial.begin(9600);
  pinMode (EncoderA, INPUT);  //Set Encoder A pin as Input
  digitalWrite (EncoderA, HIGH); //Turn on pull up resitor
  pinMode (EncoderB, INPUT);  //Set Encoder B pin as Input
  digitalWrite (EncoderB, HIGH); //Turn on Pull up resistor
  pinMode (Direction, OUTPUT);
  pinMode (StepOut, OUTPUT);
}

void loop() {
   CheckChange: 
      ACurrent = digitalRead (EncoderA); //Read & save current value of pin A
      BCurrent = digitalRead (EncoderB); //Read & save current value of pin B
      if (ACurrent == APrevious && BCurrent == BPrevious) { //if Values have not changed, go back and check again
         goto CheckChange;
          }
      if (APrevious == HIGH && BPrevious == HIGH && ACurrent == HIGH) {
        digitalWrite (Direction, HIGH);
        Serial.print ("CW"); 
      }
      else if  (APrevious == LOW && BPrevious == LOW && ACurrent == LOW){
        digitalWrite (Direction, HIGH);
        Serial.print ("CW"); 
      }
      
      else if  (APrevious == HIGH && BPrevious == LOW && ACurrent == LOW){
        digitalWrite (Direction, HIGH);
        Serial.print ("CW"); 
      }
      
      else if  (APrevious == LOW && BPrevious == HIGH && ACurrent == HIGH){ 
        digitalWrite (Direction, HIGH);
        Serial.print ("CW"); 
      }
      
      else {
        digitalWrite (Direction, LOW);
        Serial.print ("CCW"); 
      }
      
      APrevious = ACurrent; //Update Previous position with new position
      BPrevious = BCurrent; //Update Previous position with new position
     
      for (int Stepcount = 0; Stepcount <= 33; Stepcount ++) {
        digitalWrite (StepOut, HIGH);
        digitalWrite (StepOut, LOW);
        delayMicroseconds (700);
       }
}

and here is my attempt at debouncing it:

const int EncoderA = 0;
const int EncoderB = 2;
const int Direction = 8;
const int StepOut = 9;


int ACurrent = 0;
int BCurrent = 0; 
int ACurrentLast = LOW;
int BCurrentLast = LOW;
int APrevious = digitalRead(EncoderA); //Read starting posion of encoder
int BPrevious = digitalRead(EncoderB); //Read startung position of encorder

long lastDebounceTimeA;
long lastDebounceTimeB;
long debounceDelay = 50;


void setup() {
  Serial.begin(9600);
  pinMode (EncoderA, INPUT);  //Set Encoder A pin as Input
  digitalWrite (EncoderA, HIGH); //Turn on pull up resitor
  pinMode (EncoderB, INPUT);  //Set Encoder B pin as Input
  digitalWrite (EncoderB, HIGH); //Turn on Pull up resistor
  pinMode (Direction, OUTPUT);
  pinMode (StepOut, OUTPUT);
}

void loop() {
   CheckChange: 
         
          //debounce
      int ReadingA = digitalRead (EncoderA); //Read & save current value of pin A
      int ReadingB = digitalRead (EncoderB); //Read & save current value of pin B
      
      if (ReadingA != ACurrentLast) {
          lastDebounceTimeA = millis(); //if signal has changed, register time for comparison   
          }
      if (ReadingB != BCurrentLast) {
          lastDebounceTimeB = millis(); //if signal has changed, register time for comparison   
          }
      if ((millis() - lastDebounceTimeA) > debounceDelay) {
          ACurrent = ReadingA;                                //if sufficient time was been waited between readings, use reading
        }
      if ((millis() - lastDebounceTimeB) > debounceDelay) {
          BCurrent = ReadingB;                                //if sufficient time was been waited between readings, use reading
        }
                    
      ACurrentLast = ReadingA; //Update Current Reading as Last Reading, ready for next Reading
      BCurrentLast = ReadingB; //Update Current Reading as Last Reading, ready for next Reading
    
    
      //encoder check
      if (ACurrent == APrevious && BCurrent == BPrevious) { //if Values have not changed, go back and check again
         goto CheckChange;
          }
      if (APrevious == HIGH && BPrevious == HIGH && ACurrent == HIGH) {
        digitalWrite (Direction, HIGH);
        Serial.print ("CW"); 
      }
      else if  (APrevious == LOW && BPrevious == LOW && ACurrent == LOW){
        digitalWrite (Direction, HIGH);
        Serial.print ("CW"); 
      }
      
      else if  (APrevious == HIGH && BPrevious == LOW && ACurrent == LOW){
        digitalWrite (Direction, HIGH);
        Serial.print ("CW"); 
      }
      
      else if  (APrevious == LOW && BPrevious == HIGH && ACurrent == HIGH){ 
        digitalWrite (Direction, HIGH);
        Serial.print ("CW"); 
      }
      
      else {
        digitalWrite (Direction, LOW);
        Serial.print ("CCW"); 
      }
      
      
      
      ACurrentLast = ACurrent;
      BCurrentLast = BCurrent;
      APrevious = ACurrent; //Update Previous position with new position
      BPrevious = BCurrent; //Update Previous position with new position
      
      for (int Stepcount = 0; Stepcount <= 33; Stepcount ++) {
        digitalWrite (StepOut, HIGH);
        digitalWrite (StepOut, LOW);
        delayMicroseconds (900);
       }
}

This is the first time i have needed to use debounce, so if anyone has any ideas please share them! many thanks :slight_smile:

I did quite a bit of work on rotary encoders here:

http://www.gammon.com.au/forum/?id=11130

There was quite a bit of fiddliness to getting it right. In particular, some sequences from the encoder are "invalid" and if ignored help the output. Also I found hooking it up to an interrupt helped. And there is a suggestion that putting a 0.1uF capacitor across the terminals helps (see circuit on that page).