Reading from 3 rotary encoders

Hi,

I am currently trying to read from three (sparkfun) rotary encoders, but when I dial one of them, all three encoders output the same change (all three rotary encoders 'sense' eachother). I am using Olegs code from http://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino

My rotary encoders are connected to Analog pins 0,1 and 2,3 and 4,5. As far as I understand, it has to do with shifting some bits around, but I have no clue how that works, so any help would be appreciated. I have tried looking through all the comments in the article, but every time someone asks for help reading multiple encoders, nobody responds. In advance, thanks!

int8_t read_encoder1()
{
  static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
  static uint8_t old_1AB = 0;
  /**/
  old_1AB <<= 2;                   //remember previous state
  old_1AB |= ( ENC_PORT & 0x03 );  //add current state
  return ( enc_states[( old_1AB & 0x0f )]);
}

int8_t read_encoder2()
{
  static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
  static uint8_t old_2AB = 0;
  /**/
  old_2AB <<= 2;                   //remember previous state
  old_2AB |= ( ENC_PORT & 0x03 );  //add current state
  return ( enc_states[( old_2AB & 0x0f )]);
}

int8_t read_encoder3()
{
  static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
  static uint8_t old_3AB = 0;
  /**/
  old_3AB <<= 2;                   //remember previous state
  old_3AB |= ( ENC_PORT & 0x03 );  //add current state
  return ( enc_states[( old_3AB & 0x0f )]);
}

What calls those functions? Snippets are not sufficient.

  old_1AB |= ( ENC_PORT & 0x03 );  //add current state
  old_2AB |= ( ENC_PORT & 0x03 );  //add current state
  old_3AB |= ( ENC_PORT & 0x03 );  //add current state

You are doing direct port manipulation, whether you realize it or not, to read some pin states. Notice that it is the SAME pins that you are reading in all three cases.

Hi Paul,

thanks for the reply! You're right, I'm reading the same thing, but how can i differentiate between the three sensors then?

Sorry about not posting the entire code, but I thought it might be a bit much. Here it is:

#include <CapSense.h>

// Set up CapSense

CapSense cs_3_2 = CapSense(3,2);
CapSense cs_3_8 = CapSense(3,8);
CapSense cs_3_11 = CapSense(3,11);
CapSense cs_3_12 = CapSense(3,12);

#define ENC_PORT PINC


// Configure motor pins

const int motorEnable = 13;

const int motor1APin = 5;
const int motor1BPin = 4;

const int motor2APin = 7;
const int motor2BPin = 6;

const int motor3APin = 10;
const int motor3BPin = 9;

      int motor1running = 0;
      int motor2running = 0;
      int motor3running = 0;
      
      
const int ENC_1A = 14;
const int ENC_1B = 15;

const int ENC_2A = 16;
const int ENC_2B = 17;

const int ENC_3A = 18;
const int ENC_3B = 19;


void setup() {
  
     pinMode(motorEnable, OUTPUT);
     digitalWrite(motorEnable, HIGH);
         
     pinMode(motor1APin, OUTPUT);
     pinMode(motor1BPin, OUTPUT);
     pinMode(motor2APin, OUTPUT);
     pinMode(motor2BPin, OUTPUT);
     pinMode(motor3APin, OUTPUT);
     pinMode(motor3BPin, OUTPUT);
  
     pinMode(ENC_1A, INPUT);
     pinMode(ENC_1B, INPUT);
     
     digitalWrite(ENC_1A, HIGH);
     digitalWrite(ENC_1B, HIGH);
     
     pinMode(ENC_2A, INPUT);
     pinMode(ENC_2B, INPUT);

     digitalWrite(ENC_2A, HIGH);
     digitalWrite(ENC_2B, HIGH);

     pinMode(ENC_3A, INPUT);
     pinMode(ENC_3B, INPUT);

     digitalWrite(ENC_3A, HIGH);
     digitalWrite(ENC_3B, HIGH);
  
     //cs_3_2.set_CS_AutocaL_Millis(0xFFFFFFFF);     // turn off autocalibrate on channel 1 - just as an example
     //cs_3_8.set_CS_AutocaL_Millis(0xFFFFFFFF);     // turn off autocalibrate on channel 1 - just as an example
     //cs_3_11.set_CS_AutocaL_Millis(0xFFFFFFFF);     // turn off autocalibrate on channel 1 - just as an example
     //cs_3_12.set_CS_AutocaL_Millis(0xFFFFFFFF);     // turn off autocalibrate on channel 1 - just as an example

    Serial.begin(115200);   
}

