Go Down

Topic: Rotary encoder troubles (Read 1 time) previous topic - next topic


Mar 13, 2012, 07:56 pm Last Edit: Mar 13, 2012, 08:08 pm by hammeraxe Reason: 1

I am using the Mega 2560 to poll values from 12 encoders and keep track of their position. Due to the number of encoders I can't use interrupts so my only option seems to be digitalRead().

Code: [Select]

     for(byte i=0; i<24; i++){

And this is the code (C++) I use on the computer to resolve the values: (buffer is the serial input from arduino)
Code: [Select]

int QEM [16] = {0,-1,1,2,1,0,2,-1,-1,2,0,1,2,1,-1,0};
int old_values[12];
int counts[12];

void update_encoder(int num){

if (int(buffer[2*num]-'0')!=int(old_buffer[2*num]-'0')||int(buffer[2*num+1]-'0')!=int(old_buffer[2*num+1]-'0')){

     int New=2*int(buffer[2*num]-'0')+int(buffer[2*num+1]-'0');
     counts[num]+=QEM [old_values[num] * 4 + New];
     old_values[num] =New;

However, this is too slow as the encoders seemingly "skip" positions and after I resolve the quadrature output the resultant angle is a lot less that it should be. Is there any way around this without using interrupts? Addressing the pins directly maybe? Or configuring other pins for interrupts?

Any help would be greatly appreciated.


Addressing the pins directly will definitely be faster than using digitalRead(). But note that you have 24 pin-change interrupts available on the Mega 2560, just enough for 12 encoders. Maybe you can do this with interrupts after all?

Also not sure about the use of '0' in your code and why you keep subtracting it all over the place. Seems unnecessary.

The Rugged Motor Driver: two H-bridges, more power than an L298, fully protected


Oh, I wasn't aware of that. Is this the library you are referring to? Because it claims in the description that it doesn't work with the Mega, although it's not clear whether it is the original Mega or the 2560

The zeros are there to... well... just make the code work. The typecasting was going wrong for some reason unless the  end-of-string characters were removed. This works, so I just stuck with that.


Yes, although I wasn't referring to the pin change library specifically, just the pin change capability of the processor. In fact, before going this route it would be worthwhile to see if you can even access all 24 pin-change-capable pins on the ATmega2560 (some of the ATmega2560 pins aren't even brought out to connectors).

If you're going for maximum speed you probably want to bypass "libraries" altogether and learn how to do it at the lowest level (in the same way as bypassing digitalRead).

The Flexible MIDI Shield: MIDI IN/OUT, stacking headers, your choice of I/O pins


Hmmmmm, I can only seem to find 20 interrupt pins that I can use....

(I'm using pins 2 - 13 for PWM and 0 - 1 can't be used without disrupting serial)

Pin change interrupts are available on:
Pins 50-53 (PB0 - PB3)
Pins 14-15 (PJ0)
Pins A8-A15 (PK0 - PK7)

And external interrupts on pins 18-21.

So that's 20. Pins 10-13 can be used for pin change interrupts but I'm already using them for PWM.  So what would you suggest? Using these 20 and polling the other 4? Polling all of them and trying to make the code as quick as possible? Using 24 interrupts and somehow shifting 4 PWM outputs to different pins (is that even possible?)?

Go Up