Why rotary encoder must be plugged on interrupt pins?

What if i want to use two rotary encoders on UNO, NANO etc?

I building a frequency generator, with ad9833 the output will also be plugged in pin 5 to use freqcount and measure it.

The generator will have an encoder to increase/decrease frequency, and another to change the scale (x1,x10,x100,x1000...) the first encoder will increase 1*scale.

So i faced the problem that all examples using rotary encoders, uses pins 2 and 3 (on nano) which are the only interrupt pins, if I use any other pins, will it be a problem? (i only have one rotary, but more are on the go, so i cant test yet)

If its a problem, how to solve it? i saw one library that clains to use 4 rotary encoders at same time, but, some parts of the code have conficts with freqcount.

the main question its, why its needed to use interrupt pins? i mean, if the behaviour its like a push button, i can use a push button on any pin, why not rotary encoder "push button"?

Thanks.

PD: encoders are EC11.

Use this encoder library (or study the code)

The popular Encoder library has the capability to work without interrupts:

The potential problem this poses is explained in the comment:

Without interrupts, your program must call the read() function rapidly, or risk missing changes in position.

So I assume that it is manually operated, at low pulse rate. Then it's not required to use interrupts, in detail if mechanical contacts deserve debouncing.

1 Like

thanks, thats the right answer for me.

Yes, it will be manually operated both encoders, the scale encoder will change almost like 1 or 2 Hz, and the other maybe could get .. what to say, 100Hz? on dont know if i could speed it more than that
xD

So if i understood it, interrupts are mandatory if the encoder will click at a very high speed? like measuring an engine?

Also yes, it will use debonce.

Thanks

Right. And there are many more interrupt pins depending on the controller type, like PCINT (Pin Change INTerrupt).

1 Like

oof

in a newbie in arduino, I´m discovering the tricks while I am trying new things xD

thanks again.

It is possible to use a single timer interrupt to handle as many rotary encoders as you have. The example here uses the timer interrupt to sample the encoder pins to detect rotation. The interrupts occur every 1.024 ms, and the pins are sampled every 10 interrupts. This will provide debouncing of mechanical contacts. You won't be able to use PWM on pin 6, as that timer channel is used for the interrupt. The code works for UNO/NANO. The example handles one encoder but can be easily expanded or altered.


#define phaseA 2 // Pins for the encoder
#define phaseB 3

volatile int position;
volatile bool lastPhaseA, lastPhaseB;

void setup() {
  Serial.begin(9600);
  lastPhaseA =digitalRead(phaseA); // initial values
  lastPhaseB = digitalRead(phaseB);
  // Initialize interrupt
  // Configure OC0A for an interrupt
  OCR0A = 128; // Interrupt occurs midway between Arduino time interrupts
  TIMSK0 |= 1 << OCIE0A; // Enable the interrupt

}

void loop() {
  static int oldPosition;
  int pos;
  cli();
  pos = position; // atomic reference
  sei();
  if (pos != oldPosition) {
    oldPosition = pos;
    Serial.println(pos);
  }
}

ISR(TIMER0_COMPA_vect) {
  // Check to see if a pin has changed
  static uint8_t cnt; // check every 10 interrupts
  if (cnt-- == 0) {
    bool a = digitalRead(phaseA);
    bool b = digitalRead(phaseB);
    cnt = 10;
    if (lastPhaseA != a) {
      position += (a == b) ? -1 : 1;
      lastPhaseA = a;
    }
    if (lastPhaseB != b) {
      position += (a == b) ? 1 : -1;
      lastPhaseB = b;
    }
  }
}

I'd just use a more capable processor board. The Teensy LC, for example, supports interrupts on 18 pins.