Pololu Magnetic Encoder 12cpr

Hello,
I'm reading a Polulu Magnetic Encoder incorrectly. I have this encoder attach to my Arduino/motor.

One full rotation is outputting 3 counts and it should be outputting 20 counts. I tried the following code with a rotary encoder and it was giving me the right cpr. I'm not sure why this magnetic encoder is outputting the wrong value.

#define encoderPinA 2
#define encoderPinB 3
#define CPR 12
volatile int counter =0;
volatile boolean flag;

volatile int var_degrees =0;

void setup() {
  pinMode(9, OUTPUT);
  pinMode(encoderPinA, INPUT_PULLUP);
  pinMode(encoderPinB, INPUT_PULLUP);
  Serial.begin (9600);
  attachInterrupt(digitalPinToInterrupt(encoderPinA), isr_A, CHANGE); //INTERRUPT FOR A
  attachInterrupt(digitalPinToInterrupt(encoderPinB), isr_B, CHANGE); //INTERRUPT FOR B
}

void loop() {
  
   if(flag == true){     
        var_degrees = ((360/20)*counter); // convert from counts to degrees
       Serial.println(var_degrees);
        flag = false;
  }
 
//Interrupts 

void isr_A(){

  
flag = true;
  if(digitalRead(encoderPinA) == HIGH){
    if(digitalRead(encoderPinB) == LOW){
      counter = counter -1; //COUNTER CLOCK WISE
    }
    else{
      counter = counter +1; //CLOCK WISE
    }
  }
  else{ //IF PIN A IS LOW
    if(digitalRead(encoderPinB) == LOW){
      counter = counter +1; //CLOCK WISE
    }
    else{
      counter = counter -1 ; //COUNTER CLOCK WISE
    }
  }
  
}

void isr_B(){

  
flag = true;
  if(digitalRead(encoderPinB) == HIGH){
    if(digitalRead(encoderPinA) == HIGH){
      counter = counter + 1; 
    }
    else{
      counter = counter -1; 
    }
  }
  else{ //IF PIN A IS LOW
    if(digitalRead(encoderPinA) == LOW){
      counter = counter +1; 
    }
    else{
      counter = counter -1 ; 
    }
  }
  
}

Please post a wiring diagram (hand drawn, not a Fritzing mess).

Note: to get the full resolution of the encoder, you have to have an interrupt or poll event for every transition (rising and falling) on both A and B channels.

Would this encoder example from the playground help?

One full rotation is outputting 3 counts and it should be outputting 20 counts. I tried the following code with a rotary encoder and it was giving me the right cpr. I'm not sure why this magnetic encoder is outputting the wrong value.

As others have indicated, you are not reading all the available quadrature transitions. Your code is reading only one of the four transitions available. With a 20 cpr encoder, you should be seeing 5 counts/rev with your code.

There is a very similar encoder with 12 cpr, and that would give 3 counts with your code. Are you certain that you have the 20 cpr encoder?

Thank you for your reply. I appreciate it a lot. I used this code to read a rotary encoder with 256 cpr. and it seemed to be working right or at least outputting the write output which is 256 in one full rotation. I need to admit I am a little bit lost about reading encoder using interrupts. Does this mean I need to have two ISR one for A and one for B? why? if yes, I need to attach two interrupts as well for pinA and Pin B? why?. How do I properly read all the available quadrature transitions?
I used the example provided from the Arduino playground. I really hope I can get guidance in the code and hoping I will get a fully understanding of reading encoders using interrupts.

void isr_A(){

  
flag = true;
  if(digitalRead(encoderPinA) == HIGH){
    if(digitalRead(encoderPinB) == LOW){
      counter = counter -1; //COUNTER CLOCK WISE
    }
    else{
      counter = counter +1; //CLOCK WISE
    }
  }
  else{ //IF PIN A IS LOW
    if(digitalRead(encoderPinB) == LOW){
      counter = counter +1; //CLOCK WISE
    }
    else{
      counter = counter -1 ; //COUNTER CLOCK WISE
    }
  }
  
}

void isr_B(){

  
flag = true;
  if(digitalRead(encoderPinB) == HIGH){
    if(digitalRead(encoderPinA) == HIGH){
      counter = counter + 1; //COUNTER CLOCK WISE
    }
    else{
      counter = counter -1; //CLOCK WISE
    }
  }
  else{ //IF PIN A IS LOW
    if(digitalRead(encoderPinA) == LOW){
      counter = counter +1; //CLOCK WISE
    }
    else{
      counter = counter -1 ; //COUNTER CLOCK WISE
    }
  }
  attachInterrupt(digitalPinToInterrupt(encoderPinA), isr_A, RISING); //INTERRUPT
  attachInterrupt(digitalPinToInterrupt(encoderPinA), isr_B, RISING); //INTERRUPT

You only have 1 attach interrupt and it's set to rising, won't see channel A when it falls.

so it has to be rising for A. and falling for B?

The examples I have seen set up the interrupt on both pins as CHANGE.
You know, like the linked tutorial I included up in reply #2.

Yeah. I didn't update it but it is like this :

attachInterrupt(digitalPinToInterrupt(encoderPinA), isr_A, CHANGE); //INTERRUPT
attachInterrupt(digitalPinToInterrupt(encoderPinB), isr_B, CHANGE); //INTERRUPT

I really hope I can get guidance in the code

Then post ALL the code, using code tags.

And where is that wiring diagram?

Updated. I actually found out that the encoder is 12 CPR and not 20.
Here is my updated code.

1st test

This is the output I am getting in one full rotation:
1
4
9
11
12

2nd test

How is it incrementing from 1 to 4 then 9 to 11 and 12.. dont really get it?
Every time gets me the right output which is 12 but the increment are different. why?

2
6
10
12

#define encoderPinA 2
#define encoderPinB 3
#define CPR 20
volatile int counter =0;
volatile boolean flag;

volatile int var_degrees =0;

void setup() {
  pinMode(9, OUTPUT);
  pinMode(encoderPinA, INPUT_PULLUP);
  pinMode(encoderPinB, INPUT_PULLUP);
  Serial.begin (9600);
  attachInterrupt(digitalPinToInterrupt(encoderPinA), isr_A, CHANGE); //INTERRUPT FOR A
  attachInterrupt(digitalPinToInterrupt(encoderPinB), isr_B, CHANGE); //INTERRUPT FOR B
}

void loop() {
  
   if(flag == true){     
        var_degrees = ((360/20)*counter); // convert from counts to degrees
       Serial.println(var_degrees);
        flag = false;
  }
 
//Interrupts 

void isr_A(){

  
flag = true;
  
  if(digitalRead(encoderPinA) == HIGH){
    
    if(digitalRead(encoderPinB) == LOW){
      counter = counter +1; //COUNTER CLOCK WISE
    }
    else{
      counter = counter -1; //CLOCK WISE
    }
  }
  else{ //IF PIN A IS LOW
    if(digitalRead(encoderPinB) == HIGH){
      counter = counter +1; //CLOCK WISE
    }
    else{
      counter = counter -1 ; //COUNTER CLOCK WISE
    }
  }
  
}

void isr_B(){

  
flag = true;
  if(digitalRead(encoderPinB) == HIGH){
    if(digitalRead(encoderPinA) == HIGH){
      counter = counter + 1; //COUNTER CLOCK WISE
    }
    else{
      counter = counter -1; //CLOCK WISE
    }
  }
  else{ //IF PIN A IS LOW
    if(digitalRead(encoderPinA) == LOW){
      counter = counter +1; //CLOCK WISE
    }
    else{
      counter = counter -1 ; //COUNTER CLOCK WISE
    }
  }
  
}

And where is that wiring diagram?

jremington:

The wiring diagram of my Arduino to the encoder? I am only using GND VDD A AND B. I don't have a wiring diagram. It is pretty straightforward the connection. My apologies.
Encoder : Arduino
GND GND
VDD 5V
A PIN 2
B PIN 3

cattledog:
As others have indicated, you are not reading all the available quadrature transitions. Your code is reading only one of the four transitions available. With a 20 cpr encoder, you should be seeing 5 counts/rev with your code.

There is a very similar encoder with 12 cpr, and that would give 3 counts with your code. Are you certain that you have the 20 cpr encoder?

Yes, I am using 12 CPR encoder. My apologies. I also modified the code but still confused since it seems to get the right output in one rotation but every time the numbers are different.

2
6
10
12

I also modified the code

Which you AGAIN failed to post.

Will you ever figure out how to use this forum sensibly?

claudilla:
I don't have a wiring diagram.

But you can make one.
Get a pencil.
Get some paper.
Draw the hardware with all important detail.
Take a digital picture of it.
Post it here.
Follow this handy image guide

jremington:
Which you AGAIN failed to post.

Will you ever figure out how to use this forum sensibly?

I posted the code in the previous reply. I updated my code in the original entry.

claudilla:
I updated my code in the original entry.

Don't do that. It breaks the flow of the thread. Go ahead and correct typos in previous posts. But do not change the content.

It you DO make significant changes to the content of an earlier post, nobody can understand who said what, when.

Instead, post your new information in a new reply.