2

I wrote some code that handles rotary encoder using an interrupt, but I would like to get which pin generated the interrupt, so I'll be able to handle many interrupts in a single method.

Something like:

void ISREncoders()
{
  int pin = GetCurentInterruptPin(); // <============= this
  int dataPin = dataPins[pin];
  int data = DigitalRead(dataPin);
  if(data == HIGH)
  {
    encoders[pin] += 1;
  }
  else
  {
    encoders[pin] -= 1;
  }
}

Is it anyhow possible?


As mentioned in the answer this is not possible. Still, after peeking some encoder libraries that use interrupt found out that they do the following:

The Encoder class contains several static ISR methods hard coded.

As you create new objects it increments an internal counter and sets proper ISR method on the interrupt.

This is for sure the best solution available, but this is not at all scalable, for instance if you have an imaginary board with thousand pins that handle thousands encoders you will have to hard code each ISR method.

VE7JRO
  • 2,497
  • 15
  • 24
  • 29
  • A common data, clock endoder. (when you rotate it generates a clock, and data contains rotation direction information). The objective is to use a single method to handle multiple encoders, I would like to know wich pin generated the interrupt. –  Jul 05 '20 at 19:34
  • What if user rotates two encoders at the same time, and inspite of possibility, two clock pins are in HIGH state? –  Jul 05 '20 at 19:35
  • keep a list of the states of the interrupt pins ... compare list at an interrupt .... anyway, your question is a general programming question ... there is no Arduino component in your question – jsotola Jul 05 '20 at 19:43
  • Polling clock pin is OK, this is not the problem. The question is how to acquire which pin generated the interrupt, so, using interrupts I don't need to constantly poll clock pins. Posted here because it is an arduino (like) issue, and haven't found any information on this on Google. If anyone closes it I would understand. Thanks for your time and effort. –  Jul 05 '20 at 19:46
  • `two clock pins are in HIGH state` ... there is a flaw in your thinking (not related to your question though) ... your thinking should be `two clock pins transition from LOW to HIGH state (or vice versa)` – jsotola Jul 05 '20 at 19:46
  • i said `compare list at an interrupt` ... do not poll constantly ... check the state of all the pins when interrupt is received ... anyway, it may be possible to determine which pin generated the interrupt through hardware, but that would be hardware dependent ... you said nothing about the hardware you are using – jsotola Jul 05 '20 at 19:50
  • Imagine this scenario: two clock pins are in LOW state, they transact (at the same time) to HIGH state, this would generate two interrupts, which interrupt came from which pin? I should handle both encoders once, and skip next interrupt? This is for sure cumbersome to implement, just getting which pin generated the interrupt is easier and more elegant solution. With all due respect a simple: "No it is not possible actually" would be more useful from your part. –  Jul 05 '20 at 19:53
  • Let us [continue this discussion in chat](https://chat.stackexchange.com/rooms/110243/discussion-between-edney-and-jsotola). –  Jul 05 '20 at 19:57

1 Answers1

2

It is not possible to know which interrupt caused the ISR to be called. The INTFx flag gets cleared when the interrupt routine is called, so you lose that information (which is a shame).

The closest you could do is to have a separate ISR for each pin which just calls the common routine with a parameter to say which ISR it was executed via. That will add some extra latency though as it has to make an extra function call, but that can be somewhat mitigated by having the common function marked as always_inline, which means the compiler will duplicate it and place it within the code where it's being called from. This reduces latency but increases code size.

static ISREncoder(uint8_t pin) __attribute__ ((always_inline)) {
    // Do stuff with the `pin` variable
}

void ISR0() { ISREncoder(2); }
void ISR1() { ISREncoder(3); }
Majenko
  • 103,876
  • 5
  • 75
  • 133