Quadrature Encoders

I can't seem to find much code -anywhere- about decoding quadrature encoders. Or even quadrature decoder chips.

I'm trying to make a closed loop quadrature encoder-based motor controller with the Duemilanove.

Thanks.

Did you see this playground page: http://www.arduino.cc/playground/Main/RotaryEncoders

There's a very good article about encoders here:

http://www.geology.smu.edu/~dpa-www/robo/Encoder/pitt_html/encoders.html

And another about quadrature here:

http://www.mcmanis.com/chuck/robotics/projects/lab-x3/quadratrak.html

Another mention here:

http://www.barello.net/Robots/firebot/index.htm

And a photo of my own attempt here:

http://letsmakerobots.com/node/3815

Thanks, the playground code should be close enough to start with.

Doesn't anyone else find it a bit odd that there is such a limited amount of info on code on the net about decoding quadrature encoders, let alone dedicated ASICS for that purpose?

Am I searching for the wrong thing? I have found only a few sources that make decoder chips, and they do much more than just plain simple quadrature decoding with direction and count output.

The middle bunch of code on “Reading Rotary Encoders” page does not compile. It is in the section titled “Code for reading encoder using 2 interrupts on pin 2 & pin3”

It gives the

function-definition is not allowed here before ‘{’ token

error.

I’m not familiar enough with C to figure out why. Help, anyone?

The code compiles ok for me in versions 0012 and 0013. What Arduino version are you using and what OS are you using?

Duemilanove, received 2 weeks ago.

XP Pro SP2

I just copied and pasted, maybe that's the problem?

I just realized it is the third of the four sketches on that page. I'm not sure what you mean by 0012 and 0013?

Perhaps you could double check that you copied it correctly. if it still doesn’t work, paste exactly the same code you are trying to compile into a reply here.

0013 is the current Arduino release, 0012 is the previous release.

Here it is, but I really just copied/pasted it from the playground page. Still won't compile.

define encoder0PinA 2

define encoder0PinB 3

volatile unsigned int encoder0Pos = 0;

void setup() {

pinMode(encoder0PinA, INPUT); pinMode(encoder0PinB, INPUT);

// encoder pin on interrupt 0 (pin 2)

attachInterrupt(0, doEncoderA, CHANGE);

// encoder pin on interrupt 1 (pin 3)

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 } }

// Look for a high-to-low on channel B

else { // check channel B to see which way encoder is turning if (digitalRead(encoder0PinA) == LOW) { encoder0Pos = encoder0Pos + 1; // CW } else { encoder0Pos = encoder0Pos - 1; // CCW } }

}

I have the 0013 release. Thanks.

void loop(){ //Do stuff here }

There’s the problem. The closing curly bracket is commented out by the two slashes. This needs to be written out on at least two lines, maybe three:

void loop ()
{ //Do stuff here
}

Done. Compiled. Thanks.

This code stuff is so picky! :-X

This code stuff is so picky!

That's what I like about it!

Could decoding quadrature encoders be a simple as this.

pinMode(2, INPUT); // interrupt 0, pin 2
attachInterrupt(0, Decoder, CHANGE); // encoder trips interrupt on change at pin 2

void Decoder()
{
if (digitalRead(2) == digitalRead(4));
{
encoderCount = encoderCount + 1; //if on interrupt the encoder channels
//are the same, count up
}
else
{
encoderCount = encoderCount - 1; //if they are not the same, count down
}
}

After much more searching and thinking about how they work, this is where I’ve ended up.
Anyone see any issues? This looks too simple.

It does look simple but it is the same logic as the Playground encoder code, so if that works so should yours.

Have you tried it?

Don't have a set up to try it out yet. That's next on the ToDo list.

I'll post as soon as there something worth posting.

I'll run it by a "C" expert friend of mine and an EE motor control guy to get their input also.

Just had another look at the code and I think you may need to call Decode when either pin changes. Try adding this to setup: attachInterrupt(1, Decoder, CHANGE);

This would mean you would need to use pin 3 instead of pin 4

I tried this code and it decodes direction just fine. I'm on to calculating rpm now.

BTW: How do I get my example code inside those cool windows I see on other posts?

CODE: volatile int dir = 0;

void setup() { pinMode(2, INPUT); //interrupt input pinMode(4, INPUT); //other encoder channel input attachInterrupt(0, Decoder, CHANGE); //encoder trips interrupt on change at pin 2 pinMode(13, OUTPUT); //for debugging }

void loop() { //other stuff }

void Decoder() { if (digitalRead(2) == digitalRead(4)) { dir = 1; //if on interrupt the encoder channels are the same, direction is positive digitalWrite(13, LOW); } else { dir = -1; //if they are not the same, direction is negative digitalWrite(13, HIGH); } }

In the reply toolbar click the '#' icon and paste your code between markers.

[c0de]your code goes here [/c0de]

Have you tried using a second encoder?

Only have one encoder right now, but will test as soon as I get another one. Are you anticipating problems?

not seen it done before so just looking for confirmation that it works, but not expecting any problems.

That said, I've spent lots of time fixing stuff over the years that that really should have worked and didn't ;)