Rotary Encoder Help

Does anyone have experience with Rotary Encoder - 1024 P/R (Quadrature) ?

On the hardware side is a custom wood frame connected to a rotating mount. Attached to the back of the frame is a rotary encoder sensor.
I have some problems with finding out what I actually need to get only rotation degrees from pulses..Mechanical absolute encoder or incremental encoder?
If someone have experience with this models please help me with schema and some code.

Thanks!

This is a standard rotary encoder with a high resolution (1024 pulses per rotation). A lot of example code exists for such encoders, a page in the playground may help you further:

http://arduino.cc/playground/Main/RotaryEncoders

On page 5 of the datasheet you have the exact schema of the internals. For most applications wires A (black) and B (white) are enough, you don't need wire Z (orange).

Mechanical absolute encoder or incremental encoder?

Incremental encoder.

I have some problems with finding out what I actually need to get only rotation degrees from pulses.

If you only measure at the rising edge of A you get one pulse per 0.3515625° or about 3 pulses per degree.

Thanks pylon!

What to do with the BLUE wire ?

BROWN - 5V
SMELD - GND

I have Arduino Diecimila. Arduino Diecimila's digital pins 2 and 3 can be used as External Interrupts. I don't understand Interrupt service and how to connect OUTA and OUTB if I want to know encoder turning direction (CW or CCW)..

Here is Example 1 from arduino playground:

 /* Read Quadrature Encoder
  * Connect Encoder to Pins encoder0PinA, encoder0PinB, and +5V.
  *
  * Sketch by max wolf / www.meso.net
  * v. 0.1 - very basic functions - mw 20061220
  *
  */  


 int val; 
 int encoder0PinA = 3;
 int encoder0PinB = 4;
 int encoder0Pos = 0;
 int encoder0PinALast = LOW;
 int n = LOW;

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

 void loop() { 
   n = digitalRead(encoder0PinA);
   if ((encoder0PinALast == LOW) && (n == HIGH)) {
     if (digitalRead(encoder0PinB) == LOW) {
       encoder0Pos--;
     } else {
       encoder0Pos++;
     }
     Serial.print (encoder0Pos);
     Serial.print ("/");
   } 
   encoder0PinALast = n;
 }

Please help me with Interrupt routine and which code is than usable (Interrupt Example, Interrupt Example (the Encoder interrupts the processor)) ??

What to do with the BLUE wire ?

Blue goes to GND as well as the shielding. Brown goes to 5V, correct.

I don't understand Interrupt service and how to connect OUTA and OUTB if I want to know encoder turning direction (CW or CCW)..

OUTA and OUTB has to go to digital IO pin on the Arduino. Do you need an interrupt? How fast will the encoder be rotated? Please tell more about your specs to help you find the best solution for your case. What other devices are connected to your Arduino? How many such decoders do you wanna connect to the Arduino, what's their purpose?

only one decoder..

An explanation of what I'm trying to do is in this 2 videos:

Interrupt are used for faster speeds?

I need a solution for both slow and faster versions..

For both projects you don't need the speed of an interrupt version (both movements are slow in the world of Arduinos), so I'd try with a polling version (the software is easier to understand for the beginner) but use one of the interrupt pins (2 or 3 on an UNO) for at least the OUTA line just to be able to change the software to use interrupts if needs later arise.

I haven't bought encoder yet so I can't test it.
It's not necessary to add extra code for direction (code above) ?

In horizontal position var encoder0Pos would be 0. Code will increase or decrease variable by 1 depending on CW or CCW direction?

degree = encoder0Pos * 0.3515625

bad note:

  • encoder0Pos will be counting forever, that means that if you keep turning into the same direction,
    the serial message will become longer (up to 6 characters), costing more time to transmit..)
  • for higher resolution encoders, there is a possibility that this sketch will not see every individual step.

Pulldown resistors (10k) are going to be needed on the inputs in Interrupt Example from arduino playground?
Does I need also Low pass or Kalman filters for smoothing sets of data?

It's not necessary to add extra code for direction (code above) ?

Your code already includes the direction switch, that's why the encoderPos is either incremented or decremented.

In horizontal position var encoder0Pos would be 0. Code will increase or decrease variable by 1 depending on CW or CCW direction?

It's on you to decide that, you have to calibrate it.

encoder0Pos will be counting forever, that means that if you keep turning into the same direction, the serial message will become longer (up to 6 characters), costing more time to transmit..)

Correct, but with a statement like this, you can change that:

encoderPos = encoderPos % 1024;

This way you alway get the same value for the same position (given you calibrated the sensor in some known position).

