Multiple rotary encoders interrupts in one arduino

Hi all,

I am doing a project using three multiple rotary encoders(it can count the number of revolutions = position level) to check whether the position of three targets is in the same level. All encoders are connected in one arduino mega2560, and I use int0, int1, int2 pins for each encoder. I know there is a priority in them, but I want the three interrupts happened at same time, so does anyone know how to do it, or is there any other way I can detect the position of three encoders together?

ted1101:
I know there is a priority in them, but I want the three interrupts happened at same time, so does anyone know how to do it, or is there any other way I can detect the position of three encoders together?

The "happened at the same time" isn't going to work on the Arduino. Maybe Nick can correct me if I'm wrong, but the ISR's you define for each interrupt will be serviced in the order in which they are detected. While the first ISR is being serviced, nothing else can happen, which is why you want to keep them as short as possible. If one fires an interrupt, what do you mean "detect the position of the three encoders"? ISR's detect an event. If the other two encoders are not moving, what are you going to try and read?

Hi all,

I am doing a project using three multiple rotary encoders(it can count the number of revolutions = position level) to check whether the position of three targets is in the same level. All encoders are connected in one arduino mega2560, and I use int0, int1, int2 pins for each encoder. I know there is a priority in them, but I want the three interrupts happened at same time, so does anyone know how to do it, or is there any other way I can detect the position of three encoders together?

What is rotating the encoders?
How fast are they rotating?
How many pulses per revolution do they produce?

My understanding of the Atmega 2560 datasheet is that an interrupt will trigger an ISR and simultaneously disable the response to other interrupts. However if an interrupt condition occurs on another pin while the ISR is in progress it will be recorded and attended to when the ISR completes.

That suggests to me that interrupts can be detected simultaneously but they can only be attended to in sequence and if the time needed to attend to them is longer than the interval before the next "round" of interrupt conditions then some will be lost.

Keeping track of a rotary encoder can impose a heavy computational load on an Arduino.

...R

Do you really mean at the exact same atomic time ? Are they manually driven?

What human perceive as real time is pretty slow for your arduino.. unless you are talking about absolute encoders - for the incremental ones You usually don't detect the position But its modifications

interrupt by default are blocking (as the default behavior is to disable interrupts when entering an ISR and re-enable them afterwards) so it is critically important that the ISR be as fast as possible.

