Author Topic: Rotary encoder question  (Read 8533 times)

0 Members and 1 Guest are viewing this topic.

Offline shebu18Topic starter

  • Frequent Contributor
  • **
  • Posts: 309
  • Country: ro
Rotary encoder question
« on: June 30, 2012, 08:29:18 pm »
Hello all,


I have bought some rotary encoders from TME, ED16112O. They do not use the normal grey code. If i rotate them CW i get initial state 00 then 11, 10, then 00 again. CCW it is the exact opposite. I connect the middle pin to GND and the other 2 to 5V.
I have tried it with arduino, got some results using interrupts but i had some misses of rotations.


Can you give me some advice on the code? Thank you.


Code: [Select]
int pina=2;
int pinb=3;
volatile int x=0;
volatile int trigger=0;


void setup(){
  pinMode(pina, INPUT);
  pinMode(pinb, INPUT);
  attachInterrupt(0, count, RISING);
  Serial.begin(9600);
}
void loop(){

  Serial.println(trigger);
}

void count(){
  if(digitalRead(pinb)==HIGH){
    x=2; 
  };
  if(digitalRead(pinb)==digitalRead(pina)){
    trigger--;
  }
  else{
    trigger++;
  }


}
 

Offline free_electron

  • Super Contributor
  • ***
  • Posts: 8550
  • Country: us
    • SiliconValleyGarage
Re: Rotary encoder question
« Reply #1 on: June 30, 2012, 09:09:01 pm »
nah. its standard gray code... the common is not the center pin but the right pin for this part.
Professional Electron Wrangler.
Any comments, or points of view expressed, are my own and not endorsed , induced or compensated by my employer(s).
 

Offline shebu18Topic starter

  • Frequent Contributor
  • **
  • Posts: 309
  • Country: ro
Re: Rotary encoder question
« Reply #2 on: July 01, 2012, 07:19:15 am »
Thank you for your help. Now i need to find a good code for the encoder.
 

Offline shebu18Topic starter

  • Frequent Contributor
  • **
  • Posts: 309
  • Country: ro
Re: Rotary encoder question
« Reply #3 on: July 01, 2012, 08:17:39 am »
I changed the pinout but now i fase the problem of not enough interrupt pins on the arduino duemilanove. I have 2 but need 4(for 2 encoders) How can i solve this problem. How did Dave solve this in his code?
 

Offline Psi

  • Super Contributor
  • ***
  • Posts: 10344
  • Country: nz
Re: Rotary encoder question
« Reply #4 on: July 01, 2012, 08:37:48 am »
I don't know much about Arduinos , but modern AVRs have a PCINTs for pretty much every pin.  (Pin Change interrupt).

Does the Arduino have this?

(Edit: The Arduino Uno looks to use an ATmega16U2 which does have PCINTs)
« Last Edit: July 01, 2012, 08:40:37 am by Psi »
Greek letter 'Psi' (not Pounds per Square Inch)
 

Offline Bored@Work

  • Super Contributor
  • ***
  • Posts: 3932
  • Country: 00
Re: Rotary encoder question
« Reply #5 on: July 01, 2012, 08:44:40 am »
Should I mention it? Ah well, it will anyhow be ignored, so I keep it short. One does not connect slow turning (aka hand operated) mechanical encoders via interrupts.
I delete PMs unread. If you have something to say, say it in public.
For all else: Profile->[Modify Profile]Buddies/Ignore List->Edit Ignore List
 

Offline shebu18Topic starter

  • Frequent Contributor
  • **
  • Posts: 309
  • Country: ro
Re: Rotary encoder question
« Reply #6 on: July 01, 2012, 09:03:43 am »
I don't know much about Arduinos , but modern AVRs have a PCINTs for pretty much every pin.  (Pin Change interrupt).

Does the Arduino have this?

(Edit: The Arduino Uno looks to use an ATmega16U2 which does have PCINTs)


Here http://arduino.cc/en/uploads/Main/Arduino_Uno_Rev3-schematic.pdf is the schematic of the arduino uno or duemilanove, they use the smae atmega328 chip. It has only INT0 and INT1(pin 2 and 3).In the 328 datasheet i have seen that there are more pins with int functions, but the arduino does not use them. This is the problem.
 

Offline shebu18Topic starter

  • Frequent Contributor
  • **
  • Posts: 309
  • Country: ro
Re: Rotary encoder question
« Reply #7 on: July 01, 2012, 09:05:15 am »
Should I mention it? Ah well, it will anyhow be ignored, so I keep it short. One does not connect slow turning (aka hand operated) mechanical encoders via interrupts.
THen how should i connect them? Teach me.
 

Offline Psi

  • Super Contributor
  • ***
  • Posts: 10344
  • Country: nz