for higher resolution encoders, there is a possibility that this sketch will not see every individual step.

Theoretically correct, but in practical live you won't have that problem. For one the sensor you mentioned already has a very high resolution and for the other Arduino is doing the stuff in the loop perhaps 100'000 times per second, so if you turn your picture-monitor completely around once per second, it still has 100 loop runs to detect the movement of one step. I'd start with that and if you run into problems you can later change the code to use interrupts and you'll probably never loose a step anymore (if you're not turning it faster than the sensor can react, it has the limit of 6000rpm).

Pulldown resistors (10k) are going to be needed on the inputs in Interrupt Example from arduino playground?

You don't need the pull-downs with your sensor because it already includes these parts.

Does I need also Low pass or Kalman filters for smoothing sets of data?

I don't think so. If the sensor is giving an exact signal (and I believe it will do), you won't get measurement errors and these filters are to flatten out these errors.

Final conclusion before buying the rotary sensor..What is better solution, example 1 or example 2 ?

example 1

 int val; 
 int encoder0PinA = 3;
 int encoder0PinB = 4;
 int encoder0Pos = 0;
 int encoder0PinALast = LOW;
 int n = LOW;

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

 void loop() { 
   n = digitalRead(encoder0PinA);
   if ((encoder0PinALast == LOW) && (n == HIGH)) {
     if (digitalRead(encoder0PinB) == LOW) {
       encoder0Pos--;
     } else {
       encoder0Pos++;
     }
     Serial.print (encoder0Pos);
     Serial.print ("/");
   } 

   encoder0Pos = encoder0Pos % 1024;
   encoder0PinALast = n;
 }

example 2

#define encoder0PinA  2
#define encoder0PinB  4

volatile unsigned int encoder0Pos = 0;

void setup() { 

  pinMode(encoder0PinA, INPUT); 
  digitalWrite(encoder0PinA, HIGH);       // turn on pullup resistor
  pinMode(encoder0PinB, INPUT); 
  digitalWrite(encoder0PinB, HIGH);       // turn on pullup resistor

  attachInterrupt(0, doEncoder, CHANGE);  // encoder pin on interrupt 0 - pin 2
  Serial.begin (9600);
  Serial.println("start");                // a personal quirk

} 

void loop(){
// do some stuff here - the joy of interrupts is that they take care of themselves
}

void doEncoder() {
  /* If pinA and pinB are both high or both low, it is spinning
   * forward. If they're different, it's going backward.
   */
  if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)) {
    encoder0Pos++;
  } else {
    encoder0Pos--;
  }

  encoder0Pos = encoder0Pos % 1024;
  Serial.println (encoder0Pos, DEC);

}

"Better" depends on the rest of the sketch, but in most situations the second will be the more reliable one. Please note that the two sketches don't produce the same output, though. The second one will generate 2048 positons for one turn (you check the rising and falling edge) and therefore will have values for half a circle only.

  Serial.println (encoder0Pos, DEC);

That is a no-go. Putting something on the serial interface inside an interrupt handler is a very bad idea.

What I have to do to get values for full circle?

Change that line

  encoder0Pos = encoder0Pos % 1024;

to

  encoder0Pos = encoder0Pos % 2048;

and keep in mind that encoder0Pos now has 2048 steps for one round. The conversion factor to degrees is half the one I calculated above, just to give you one example.

I Found something that can off-load the direction detection.

http://profmason.com/wp-content/uploads/2009/01/7474encoder.jpg

-bino-

Believe me, the direction detection does not use much CPU power. It's definitely not worth additional hardware.

Hi folks - can anyone advise on the best approach (code would be great) to measuring the speed or distance a rotary encoder has been rotated (mean change) from when it is started turning to when it is no longer turning anymore. Much appreciated! Im using the 1024 from Sparkfun Rotary Encoder - 1024 P/R (Quadrature) - COM-11102 - SparkFun Electronics?

Define your terms! Distance is not possible because the rotary encoder just measures rotation and not a distance. You just get a distance if there is some kind of wheel attached to it, then you need the diameter of that wheel to calculate the distance.

What speed do you want? The average? The max?

from when it is started turning to when it is no longer turning anymore.

What is the time frame you're willing to accept that the encoder isn't rotated anymore? The rotary encoder just puts out pulses when there was a rotation of about 1/3°, so at about 1 RPM you don't get a pulse for over 60ms. Is that no rotation?

The best approach is to count the pulses for some amount of time. The size of that amount is depending largely on the answers to my questions above.

BTW: you should start your own thread.