Pages: [1] 2   Go Down
Author Topic: Rotary Encoder Help  (Read 3826 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

https://www.sparkfun.com/products/11102

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!

Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 112
Posts: 5298
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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).

Quote
Mechanical absolute encoder or incremental encoder?

Incremental encoder.

Quote
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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

Code:
/* 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)) ??
Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 112
Posts: 5298
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
What to do with the BLUE wire ?

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

Quote
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?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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..
Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 112
Posts: 5298
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 112
Posts: 5298
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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.

Quote
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.

Quote
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:

Code:
encoderPos = encoderPos % 1024;

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

Quote
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).

Quote
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.

Quote
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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

example 1

Code:
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

Code:
#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);

}

« Last Edit: September 25, 2012, 06:26:12 am by potter » Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 112
Posts: 5298
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

"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.

Code:
  Serial.println (encoder0Pos, DEC);

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

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What I have to do to get values for full circle?
« Last Edit: September 25, 2012, 09:54:53 am by potter » Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 112
Posts: 5298
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Change that line

Code:
  encoder0Pos = encoder0Pos % 1024;

to

Code:
  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.
Logged

Indonesia
Offline Offline
Jr. Member
**
Karma: 0
Posts: 70
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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

-bino-
Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 112
Posts: 5298
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 https://www.sparkfun.com/products/11102?

Logged

Pages: [1] 2   Go Up
Jump to: