Rotary Encoder Using Ardunio to Count Pulses. High Resolution

Use fpga4fun.com - Quadrature Decoder , for reference to algorithm.

//John Budd/////////////////


//Define Program Constants
#define eeprom 0x50                                            //Address of Eprom Chip #1 
#define eeprom2 0x51                                           //Address of Eprom Chip #2


void setup() {
  DDRB = DDRB | 0x00;         //Set pins 8-11 as inputs; read 0000 0000
  

}

void loop() {
  int leftClick = 0;
  int rightClick = 0;
  
  int leftA = 0,leftB = 0,prevLeftA = 0,prevLeftB = 0;
  int rightA = 0,rightB = 0,prevRightA = 0,prevRightB = 0;
  
  int countR = 0;
  int countL = 0;
  int countDirR = 0;
  int countDirL = 0; 
  
  while(true){
    
    //Sample the Left Wheel
    prevLeftA = leftA;
    prevLeftB = leftB;
    leftA = PORTB & 0x01;                            //left wheel phase A is pin 8
    leftB = (PORTB & 0x02)>>1;                        //left Wheel phase B is pin 9; shift bit to generate high signal if 
    
    
    //Sample the Right Wheel
    prevRightA = rightA;
    prevRightB = rightB;
    rightA = (PORTB & 0x04)>>2;                          //right wheel phase A is pin 10;shift bit to generate high signal if 
    rightB = (PORTB & 0x08)>>3;                          //right wheel phase B is pin 11;shift bit to generate high signal if 
  
    //Counting left
    countL = leftA ^ leftB ^ prevLeftA ^prevLeftB;        //HIGH specs count increment; LOW specs no incremenet
    countDirL = prevLeftA ^ leftB;                        //LOW specs backwards, HIGH specs foward
    
    //Counting Right
    countR = rightA ^ rightB ^ prevRightA ^prevRightB;        //HIGH specs count increment; LOW specs no incremenet
    countDirR = prevRightA ^ rightB;                        //LOW specs backwards, HIGH specs fowards
    
    if(countDirL == 1)
      leftClick = leftClick + countL;
    else
      leftClick = leftClick - countL;
    
    
    if(countDirR == 1)
      rightClick = rightClick + countR;
    else
      rightClick = rightClick - countR;
  }
  
  
   
}


void initSystem(){
                                          //Setup Interupts
}

My first time using the PORTB registers but I need this code to be fast. I wanted to know if I'm doing anything wrong with the PORTB manipulations.

I'm just reading the value of Phase B and Phase A and incrementing a counter based on a Boolean logical expression.

The period of the phase A I think is going to be around 20-50us. I have to measure with scope to be sure.

My plan was to run this code on the UNO and then interface the UNO to the MEGA which could periodically poll the UNO for the value of leftClick and rightClick. I'm thinking bitShifting serially over I/O lines or using the Tx Rx pins although I'm not sure how much time it will take to communcate serially.

Thanks for your thoughts

Have you had a look at attachInterrupt() function. With interrupts you will detect a pulse when there is one.

search (upper right) for rotary and interrupt and you will find several hits including - http://arduino.cc/forum/index.php/topic,62026.0.html -

I can't vouch for the whole algorithm but you do have a couple of problems:

DDRB = DDRB | 0x00;         //Set pins 8-11 as inputs; read 0000 0000

This doesn't actually do that. You should write:

DDRB &= ~ ( (1<<0/*D8*/) | (1<<1/*D9*/) | (1<<2/*D10*/) | (1<<3/*D11*/) );  // Or simpler, DDRB &= ~0x0F;

Then, throughout your code when you are trying to read Port B you should be reading the PINB register, not the PORTB register (the PORTB register is for setting the outputs, the PINB register for reading inputs).

--
The MegaRAM shield: add 128 kilobytes of external RAM to your Arduino Mega/Mega2560