Problem with rotary encoders and attachInterrupts

Hi !

I'm trying to use the position feedback of rotary encoders to control DC motors with an Arduino 328-based.
Here is the product : Wheel_Encoders_for_DFRobot_3PA_and_4WD_Rovers__SKU_FIT0029_-DFRobot

And my code :

#define LEFT 0
#define RIGHT 1

volatile long coder[2] = {0,0};
volatile int lastSpeed[2] = {0,0};  

void setup() {
  Serial.begin(9600);                            //init the Serial port to print the data
  attachInterrupt(LEFT, LwheelSpeed, CHANGE);    //init the interrupt mode for the digital pin 2
  attachInterrupt(RIGHT, RwheelSpeed, CHANGE);   //init the interrupt mode for the digital pin 3
}
 
void loop(){
  static unsigned long timer = 0;                //print manager timer
   
  if(millis() - timer > 100){                   
    Serial.print("Coder value: ");
    Serial.print(coder[LEFT]);
    Serial.print("[Left Wheel] ");
    Serial.print(coder[RIGHT]);
    Serial.println("[Right Wheel]");
     
    lastSpeed[LEFT] = coder[LEFT];   //record the latest speed value
    lastSpeed[RIGHT] = coder[RIGHT];
    timer = millis();
  }
}
 
void LwheelSpeed() {
  coder[LEFT] ++;  //count the left wheel encoder interrupts
}
 
void RwheelSpeed() {
  coder[RIGHT] ++; //count the right wheel encoder interrupts
}

Basically, it just gives serial feedback.

When the right wheel is spinning alone (pin 3 -> interrupt 1), I see coder[ RIGHT ] values increase.

When the left wheel is spinning alone very slowly (pin 2 -> interrupt 0), coder[ LEFT ] increase normally.

