Hi everyone,
I am currently planning a project which includes multiple rotary encoders which I want to wire to interrupt pins to reliably get inputs from them.
I want every encoder to do essentially the same thing but dependent on which encoder is turned, some variables in the code will have to change.
Do I have to write a separate function for each one of them? It is not possible to pass an argument (the interrupt pins number in this case) to the called function from the attachInterrupt and I don't really see any other viable option than to write 5 functions (rotary1() rotary2()...) containing the exact same code with a few variables changed.
One other option I thought of would be to call an "intermediary" function which checks for the currently relevant pin and then calls the rotary function with this information passed down, but this is far from an elegant solution and probably slows down the whole process a lot. I really don't want to have to do a separate check for which encoder is being turned because this information is already there, I just don't know how to access it.
I would appreciate if someone with more experience could point me in the right direction here, as it seems very wrong to me even as a relative beginner to write the same code so many times.
Different boards have different processors which have different numbers and types of interrupts. So without a specific board to work on there's no specific answer for your question.
sirsimon771:
Do I have to write a separate function for each one of them?
On an Atmega328 the pinChange interrupts are triggered by any of the 8 I/O pins on an I/O Port so if you had a few encoders connected to a single Port movement of any one of them would trigger the same ISR code. Your code in the ISR would need to figure out which pin was triggered and hence which encoder was moved.
Note that this system may not suitable if more than one encoder can be moved at the same time.
Robin2:
On an Atmega328 the pinChange interrupts are triggered by any of the 8 I/O pins on an I/O Port so if you had a few encoders connected to a single Port movement of any one of them would trigger the same ISR code. Your code in the ISR would need to figure out which pin was triggered and hence which encoder was moved.
Note that this system may not suitable if more than one encoder can be moved at the same time.
...R
Exactly, that would be one way to do it. But if I wire every encoder to its own interrupt pin I would already have the information which encoder is being moved because I know which one is wired to which pin. I'm just asking if there's any way to use this information in the function that is being called by the interrupt, so I don't have to write the same code for all 5 interrupts with slightly changed variables.
If they are turned by hand, there is no need for interrupts.
If driven by a motor then you are in serious bother!
They are being turned by hand, but the microcontroller has a bunch of other tasks at hand which is why I decided to try it with interrupts to increase the reliability. I guess I will try to just read them in the main loop as well and see how well that works (currently waiting for parts to arrive)
The ATmega328 has two so-called external interrupts on pins 2 and 3, that can be set to change/rising/falling. If those are triggered, it was that pin.
It also has three pin change interrupts: for PORTA, PORTB and PORTD. They're enabled on a per-pin basis, but shared between the pin on that PORT. They trigger on each change.
So that are the five you can use. Of course you have to change the code a bit for each ISR as it's about a different pin, different encoder, different counter variable, though you could do most of the work in a single function that the ISRs call, passing in the pin number or encoder number or so.
Or you place all five encoders on a single PORT, enable the pin change interrupts for them, and use a single ISR that then has to figure out which pins have changed.