Re: Rotary encoder question
« Reply #8 on: July 01, 2012, 09:10:53 am »
Here http://arduino.cc/en/uploads/Main/Arduino_Uno_Rev3-schematic.pdf is the schematic of the arduino uno or duemilanove, they use the smae atmega328 chip. It has only INT0 and INT1(pin 2 and 3).In the 328 datasheet i have seen that there are more pins with int functions, but the arduino does not use them. This is the problem.
That will teach me for skim reading.
It has an Atmega16U2 but it's for the USB emulation not the actual processor.


Should I mention it? Ah well, it will anyhow be ignored, so I keep it short. One does not connect slow turning (aka hand operated) mechanical encoders via interrupts.
THen how should i connect them? Teach me.

You can sample the pin yourself, say 100 times a second (10ms) on any input pin.

Use the hardware timer overflow interrupt to set flags when a specific time expires.
Then, in the main code loop area, check the flag,
-  If it's "set" do the logic to process the new encoder position and reset the flag.
-  If it's not set, do nothing. Eventually it will be set.

I wrote this example code on the wiki a while ago, but it's for an AVR not an Ardiuno. So maybe a little different.
http://www.eevblog.com/wiki/index.php?title=Embedded_Programming_Tips_and_Tricks_for_Beginners
Scroll down to "Repeating Code Using Timer Overflow Interrupts"
« Last Edit: July 01, 2012, 09:18:12 am by Psi »
Greek letter 'Psi' (not Pounds per Square Inch)
 

Offline johnnyfp

  • Frequent Contributor
  • **
  • Posts: 261
  • Country: nz
Re: Rotary encoder question
« Reply #9 on: July 01, 2012, 10:09:54 am »
 

Offline shebu18Topic starter

  • Frequent Contributor
  • **
  • Posts: 309
  • Country: ro
Re: Rotary encoder question
« Reply #10 on: July 01, 2012, 10:19:29 am »
I do not have enough C knowledge to understand that code(i am learning it alone at home). I am trying to use the method Psi mentioned. I use timer1 to make a interrupt and read the pin states every 10ms. Now i need to manage the code for knowing in witch  direction i am rotating the encoder. I am curios how Dave has done this.
Thank you for your help.
 

Offline Psi

  • Super Contributor
  • ***
  • Posts: 10344
  • Country: nz
Re: Rotary encoder question
« Reply #11 on: July 01, 2012, 10:39:15 am »
This may help too  http://arduino.cc/playground/Main/RotaryEncoders

Basically you pick one of the encoder wires and an edge type (rising or falling), doesn't matter which.

Then, when that edge type occurs on that encoder wire you look at the other wire and its state will tell you if the encoder is rotating left or right.

To tell if an edge is rising or falling you have to store the previous state in a variable so you can compare it to the current state.
« Last Edit: July 01, 2012, 10:42:11 am by Psi »
Greek letter 'Psi' (not Pounds per Square Inch)
 

Offline shebu18Topic starter

  • Frequent Contributor
  • **
  • Posts: 309
  • Country: ro
Re: Rotary encoder question
« Reply #12 on: July 01, 2012, 11:24:22 am »
I used this code:
Code: [Select]
int pina=2;
int pinb=1;
int value;
int oldvalue;


void setup(){
  pinMode(pina, INPUT);
  //digitalWrite(pina, HIGH);
  attachInterrupt(0, scan, RISING);
  Serial.begin(9600);
}

void scan(){
  value=digitalRead(pinb);
  if(value != oldvalue){

    Serial.println("right");
  }
  if(value==oldvalue){
    Serial.println("left");
  }
  value=oldvalue;
}

void loop(){

}
and i got this:
If i turn only right i get sometimes right sometimes left. If i turn left i get the things i get on right turning plus some errors. why do i get those errors and why do i not get only right when i turn right and only left when i turn left?
Code: [Select]
<LF>left [len=5]
<LF>right [len=6]
<LF>left [len=5]
<LF>right [len=6]
<LF>left [len=5]
<LF>right [len=6]
<LF>right [len=6]
<LF>right [len=6]
<LF>right [len=6]
<LF>left [len=5]
<LF>right [len=6]
<LF>right [len=6]
<LF>right [len=6]
<LF>left [len=5]
<LF>right [len=6]
<LF>left [len=5]
<LF>left [len=5]
<LF>right [len=6]
<LF>right [len=6]
<LF>left [len=5]
<LF>ht [len=3]
<LF>left [len=5]
<LF>right [len=6]
<LF>left [len=5]
<LF>right [len=6]
<LF>left [len=5]
<LF>right [len=6]
<LF>left [len=5]
<LF>ight [len=5]
<LF>left [len=5]
<LF>right [len=6]
<LF>left [len=5]
<LF>right [len=6]
<LF>left [len=5]
<LF>right [len=6]
<LF> [len=1]
<LF>left [len=5]
<LF>right [len=6]
<LF>left [len=5]
<LF>t [len=2]
<LF>left [len=5]
<LF>ight [len=5]
<LF>left [len=5]
<LF><LF>right [len=7]
<LF>left [len=5]
<LF>right [len=6]
<LF>left [len=5]
<LF>right [len=6]
<LF>ght [len=4]
<LF>left [len=5]
<LF>ight [len=5]
<LF>left [len=5]
<LF>right [len=6]
<LF>right [len=6]
<LF>left [len=5]
<LF>ht [len=3]
<LF>left [len=5]
<LF>t [len=2]
<LF>left [len=5]
<LF>right [len=6]
<LF>left [len=5]
<LF>t [len=2]
<LF>left [len=5]
<LF>left [len=5]
<LF>left [len=5]
<LF>t [len=2]
<LF>left [len=5]
<LF>right [len=6]
<LF>left [len=5]

 

