Pololu Magnetic Encoder 20cpr

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

One full rotation should be 12 CPR. I updated my code and it seems to be giving that, not all the time. Updated.
Here is my updated code. This is the output I am getting in one full rotation:
1
4
9
11
12

How is it incrementing from 1 to 4 then 9 to 11 and 12… dont really get it?




#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) == 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 ; 
    }
  }
  
}

Hello.

How did you determine that you are only getting 3 counts per motor rotation? To get the full resolution, you need to read both the falling and rising edges of the output signals for both channels (A and B). From your code, it looks like you are just reading the rising edge of channel A, and then checking if channel A is low in your ISR. Since you are triggering the ISR when channel A is high, the code for when channel A is low will never execute.

Can you explain where you got the 256 value for your CPR variable? Can you give a broader view of what you are trying to do?

- Amanda

Thank you for your reply. I rotate the encoder 360 degrees. Let me explain it a little bit better. the encoder is attach to the motor and when I run the motor I check to see if my encoder moves 360. So every one full rotation or 360 degrees I am getting 0 1 2 3 counts, but I should be getting 20 cpr. So I tried this code but for a rotary encoder that was 256 cpr and it seemed to be working or at least outputting 256 cpr. For this particular case CPR should be 20 to get converted my counts to degrees. My apologies, I am new to this forum. You said that from my code it looks that I am reading the rising edge of channel A ( attachInterrupt(digitalPinToInterrupt(encoderPinA), isr_2, RISING) and then checking in my ISR_2 if channel A is low. I don’t quite get why the code for when channel A is low will never execute. Could you give an example of what you mean? or the proper way to do it? Does that mean I am not reading all the available quadrature transitions ? if yes, what will be the right way? Yes, I am just trying to get the angle of this magnetic encoder attach to the motor. and after reading the angle tell my motor to run for a specific angle. I UPDATED THE CODE IN MY ORIGINAL POST .Thank you.

UPDATE: THE ENCODER IS 12 CPR NOT 20 CPR

Thanks for letting us know that you modified your first post. In general, we prefer people to create new posts when responding to our requests (e.g. posting pictures and code), so in the future, please do that. This way it makes it easier for others, who might be having a similar issue, to follow the discussion.

Just to be clear, can you provide links to the product pages for the encoder pair kit and motor(s) you are using?

In your original code (before you modified it), you configured an Interrupt to trigger only when the output signal for channel A changes from low to high (attachInterrupt(digitalPinToInterrupt(encoderPinA), isr_2, RISING)), meaning that you are only checking for a high signal transition. So, when entering your ISR, the first condition will always evaluate true, since channel A’s signal will read high, not low. If you want to check both the rising (low to high) and falling (high to low) edges of channel A’s output signal in your ISR, the code should be attachInterrupt(digitalPinToInterrupt(encoderPinA), isr_2, CHANGE). You might find it helpful to look at the documentation for attachInterrupt() on the Arduino website, particularly the function’s mode parameter.

Based on your questions, it sounds like you are not familiar with how quadrature encoders work, I suggest first reading the Incremental rotary encoder section of the Rotary encoder Wikipedia page. You might also consider looking at some of the code examples on the Reading Rotary Encoders page on the Arduino website. If you are still confused and have trouble getting your code to work, you can post your questions and modified code here, and I would be happy to help.

- Amanda

A post was split to a new topic: Safe encoder disk separation