Encoder doesn't produce usefull data?

I got an EC11 Rotary Encoder Module by DFRobot. I’ve connected it to an Arduino Mega 2560 on pins 2,3,4, where three is the push button.

The code is:

void setup() {
  
    Serial.begin(9600);

    pinMode(2, INPUT_PULLUP);
    pinMode(3, INPUT_PULLUP);
    pinMode(4, INPUT_PULLUP);

    attachInterrupt(digitalPinToInterrupt(2), EncoderRotate, CHANGE);
    attachInterrupt(digitalPinToInterrupt(3), EncoderPress, CHANGE);

    Serial.println(); 
    Serial.println();

}

void EncoderRotate(){
  
  if(digitalRead(2) == digitalRead(4)){
    Serial.print("Left");    
    EncoderPosition++;
  }
  else{
    Serial.print("Right");
    EncoderPosition--;
  }

  Serial.println();  
}

void EncoderPress(){
  Serial.print("EncoderPress!");
  Serial.println();
}

When I operate the encoder, one click to the right produces:

Right
EncoderPress!
Right

When I turn it one click right again:

Right
Right
Right
Left
Right

again:

Right
Left
Right

one click left:

Right
Left
Left

again:

Right
Right
Left
Left
Left

again:

Right
Left
Right
Left
EncoderPress!

pressing the encoder once:

EncoderPress!
EncoderPress!

again:

EncoderPress!
EncoderPress!
EncoderPress!
EncoderPress!

again:

EncoderPress!
EncoderPress!
EncoderPress!
EncoderPress!

This is useless. Turning to the left should produce “left” ONCE, to the right, should produce “Right”, ONCE, and the press should produce “Encoder Press!” ONCE.

So there are two problems:

  1. A single action is firing multiple times.
  2. A single action is firing conflicting and incorrect actions. ie. it says “Encoder Press” sometimes when the encoder is not pressed, and “Left, Right, Left”, when the wheel turns one click left.

Is this encoder defective? If not, how can I get it to produce something more useful where one action fires only one time and the correct action is reported?

Hi @lightnb
maybe you get double action because of the change mode. Try falling instead, since you have the pullups activated.
Another bad idea is to use serial.print with 9600 BAUD in your interrupt-service-routines. Make them as short as possible, like toggle a boolean variable. Then react on the boolean while the code is in the regular loop.

I’ve once written a quadrature encoder test routine. Maybe you can destille the best out off it…
quadrature_encoder.txt (2.3 KB)