Do you see counting miss when you turn the knobs at the same time? ( Assuming you don't do crazy Serial.print)

but I want the three interrupts happened at same time,

Impossible and unnecessary, the mega2560 is a single core processor and can only do one thing at any one time. But so long as you service three before the first one triggers again you will be fine. You are only not fine if you want to go faster than this and if you do the a Mega is not the best choice.

Grumpy_Mike:
Impossible and unnecessary, the mega2560 is a single core processor and can only do one thing at any one time. But so long as you service three before the first one triggers again you will be fine. You are only not fine if you want to go faster than this and if you do the a Mega is not the best choice.

Thanks, do you have any advice I can make it with other devices?

@ted1101, do not cross-post. Threads merged.

ted1101:
Thanks, do you have any advice I can make it with other devices?

Ever since I first mentioned using interrupts on this forum I have been told many times why not to use them.
In my view it is an urban legend with all its nonsense is stemming from " don't confuse beginners" attitude.
Interrupts have its place in universe , and can do what YOU want to do. Easy, same (relative) time.
It takes some digging thru the spec and planning.
I would not bother with Uno,nor getting involved in "same time" discussions.
But it;s a free country, you do what floats your boat.
Jim

.

@JJ what do you propose?

Rotary encoders are good candidates for ISR - that does not make everything a good candidate. The right tool at the right time...

That's the law of the instrument: "Give Someone a hammer, and he will find that everything he encounters needs pounding." or originally from "I suppose it is tempting, if the only tool you have is a hammer, to treat everything as if it were a nail." (Abraham Maslow, The Psychology of Science /Toward a Psychology of Being) or Abraham Kaplan, The Conduct of Inquiry: Methodology for Behavioral Science)

julyjim:
Ever since I first mentioned using interrupts on this forum I have been told many times why not to use them.
In my view it is an urban legend with all its nonsense is stemming from " don't confuse beginners" attitude.

No Jim that is not why. It is that all too often beginners think an interrupt does something magical and try and use it in totally inappropriate cases.
Typical is in the reading of a push button in an ISR and then reading the flag it sets in the loop function. You might as well just read the push button in the loop. That technique is only suitable for reading a fast pulses that you might ordinarily miss due to the time between polling.

Ted. .how frequently do the readings change?

econjack:
The "happened at the same time" isn't going to work on the Arduino. Maybe Nick can correct me if I'm wrong, but the ISR's you define for each interrupt will be serviced in the order in which they are detected. While the first ISR is being serviced, nothing else can happen, which is why you want to keep them as short as possible. If one fires an interrupt, what do you mean "detect the position of the three encoders"? ISR's detect an event. If the other two encoders are not moving, what are you going to try and read?

My project is to control three stepper motors which move the ball screws up and down on three separate lifters, so I use encoders to measure how much the ball screws move or whether they are moving in the same level correctly.

I am sorry, I am not familiar with this forum system.Should I delete the other one?

ted1101:
Should I delete the other one?

scrumfled:
Ted. .how frequently do the readings change?

I am not so sure frequency of the reading change. One cycle of one pulse that I sent to the motor is larger than 200 microseconds (800 pulses at least). I have three motors, and they will receive the pulses at same frequency and moving at same time. So the encoder will read the change once the motor moves.

Robin2:
What is rotating the encoders?
How fast are they rotating?
How many pulses per revolution do they produce?

My understanding of the Atmega 2560 datasheet is that an interrupt will trigger an ISR and simultaneously disable the response to other interrupts. However if an interrupt condition occurs on another pin while the ISR is in progress it will be recorded and attended to when the ISR completes.

That suggests to me that interrupts can be detected simultaneously but they can only be attended to in sequence and if the time needed to attend to them is longer than the interval before the next "round" of interrupt conditions then some will be lost.

Keeping track of a rotary encoder can impose a heavy computational load on an Arduino.

...R

Sorry I didn't describe clearly.
The rotary encoders are on three ball screws, they will counters how many revolutions the motors rotates. The fastest speed is 1000 RPM/s, and 400 pulses per revolution. I know there is a chance that I may lose some pulses reading, but if the interrupt change reading and the function operate are happened really fast that is finished before the next change coming, will it look like simultaneously?

This may help. I am able to handle multiple interrupts on multiple pins reliably. This it’s a portion of the encoder library I created.

Concept is. Upon interrupt get all pin values now. Then you can handle any pin changes
If 2 pins change then you handle both encoders with the first interrupt trigger. The second interrupt trigger will either show more changes or none which is ok because you caught it on the first test

union Mask{
	volatile uint32_t All;
	volatile uint8_t  Port[4];
};

Mask Now;

static inline void Encode() {
	M = Changed & EncodePinMask;				// only keep Encoder Data
	if (!M)return;                              // no encoder data move on
	for (uint8_t Position = 0; (Position < EncoderPinCtr); Position++) {	// Cycle throug all the pins
		uint8_t Bit = BitNumber[EncoderPinList[Position]];
		if (M >> Bit & 1) {  // See if the pin has changed
			uint8_t DataBit = BitNumber[DataPinLink[Position]];
			if ((Now.All >> Bit & 1)) {             //CLK Pulse went HIGH
				if (Now.All >> DataBit & 1) EncodeValue[Position]--;         // Check if Data Pin is High at the moment of change
				else EncodeValue[Position]++;
			} else if (EncodeModeVal >= 1) { // half step code higher resolution
				if (Now.All >> DataBit & 1)  EncodeValue[Position]++;        // Check if Data Pin is High at the moment of change
				else  EncodeValue[Position]--;
			}
		}
	}
}
ISR(PCINT2_vect) { //this ISR pins 0-7
	Now.Port[0] = PIND; // 0-7
	Now.Port[1] = PINB; // 8-13
	Now.Port[2] = PINC; // A0-A6
	Changed = Now.All ^ PCintLast;// doing a ^ between the current interruption and the last one indicates wich pin changed
	sei();                        // re enable other interrupts at this point, the rest of this interrupt is not so time critical and can be interrupted safely
	Encode();    // Calculate Encoder Data
	
	PCintLast = Now.All;          // we memorize the current state of all PINs in group

}

At 1000 rpm or 16.7 rps and 400 pulses per rev that gives 6680 pulses per second or 149 µsecs between pulses.

In that time the Arduino would have to respond to any other pulses that are created by the other encoders and do something useful with the data.

If the quantity of pulses per second is low enough for the Arduino to keep up it will give the impression of doing everything simultaneously as long as the required output is slow enough. In other words if it must produce an output for every pulse it won’t be simultaneous. But if (for example) it only needs to produce an output every 1000 pulses it should appear simultaneous. (And 1000 is just a number for illustration - it has no significance).

The key to high speeds is minimizing the amount of calculating the Arduino needs to do.

I can’t see the system being any value to you if it misses pulses.

I guess one possibility would be use a separate Arduino with each encoder - but I would see that as a last resort because it brings other complications.

…R