Offline shebu18Topic starter

  • Frequent Contributor
  • **
  • Posts: 309
  • Country: ro
Re: Rotary encoder question
« Reply #13 on: July 01, 2012, 12:09:21 pm »
I can recommend this http://www.buxtronix.net/2011/10/rotary-encoders-done-properly.html for a library and it is nice to add it to the code. It works on pins without or with interrupt and it does not take much space up.


LE No debounce circuit is required but no for loop runs. It simply does not start running
« Last Edit: July 01, 2012, 12:32:07 pm by shebu18 »
 

Offline Psi

  • Super Contributor
  • ***
  • Posts: 10344
  • Country: nz
Re: Rotary encoder question
« Reply #14 on: July 01, 2012, 12:29:23 pm »
You maybe getting some switch bounce. (Where the contacts bounce back and forward before they settle).
Google "rotary encoder hardware debounce"

Also you have a bug in the code.  You want to set oldvalue = value;  but you have it the other way around.
The way you have it oldvalue never gets set to anything.

EDIT: Actually, looking at your code, you're using an external hardware interrupt for one of the connections.
The hardware interrupt pins do rise/fall detection themselves, so you don't need any of that oldvalue stuff at all.
(It's only needed when you're trying to work out rise/fall yourself in software)

Try this scan function instead.

void scan(){
  value=digitalRead(pinb);
  if(value == HIGH){
    Serial.println("right");
  }
  if(value == LOW){
    Serial.println("left");
  }
}

(i may have left/right reversed)
« Last Edit: July 01, 2012, 12:51:46 pm by Psi »
Greek letter 'Psi' (not Pounds per Square Inch)
 

Offline shebu18Topic starter

  • Frequent Contributor
  • **
  • Posts: 309
  • Country: ro
Re: Rotary encoder question
« Reply #15 on: July 01, 2012, 05:25:17 pm »
it work kind of. I need to debounce it in hardware. I can use the code i found an i do not need the hardware debounce. I am only curios if the loop works if no for loop works. Theoretically i do no need any for or while loop in my psu code.
 

Offline Psi

  • Super Contributor
  • ***
  • Posts: 10344
  • Country: nz
Re: Rotary encoder question
« Reply #16 on: July 02, 2012, 03:01:59 am »
You shouldn't do any delay loops, use the hardware timer to set variables like flags instead.
Greek letter 'Psi' (not Pounds per Square Inch)
 

Offline shebu18Topic starter

  • Frequent Contributor
  • **
  • Posts: 309
  • Country: ro
Re: Rotary encoder question
« Reply #17 on: July 02, 2012, 04:36:48 am »
Could you give me a example? Thank you.
 

Offline shebu18Topic starter

  • Frequent Contributor
  • **
  • Posts: 309
  • Country: ro
Re: Rotary encoder question
« Reply #18 on: October 19, 2012, 04:59:57 pm »
Dave, how did you do the rotary encoder on your PSU?


I want an increase or decrease of 1 on an click. Using a library found i get almost 4 steps decreased or incresed on one click. THe library is very precise, but not suited for my needs. I will try to write my one.
 

Offline andersm

  • Super Contributor
  • ***
  • Posts: 1198
  • Country: fi
Re: Rotary encoder question
« Reply #19 on: October 19, 2012, 06:19:58 pm »
Divide the library-provided position by 4? The quadrature encoder pins have four state transitions per "count", so by using each transition you can get 4 times the resolution. Obviously not so useful if you are using encoders with detents ("clicks"), but much better for eg. emulating a potentiometer.

Offline AndreasF

  • Frequent Contributor
  • **
  • Posts: 251
  • Country: gb
    • mind-dump.net
Re: Rotary encoder question
« Reply #20 on: October 19, 2012, 06:26:28 pm »
The last line of your scan() function is the wrong way around: you want to update the "oldvalue" variable (you had it reversed), therefore:

Code: [Select]
...
oldvalue = value;
}
...

That should do it.

Edit:  Oops, just saw that Psi already mentioned the oldvalue/value issue (and that it's actually not necessary), so please ignore me.   :-X
« Last Edit: October 19, 2012, 06:34:01 pm by AndreasF »
my random ramblings mind-dump.net
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf