Rotary encoder and interrupts

I'm starting to learn and experiment with rotary encoders. I'm following some of the examples on the rotary encoders page (http://arduino.cc/playground/Main/RotaryEncoders). I'm able to get the first example to work, however I'm not able to get any of the examples which use interrupts to work. The settings for the pins in my code are correct, however, when I turn my encoder, the interrupts never get called.

My processor is an Arduino Duemilanove. I have everything setup correctly (I think). I'm able to get serial output from the other sketches I've made, and like I said, the first non-interrupt example on the rotary encoder example page works fine.

Is there a step I'm missing? Is there something 'extra' I have to do in order to get interrupts to work? I'm new to interrupts so I'm not sure how to troubleshoot this.

Thanks,

Jeff

PS. If this message belongs in a different forum, please let me know.

Well first question I would ask is what two arduino pins numbers are you wiring your encoder channels to. And while I know you said you are running the example sketches, you really should post a copy of the exact sketch you are running that doesn't work correctly. Copy it from your IDE sketch editor and past it here in a code (#) window.

Lefty

The pins are 11 and 12.

As far as the code goes, here is the code which works (but doesn't use interrupts):

const int encoder0PinA = 11; const int encoder0PinB = 12; int encoder0Pos = 0;

int encoder0PinALast = LOW; int encoder0PinBLast = LOW;

void setup() { pinMode(encoder0PinA, INPUT); pinMode(encoder0PinB, INPUT); Serial.begin(9600); }

void loop() { int encoder0PinANew = digitalRead(encoder0PinA); int encoder0PinBNew = digitalRead(encoder0PinB);;

if(encoder0PinANew == encoder0PinALast && encoder0PinBNew == encoder0PinBLast) { //Serial.println(" no change"); return; }

char chOutputBuffer[80]; sprintf(chOutputBuffer, "%4d %4d", encoder0PinANew, encoder0PinBNew); Serial.println(chOutputBuffer);

if(encoder0PinANew != encoder0PinALast) { if(encoder0PinANew == encoder0PinBNew) { Serial.println(" increasing"); } else { Serial.println(" decreasing"); } } else { if(encoder0PinANew == encoder0PinBNew) { Serial.println(" decreasingX"); } else { Serial.println(" increasingX"); } }

encoder0PinALast = encoder0PinANew; encoder0PinBLast = encoder0PinBNew;

delay(500); }

...and the code which uses interrupts (but doesn't print anything) is:

define encoder0PinA 12

define encoder0PinB 11

volatile unsigned int encoder0Pos = 0;

void setup() { pinMode(encoder0PinA, INPUT); pinMode(encoder0PinB, INPUT);

// encoder pin on interrupt 0 (pin 12) attachInterrupt(0, DoEncoderA, CHANGE);

// encoder pin on interrupt 1 (pin 11) attachInterrupt(1, DoEncoderB, CHANGE);

Serial.begin(9600); }

void loop() { // Do stuff here }

void DoEncoderA() { // look for a low-to-high on channel A if (digitalRead(encoder0PinA) == HIGH) { // Check channel B to see which way encoder is turning if (digitalRead(encoder0PinB) == LOW) { encoder0Pos = encoder0Pos + 1; // CW } else { encoder0Pos = encoder0Pos - 1; // CCW } } else // must be a high-to-low edge on channel A { // check channel B to see which way encoder is turning if (digitalRead(encoder0PinB) == HIGH) { encoder0Pos = encoder0Pos + 1; // CW } else { encoder0Pos = encoder0Pos - 1; // CCW } }

Serial.println (encoder0Pos, DEC); // use for debugging - remember to comment out }

void DoEncoderB() { // look for a low-to-high on channel B if(digitalRead(encoder0PinB) == HIGH) { // check channel A to see which way encoder is turning if(digitalRead(encoder0PinA) == HIGH) { encoder0Pos = encoder0Pos + 1; // CW } else { encoder0Pos = encoder0Pos - 1; // CCW } } else // Look for a high-to-low on channel B { // Check channel B to see which way encoder is turning if (digitalRead(encoder0PinA) == LOW) { encoder0Pos = encoder0Pos + 1; // CW } else { encoder0Pos = encoder0Pos - 1; // CCW } } }

I'm new to interrupts, so I'm just starting to learn about them. The code for the second sketch was taken from the rotary encoders tutorial page. I've tried all of the different samples on the page which use interrupts, and none seem to work for me.

Ok, the problem is your pin choices. User interrupts are 'hardwired' to only use arduino pin number 2 and 3 on a 328p based board. Interrupt0 = pin 2 and interrupt1 = pin 3.

So changes need are:

const int encoder0PinA = 2;
const int encoder0PinB = 3;

// encoder pin on interrupt 0 (pin 2)
   attachInterrupt(0, DoEncoderA, CHANGE);

   // encoder pin on interrupt 1 (pin 3)
   attachInterrupt(1, DoEncoderB, CHANGE);

Ah, thanks! That solved it. I didn't know that interrupts had to be on certain pins. I guess that makes sense though.

I'm planning on building something that takes two encoders, so I'll need four pins which can handle interrupts. Can any of the other pins handle interrupts?

Thanks,

Jeff

Yes but a different type of interrupt. This is the pin change interrupt and works in a slightly diffrent way. Google it for examples.

Jeff009: Ah, thanks! That solved it. I didn't know that interrupts had to be on certain pins. I guess that makes sense though.

I'm planning on building something that takes two encoders, so I'll need four pins which can handle interrupts. Can any of the other pins handle interrupts?

Thanks,

Jeff

Actually you can get by supporting two encoders using just two user interrupt pins by having each encoder use one interrupt pin and one non-interrupt pin for their two channels. You have to tweak the code a little but it can be done. An arduino mega board supports 5 user interrupt pins.

Lefty