[Solved] Read every detent position, Rotary Encoder 24 detent 12 pulses

Hi everyone,

I am having trouble to detect every second detent position on my rotary encoder. It is a bourns PEC11R rotary encoder with 24 detents and 12 pulses.

See the attachment for the position of detents in relation to the pulses on A and B.

With the current example code: -> found here

/* Read Quadrature Encoder
   Connect Encoder to Pins encoder0PinA, encoder0PinB, and +5V.

   Sketch by max wolf / www.meso.net
   v. 0.1 - very basic functions - mw 20061220

*/

int val;
int encoder0PinA = 3;
int encoder0PinB = 4;
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = LOW;

void setup() {
  pinMode (encoder0PinA, INPUT);
  pinMode (encoder0PinB, INPUT);
  Serial.begin (9600);
}

void loop() {
  n = digitalRead(encoder0PinA);
  if ((encoder0PinALast == LOW) && (n == HIGH)) {
    if (digitalRead(encoder0PinB) == LOW) {
      encoder0Pos--;
    } else {
      encoder0Pos++;
    }
    Serial.print (encoder0Pos);
    Serial.print ("/");
  }
  encoder0PinALast = n;
}

I am able to read every second pulse. I am guessing I am only recording the detent positions at which A and B are high. How do I modify this code so it also detects the positions where both A and B are low?

I am still quite new to coding with arduino. I would appreciate it if you could add some code :slight_smile:
P.S. I am trying to get this to run on a Nano 33 BLE so unfortunately no possibility of using interrupts on this board to my knowledge.
Alex

The code decrements the value of the counter when pin A changes from LOW to HIGH and pin B is LOW at that time and increments it when pin A changes from LOW to HIGH and pin B is HIGH at that time

Exactly what conditions do you want to count ?

I want to count every detent position (in blue on the drawing).
Let's say I want to increase a variable by one when moving one detent position CW and decrease the same variable by one when turning the encoder one detent position CCW. Hope this clears things up.

Your code would work if the encoder had 24 detents and 24 pulses. But with 12 pulses, you have two detents per full pulse, so you also have to decode the low-going transition.

Try this:

void loop() {
  n = digitalRead(encoder0PinA);
  if ((encoder0PinALast == LOW) && (n == HIGH)) {
    if (digitalRead(encoder0PinB) == LOW) {
      encoder0Pos--;
    } else {
      encoder0Pos++;
    }
  }
  if ((encoder0PinALast == HIGH) && (n == LOW)) {
    if (digitalRead(encoder0PinB) == HIGH) {
      encoder0Pos--;
    } else {
      encoder0Pos++;
    }
  }
  Serial.print (encoder0Pos);
  Serial.print ("/");
  encoder0PinALast = n;
}

Use every transition of both A and B, then the resulting count can be divided by 2 to get the detent count.

Thanks of your code ShermanP
I was initially thinking it was as simple as what you suggested but I gave up.
I tried again and had to modify the code slightly but it works as expected now!! Thank you very much :slight_smile:

This is the code that works:

int val;
int encoder0PinA = 2;
int encoder0PinB = 3;
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = LOW;

void setup() {
  pinMode (encoder0PinA, INPUT);
  pinMode (encoder0PinB, INPUT);
  Serial.begin (9600);
}

void loop() {
  n = digitalRead(encoder0PinA);
  if ((encoder0PinALast == LOW) && (n == HIGH)) {
    if (digitalRead(encoder0PinB) == LOW) {
      encoder0Pos--;
    } else {
      encoder0Pos++;
    }
    Serial.println (encoder0Pos);
  }
  else if ((encoder0PinALast == HIGH) && (n == LOW)) {
    if (digitalRead(encoder0PinB) == HIGH) {
      encoder0Pos--;
    } else {
      encoder0Pos++;
    }
    Serial.println (encoder0Pos);
  }
  encoder0PinALast = n;
}

I had the filter caps and resistors on between the rotary encoder and arduino as suggested in the datasheet:

But the code as above does not work with the additional 10k resistor and 0.01uF caps. Of course I left the pull-up resistors. Removing the filter resistor and cap from one lead (A or B) also gives results as expected but I ended up taking them off of both leads A and B and connect CLK and DT directly to the digital pins which seems to work as good as with the filter cap and resistor on one lead.

The problem with mechanical rotary encoders is switch bounce. But I've never understood that hardware debounce circuit. These days deouncing is usually done in software, with something called the "lookup table" method being the most popular. In your case though, the time it takes to do the serial print may be enough that any bouncing is finished and the switch has settled down by the time you come back and check it again.