When the left wheel is spinning fast alone, both coder[ LEFT ] and coder[ RIGHT ] increase so the coder[ RIGHT ] values go completely crazy (it's not even a linear deviation). Even if the right encoder is unplugged or if I use another Arduino board. The faster the left wheel spins, the wilder coder[ RIGHT ] goes.

When both wheels are spinning, coder[ LEFT ] is normal while coder[ RIGHT ] seems to add coder[ LEFT ] values over its own.

It changes nothing if I switch the coders, it's always the pin 2 which affects the pin 3 no matter which signal it receives.

So, any clue about this ?

Thanks.

For the Due, the interrupt number is the same as the pin number.

Sorry, my bad, it's just a 328-based Arduino, not a Due (the other one I have is a Pro mini). Corrected in the first message.

Some more feedback…

When moving forward (2 wheels) very slowly :

Coder value: 0[Left Wheel] 0[Right Wheel]
Coder value: 0[Left Wheel] 0[Right Wheel]
Coder value: 1[Left Wheel] 0[Right Wheel]
Coder value: 1[Left Wheel] 1[Right Wheel]
Coder value: 2[Left Wheel] 1[Right Wheel]
Coder value: 2[Left Wheel] 2[Right Wheel]
Coder value: 2[Left Wheel] 2[Right Wheel]
Coder value: 2[Left Wheel] 2[Right Wheel]
Coder value: 3[Left Wheel] 2[Right Wheel]
Coder value: 3[Left Wheel] 3[Right Wheel]
Coder value: 4[Left Wheel] 3[Right Wheel]
Coder value: 4[Left Wheel] 3[Right Wheel]
Coder value: 4[Left Wheel] 4[Right Wheel]
Coder value: 4[Left Wheel] 4[Right Wheel]
Coder value: 5[Left Wheel] 4[Right Wheel]
Coder value: 5[Left Wheel] 4[Right Wheel]
Coder value: 6[Left Wheel] 5[Right Wheel]
Coder value: 6[Left Wheel] 5[Right Wheel]
Coder value: 6[Left Wheel] 5[Right Wheel]
Coder value: 6[Left Wheel] 6[Right Wheel]
Coder value: 6[Left Wheel] 6[Right Wheel]
Coder value: 7[Left Wheel] 6[Right Wheel]
Coder value: 7[Left Wheel] 6[Right Wheel]
Coder value: 8[Left Wheel] 6[Right Wheel]
Coder value: 8[Left Wheel] 7[Right Wheel]
Coder value: 8[Left Wheel] 7[Right Wheel]
Coder value: 8[Left Wheel] 7[Right Wheel]
Coder value: 8[Left Wheel] 8[Right Wheel]
Coder value: 9[Left Wheel] 8[Right Wheel]
Coder value: 9[Left Wheel] 8[Right Wheel]
Coder value: 10[Left Wheel] 8[Right Wheel]
Coder value: 10[Left Wheel] 9[Right Wheel]
Coder value: 10[Left Wheel] 9[Right Wheel]
Coder value: 10[Left Wheel] 9[Right Wheel]
Coder value: 10[Left Wheel] 10[Right Wheel]
Coder value: 11[Left Wheel] 10[Right Wheel]
Coder value: 11[Left Wheel] 10[Right Wheel]
Coder value: 12[Left Wheel] 10[Right Wheel]
Coder value: 12[Left Wheel] 11[Right Wheel]
Coder value: 12[Left Wheel] 11[Right Wheel]
Coder value: 12[Left Wheel] 12[Right Wheel]
Coder value: 13[Left Wheel] 12[Right Wheel]
Coder value: 13[Left Wheel] 12[Right Wheel]
Coder value: 13[Left Wheel] 12[Right Wheel]
Coder value: 14[Left Wheel] 12[Right Wheel]
Coder value: 14[Left Wheel] 13[Right Wheel]
Coder value: 14[Left Wheel] 13[Right Wheel]
Coder value: 14[Left Wheel] 13[Right Wheel]
Coder value: 14[Left Wheel] 14[Right Wheel]
Coder value: 15[Left Wheel] 14[Right Wheel]
Coder value: 15[Left Wheel] 14[Right Wheel]
Coder value: 15[Left Wheel] 14[Right Wheel]
Coder value: 16[Left Wheel] 14[Right Wheel]
Coder value: 16[Left Wheel] 14[Right Wheel]
Coder value: 16[Left Wheel] 15[Right Wheel]
Coder value: 16[Left Wheel] 15[Right Wheel]
Coder value: 16[Left Wheel] 16[Right Wheel]
Coder value: 17[Left Wheel] 16[Right Wheel]
Coder value: 17[Left Wheel] 16[Right Wheel]
Coder value: 17[Left Wheel] 16[Right Wheel]
Coder value: 18[Left Wheel] 16[Right Wheel]
Coder value: 18[Left Wheel] 17[Right Wheel]
Coder value: 18[Left Wheel] 17[Right Wheel]
Coder value: 18[Left Wheel] 17[Right Wheel]
Coder value: 18[Left Wheel] 18[Right Wheel]
Coder value: 19[Left Wheel] 18[Right Wheel]
Coder value: 19[Left Wheel] 18[Right Wheel]
Coder value: 20[Left Wheel] 18[Right Wheel]
Coder value: 20[Left Wheel] 19[Right Wheel]
Coder value: 20[Left Wheel] 19[Right Wheel]
Coder value: 20[Left Wheel] 20[Right Wheel]
Coder value: 21[Left Wheel] 20[Right Wheel]
Coder value: 21[Left Wheel] 20[Right Wheel]
Coder value: 21[Left Wheel] 20[Right Wheel]
Coder value: 22[Left Wheel] 20[Right Wheel]

The same but faster :

Coder value: 0[Left Wheel] 1[Right Wheel]
Coder value: 1[Left Wheel] 4[Right Wheel]
Coder value: 2[Left Wheel] 11[Right Wheel]
Coder value: 4[Left Wheel] 16[Right Wheel]
Coder value: 5[Left Wheel] 21[Right Wheel]
Coder value: 6[Left Wheel] 24[Right Wheel]
Coder value: 8[Left Wheel] 31[Right Wheel]
Coder value: 8[Left Wheel] 51[Right Wheel]
Coder value: 10[Left Wheel] 62[Right Wheel]
Coder value: 11[Left Wheel] 73[Right Wheel]
Coder value: 12[Left Wheel] 88[Right Wheel]
Coder value: 14[Left Wheel] 103[Right Wheel]
Coder value: 15[Left Wheel] 116[Right Wheel]
Coder value: 16[Left Wheel] 130[Right Wheel]
Coder value: 18[Left Wheel] 159[Right Wheel]
Coder value: 19[Left Wheel] 196[Right Wheel]
Coder value: 21[Left Wheel] 224[Right Wheel]
Coder value: 23[Left Wheel] 253[Right Wheel]

Just spinning the right wheel :

Coder value: 0[Left Wheel] 0[Right Wheel]
Coder value: 0[Left Wheel] 0[Right Wheel]
Coder value: 0[Left Wheel] 1[Right Wheel]
Coder value: 0[Left Wheel] 2[Right Wheel]
Coder value: 0[Left Wheel] 2[Right Wheel]
Coder value: 0[Left Wheel] 2[Right Wheel]
Coder value: 0[Left Wheel] 3[Right Wheel]
Coder value: 0[Left Wheel] 3[Right Wheel]
Coder value: 0[Left Wheel] 4[Right Wheel]
Coder value: 0[Left Wheel] 4[Right Wheel]
Coder value: 0[Left Wheel] 4[Right Wheel]
Coder value: 0[Left Wheel] 5[Right Wheel]
Coder value: 0[Left Wheel] 6[Right Wheel]
Coder value: 0[Left Wheel] 6[Right Wheel]
Coder value: 0[Left Wheel] 6[Right Wheel]
Coder value: 0[Left Wheel] 7[Right Wheel]
Coder value: 0[Left Wheel] 7[Right Wheel]
Coder value: 0[Left Wheel] 8[Right Wheel]
Coder value: 0[Left Wheel] 8[Right Wheel]
Coder value: 0[Left Wheel] 8[Right Wheel]
Coder value: 0[Left Wheel] 9[Right Wheel]
Coder value: 0[Left Wheel] 10[Right Wheel]
Coder value: 0[Left Wheel] 10[Right Wheel]
Coder value: 0[Left Wheel] 10[Right Wheel]
Coder value: 0[Left Wheel] 10[Right Wheel]
Coder value: 0[Left Wheel] 11[Right Wheel]
Coder value: 0[Left Wheel] 11[Right Wheel]
Coder value: 0[Left Wheel] 12[Right Wheel]
Coder value: 0[Left Wheel] 44[Right Wheel]
Coder value: 2[Left Wheel] 222[Right Wheel] <- spinning faster from there
Coder value: 2[Left Wheel] 397[Right Wheel]
Coder value: 2[Left Wheel] 486[Right Wheel]
Coder value: 2[Left Wheel] 492[Right Wheel]
Coder value: 2[Left Wheel] 493[Right Wheel]

Just spinning the left wheel :

Coder value: 0[Left Wheel] 0[Right Wheel]
Coder value: 0[Left Wheel] 0[Right Wheel]
Coder value: 1[Left Wheel] 0[Right Wheel]
Coder value: 2[Left Wheel] 0[Right Wheel]
Coder value: 3[Left Wheel] 0[Right Wheel]
Coder value: 4[Left Wheel] 0[Right Wheel]
Coder value: 5[Left Wheel] 0[Right Wheel]
Coder value: 6[Left Wheel] 0[Right Wheel]
Coder value: 7[Left Wheel] 0[Right Wheel]
Coder value: 8[Left Wheel] 0[Right Wheel]
Coder value: 9[Left Wheel] 0[Right Wheel]
Coder value: 10[Left Wheel] 0[Right Wheel]
Coder value: 11[Left Wheel] 0[Right Wheel]
Coder value: 13[Left Wheel] 0[Right Wheel]
Coder value: 13[Left Wheel] 0[Right Wheel]
Coder value: 13[Left Wheel] 0[Right Wheel]
Coder value: 13[Left Wheel] 0[Right Wheel]
Coder value: 13[Left Wheel] 0[Right Wheel]
Coder value: 13[Left Wheel] 0[Right Wheel]
Coder value: 13[Left Wheel] 0[Right Wheel]
Coder value: 13[Left Wheel] 0[Right Wheel]
Coder value: 13[Left Wheel] 0[Right Wheel]
Coder value: 13[Left Wheel] 0[Right Wheel]
Coder value: 15[Left Wheel] 0[Right Wheel]
Coder value: 16[Left Wheel] 0[Right Wheel]
Coder value: 17[Left Wheel] 0[Right Wheel]
Coder value: 18[Left Wheel] 0[Right Wheel]
Coder value: 19[Left Wheel] 0[Right Wheel]
Coder value: 21[Left Wheel] 0[Right Wheel]
Coder value: 22[Left Wheel] 0[Right Wheel]
Coder value: 23[Left Wheel] 1[Right Wheel]
Coder value: 25[Left Wheel] 2[Right Wheel]
Coder value: 25[Left Wheel] 2[Right Wheel]
Coder value: 25[Left Wheel] 2[Right Wheel]
Coder value: 25[Left Wheel] 2[Right Wheel]
Coder value: 25[Left Wheel] 2[Right Wheel]
Coder value: 25[Left Wheel] 2[Right Wheel]
Coder value: 25[Left Wheel] 2[Right Wheel]
Coder value: 25[Left Wheel] 2[Right Wheel]
Coder value: 27[Left Wheel] 2[Right Wheel]
Coder value: 28[Left Wheel] 24[Right Wheel] <- spinning faster from there
Coder value: 30[Left Wheel] 84[Right Wheel]
Coder value: 32[Left Wheel] 131[Right Wheel]
Coder value: 34[Left Wheel] 207[Right Wheel]
Coder value: 36[Left Wheel] 240[Right Wheel]
Coder value: 37[Left Wheel] 268[Right Wheel]

Moving forward fast with wheels wires switched (Right wheels on pin 2, Left on pin 3) :

Coder value: 0[Left Wheel] 0[Right Wheel]
Coder value: 1[Left Wheel] 0[Right Wheel]
Coder value: 2[Left Wheel] 7[Right Wheel]
Coder value: 3[Left Wheel] 10[Right Wheel]
Coder value: 4[Left Wheel] 14[Right Wheel]
Coder value: 5[Left Wheel] 20[Right Wheel]
Coder value: 7[Left Wheel] 33[Right Wheel]
Coder value: 8[Left Wheel] 48[Right Wheel]
Coder value: 9[Left Wheel] 62[Right Wheel]
Coder value: 11[Left Wheel] 73[Right Wheel]
Coder value: 12[Left Wheel] 91[Right Wheel]
Coder value: 13[Left Wheel] 103[Right Wheel]
Coder value: 15[Left Wheel] 114[Right Wheel]
Coder value: 17[Left Wheel] 129[Right Wheel]
Coder value: 18[Left Wheel] 152[Right Wheel]
Coder value: 19[Left Wheel] 170[Right Wheel]
Coder value: 21[Left Wheel] 181[Right Wheel]
Coder value: 21[Left Wheel] 193[Right Wheel]
Coder value: 23[Left Wheel] 205[Right Wheel]
Coder value: 24[Left Wheel] 220[Right Wheel]
Coder value: 25[Left Wheel] 230[Right Wheel]
Coder value: 27[Left Wheel] 237[Right Wheel]
Coder value: 28[Left Wheel] 254[Right Wheel]
Coder value: 29[Left Wheel] 264[Right Wheel]
Coder value: 30[Left Wheel] 268[Right Wheel]
Coder value: 31[Left Wheel] 268[Right Wheel]
Coder value: 32[Left Wheel] 270[Right Wheel]
Coder value: 33[Left Wheel] 271[Right Wheel]
Coder value: 33[Left Wheel] 271[Right Wheel]
Coder value: 34[Left Wheel] 272[Right Wheel]

I tried to use the internal resistor with

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

No change

This part has actively driven output, pullup resistor is not needed.

No ideas on the code problem tho.

Noisy (glitchy) interrupt lines. Unfortunately, they didn't use a small cap on the input to the schmitt trigger in the encoder, so it could easily output glitchy edges on the output signal.

Please describe how you've made power connections (the encoder needs 5V) ... the motor and Arduno gets its power from?

If power connections are OK, could filter the interrupt signals externally (RC) or could debounce the interrupts in code.

Here's an example for software debounce of both interrupts (untested):

#define LEFT 0
#define RIGHT 1
const unsigned long interval = 200;              //interrupt debounce interval (µs)
volatile unsigned long timeNow[2] = {0, 0};
volatile unsigned long timePrev[2] = {0, 0};
volatile long coder[2] = {0, 0};
volatile int lastSpeed[2] = {0, 0};

void setup() {
  Serial.begin(9600);                            //init the Serial port to print the data
  attachInterrupt(LEFT, LwheelSpeed, CHANGE);    //init the interrupt mode for the digital pin 2
  attachInterrupt(RIGHT, RwheelSpeed, CHANGE);   //init the interrupt mode for the digital pin 3
}

void loop() {
  static unsigned long timer = 0;                //print manager timer

  if (millis() - timer > 100) {
    Serial.print("Coder value: ");
    Serial.print(coder[LEFT]);
    Serial.print("[Left Wheel] ");
    Serial.print(coder[RIGHT]);
    Serial.println("[Right Wheel]");

    lastSpeed[LEFT] = coder[LEFT];   //record the latest speed value
    lastSpeed[RIGHT] = coder[RIGHT];
    timer = millis();
  }
}

void LwheelSpeed() {
  timeNow[LEFT] = micros();
  if (timeNow[LEFT] - timePrev[LEFT] > interval) {
    timePrev[LEFT] += interval;
    coder[LEFT] ++;  //count the left wheel encoder interrupts
  }
}

void RwheelSpeed() {
  timeNow[RIGHT] = micros();
  if (timeNow[RIGHT] - timePrev[RIGHT] > interval) {
    timePrev[RIGHT] += interval;
    coder[RIGHT] ++; //count the right wheel encoder interrupts
  }
}

dlloyd:
Noisy (glitchy) interrupt lines. Unfortunately, they didn't use a small cap on the input to the schmitt trigger in the encoder, so it could easily output glitchy edges on the output signal.

Please describe how you've made power connections (the encoder needs 5V) ... the motor and Arduno gets its power from?

If power connections are OK, could filter the interrupt signals externally (RC) or could debounce the interrupts in code.

thanks ! The Arduino is powered by USB (computer), the coders and motors are powered by a 4 AA battery pack (4×1.2 V).

I will test your code later. Thank you very much !

Hi !

So this code doesn't change the noise problem. I tried to connect all the grounds as well, as advised by the manufacturer.

It seems to be a problem with the pin 3, which is an interrupter and a PWM pin whereas the pin 2 is just an interrupter. Even when the right encoder is disconnected, I get noise on the pin 3. But it's not the Arduino in itself because the problem remains the same on 2 others boards.