2

I'm trying to interface an encoder and a 1602 i2c display. My encoder seems to be giving an output between steps.

I have tried to make my code as simple as possible and am outputting whether the encoder rotated clockwise or counter clockwise to serial. When I rotate the knob one physical step clockwise, '++' (separated by a new line) outputs to the serial monitor when I am expecting just '+'. The same occurs when rotating counter clockwise, except with '--' instead of '++'.

Parts:

Code:

#define enc1 32
#define enc2 33
#define button 25
#define led 2;

int oldPos1;
int newPos1;
int newPos2;

void setup() {
  pinMode(enc1, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(enc1),encRead,CHANGE);
  pinMode(enc2, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(enc2),encRead,CHANGE);
  Serial.begin(115200);

  oldPos1 = digitalRead(enc1);
}

void encRead(){
  newPos1 = digitalRead(enc1);
  newPos2 = digitalRead(enc2);
  if(oldPos1 != newPos1){
    if (newPos1 == newPos2){
      Serial.println("+");
    }
    else{
      Serial.println("-");
    }
  }
  oldPos1 = newPos1;
}

void loop() {
  delay(10);
}
1
  • 2
    remove the enc2 attachInterrupt
    – jsotola
    Jul 17, 2023 at 18:57

2 Answers 2

2

This is the kind of thing that can happen when you buy cheap parts that come with no documentation whatsoever: you don't know how they are supposed to work! Many rotary encoders have two detents per pulse: if you rotate them by a single detent, you get a single transition on each pin. If using such an encoder, you would indeed expect a single + or - printed per detent. But what about the encoder you bought? You can't tell, since there is no documentation!

Quite fortunately, a helpful individual left a useful review on the product page you linked to. It can serve as an ersatz of datasheet:

Each movement of the spindle from one detent to the next results in the encoder1 and encoder2 pins going through multiple transitions, not a single one (as you might expect).

Assuming that you have tied the encoder pins to (say) 5V with a resistor, a rotation between detents, will produce a set of encoder transitions. For example: 11 10 00 01 11 (clockwise) or 11 01 00 10 11 (anti-clockwise).

This explains the behavior you are experiencing.

Side note: as jsotola writes in a comment, you should remove the enc2 attachInterrupt(). As your interrupt handler explicitly ignores transitions in enc2 (it does nothing unless enc1 changed), there is no point in interrupting the processor for those ignored transitions.

1

Unfortunately you did not provide a link to the data sheet of the encoder.

One physical step at the knob can generate changes on both pins. And since you have assigned the interrupt service routine to both pins, it is called two times for each physical step.

Another possible reason is "bouncing" of the mechanical contacts in this encoder. That means, that multiple pulses are generated on the change between open and closed. Therefore, change or edge interrupts are only a correct solution, if you take bouncing into account.

To investigate the issue, you can insert port pin toggles to your interrupt service routine. For example, set a pin on entry and reset it on exit. Then connect an oscilloscope or logic analyzer and compare the input signals and this output.

Oh, and it is never a good idea to put serial output in an interrupt service routine. Depending on the amount of sent data and the chosen baudrate, this output will block the routine for several milliseconds. During this time, the same interrupt is not serviced, and can be skipped in case of multiple triggers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.