void loop() {
  
  if(Serial.available() > 0) {
    int inByte = Serial.read();
    
    switch(inByte) {
      
       // Motor 1
       case 10:
         motor1("backward");
         break; 
       case 11:
         motor1("stop");
         break; 
       case 12:
         motor1("forward");
         break; 
       // Motor 2
       case 20:
         motor2("backward");
         break; 
       case 21:
         motor2("stop");
         break; 
       case 22:
         motor2("forward");
         break; 
       // Motor 3
       case 30:
         motor3("backward");
         break;
       case 31:
         motor3("stop");
         break; 
       case 32:
         motor3("forward");
         break; 
       case 50:
         motor1("stop");
         motor2("stop");
         motor3("stop");
         Serial.end();
         break; 
    }
  }
  
    //long start = millis();
  int val1 = cs_3_2.capSense(10);
  int val2 = cs_3_8.capSense(10);
  int val3 = cs_3_11.capSense(10);
  int val4 = cs_3_12.capSense(10);
  
  // Print out CapSense values to Serial
  
  
  /*
  Serial.print(val1);
  Serial.print("\t");
  Serial.print(val2);
  Serial.print("\t");
  Serial.print(val3);
  Serial.print("\t");
  Serial.println(val4);
  */
  
  Serial.println("Cap1");
  Serial.println(val1);
  Serial.println("Cap2");
  Serial.println(val2);
  Serial.println("Cap3");
  Serial.println(val3);
  Serial.println("Cap4");
  Serial.println(val4);
  
  int8_t tmpdata1;
  tmpdata1 = read_encoder1();
  if(tmpdata1) {
    Serial.println("Enc1");
    Serial.println(tmpdata1);
  }
  
  int8_t tmpdata2;
  tmpdata2 = read_encoder2();
  if(tmpdata2) {
    Serial.println("Enc2");
    Serial.println(tmpdata2);
  }

  int8_t tmpdata3;
  tmpdata3 = read_encoder3();
  if(tmpdata3) {
    Serial.println("Enc3");
    Serial.println(tmpdata3);
  }
  
}

void motor1(String dir) {
  motor1running = 1;
  if(dir == "backward") {
    digitalWrite(motor1APin, LOW);
    digitalWrite(motor1BPin, HIGH);
  }
  else if(dir == "forward") {
    digitalWrite(motor1APin, HIGH);
    digitalWrite(motor1BPin, LOW);    
  } else {
    motor1running = 0;
    digitalWrite(motor1APin, LOW);
    digitalWrite(motor1BPin, LOW);    
  }
}

void motor2(String dir) {
  motor2running = 1;
  if(dir == "backward") {
    digitalWrite(motor2APin, LOW);
    digitalWrite(motor2BPin, HIGH);
  }
  else if(dir == "forward") {
    digitalWrite(motor2APin, HIGH);
    digitalWrite(motor2BPin, LOW);    
  } else {
    motor2running = 0;
    digitalWrite(motor2APin, LOW);
    digitalWrite(motor2BPin, LOW);    
  }
}

void motor3(String dir) {
  motor3running = 1;
  if(dir == "backward") {
    digitalWrite(motor3APin, LOW);
    digitalWrite(motor3BPin, HIGH);
  }
  else if(dir == "forward") {
    digitalWrite(motor3APin, HIGH);
    digitalWrite(motor3BPin, LOW);    
  } else {
    motor3running = 0;
    digitalWrite(motor3APin, LOW);
    digitalWrite(motor3BPin, LOW);    
  }
}

int8_t read_encoder1()
{
  static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
  static uint8_t old_1AB = 0;
  /**/
  old_1AB <<= 2;                   //remember previous state
  old_1AB |= ( ENC_PORT & 0x03 );  //add current state
  return ( enc_states[( old_1AB & 0x0f )]);
}

int8_t read_encoder2()
{
  static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
  static uint8_t old_2AB = 0;
  /**/
  old_2AB <<= 2;                   //remember previous state
  old_2AB |= ( ENC_PORT & 0x03 );  //add current state
  return ( enc_states[( old_2AB & 0x0f )]);
}

int8_t read_encoder3()
{
  static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
  static uint8_t old_3AB = 0;
  /**/
  old_3AB <<= 2;                   //remember previous state
  old_3AB |= ( ENC_PORT & 0x03 );  //add current state
  return ( enc_states[( old_3AB & 0x0f )]);
}

If analog pins are needed for something else, it is possible to move encoder to digital pins 8,9 or 0,1 (losing serial port) with no modification of code logic.

This does not say with not modification of code. What would need to change is the PINC would become PINA or PINB.

If you look at the direct port manipulation page, you will see what pins make up a port (A, B, or C). The PINC is the P(ort)IN(put)X (A, B, or C) way of reading all pins at once.

The & 0x03 part throws away all but the low order pin states.

What you will need to figure out is the mask to keep the lowest pin states (0x03), the next two pins, and the next two pins, and use those three different masks in the three different functions.

Doing that in a MUCH smaller sketch is highly recommended.

Aaah ok, makes sense! Thanks a lot for the help, and you're probably right about the sketch :wink:

Don't use pins 0 or 1. They are reserved for uploading sketches. Since you don't know port manipulation, you should use a library or code that doesn't require you to do so. Here is such a library:

http://code.google.com/p/phi-prompt-user-interface-library/downloads/detail?name=phi_interfaces_V100.zip&can=2&q=#makechanges

The rotary encoder example code even has 3 encoders. Just read THROUGH the library and documentation BEFORE you ask any questions.