AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
mojo-chan
PostPosted: Apr 04, 2008 - 04:03 AM
Wannabe


Joined: Jan 24, 2008
Posts: 65


I am working on a project that will ultimately be being built by other hobbyists, and it uses a rotary encoder with 2-bit gray code output.

I am having trouble reliably decoding the gray code. I think that the encoder has a lot of bounce. I really need to be able to support these cheap, crappy encoders though.

So far I have tried using rising/falling edge or pin change interrupt triggering, looped polling, timer based polling from 1khz up to 180khz, and various decoding methods such as checking B on fall of A, checking both A and B on every pin change. I also tried various methods of debouncing the inputs such as timers that are reset every time there is a change (thus requiring a certain amount of no-change time before inputs are read).

Nothing worked properly. The best I can do is count debounced pulses on A or B. No matter what I try, I can't determine which direction the shaft is rotating in.

I have spent hours searching the net, including these forums, but as far as I can see no-one has actually posted a working, robust and complete bit of code. Lots of theory, but nothing proven to work. Even the code people posted on these forums were just snippets, and I tried them all.

I'd really appreciate some help Crying or Very sad Does anyone actually have a working example of using a rotary encoder? C or asm, I don't care...
 
 View user's profile Send private message  
Reply with quote Back to top
dbc
PostPosted: Apr 04, 2008 - 05:08 AM
Resident


Joined: Jul 08, 2006
Posts: 504
Location: Sunnyvale, CA

If you are seeing a lot of bounce, I presume you are using a mechanical encoder? How fast is the encoder turning?

As far as encoders go, I have built a home-brew encoder with reflective optical sensors, and sampling on pin change interrupt worked OK. My code tolerated NOP transitions to current state and silently threw them out, so maybe there was bounce I wasn't seeing.

Anway, for mechanical switches, my favorite debouncer is to sample on 1 mSec or so interrupt and simply shift the sampled bit into a byte -- when I get 0x00 or 0xff it means I've seen 8 in a row the same, and I call it debounced. Have you tried debouncing each contact by itself, and then running the up/down counter off the debounced output? Which brings me back to the question of how fast you are turning the encoder -- maybe it is bouncing longer than it takes for you to get between sectors?

If you're feeling adventurous, the code below is how I would approach the problem.... warning: I haven't even tried to compile it.

Code:

// this runs on a suitable timer interrupt
bouncy0 =  (bouncy0 << 1) | (PINX & Q0BIT ? 1 : 0);
bouncy1 =  (bouncy1 << 1) | (PINX & Q1BIT ? 1 : 0);
if (bouncy0 == 0x00) enc &= 0x2;
if (bouncy0 == 0xff) enc |= 0x1;
if (bouncy1 == 0x00) enc &= 0x1;
if (bouncy1 == 0xff) enc |= 0x2;
switch (qstate)
{
case 0:
    switch (enc)   
    case 0:
        // ignore
        break;
    case 1:
        ++count;
        break;
    case 2:
        --count;
        break;
    case 3:
        // WTF?
        break;
    }
    break;
case 1:
   ...
}
qstate = enc;

 
 View user's profile Send private message  
Reply with quote Back to top
c_hirst
PostPosted: Apr 04, 2008 - 05:12 AM
Resident


Joined: Jun 21, 2002
Posts: 676
Location: Canberra, Australia

Because a gray code should only change one bit at a time, bounce will only be a problem it it lasts past the next bit change position. The effect will be dithering back and forward at the transition point. To get the true rotation direction, you need to consider more than two values
Code:
    ideal   A -> B -> C -> D forward
            A -> D -> C -> B reverse
    actual  A B A B A B C B C B C B C B C D C D C D  or similar forward
      use   A B         C                 D
            A D A D A D C D C D C D C B C B C B      or similar reverse
      use   A D         C             B


ie. use the last 3 positions keeping the "next different"
 
 View user's profile Send private message  
Reply with quote Back to top
dbc
PostPosted: Apr 04, 2008 - 05:12 AM
Resident


Joined: Jul 08, 2006
Posts: 504
Location: Sunnyvale, CA

[massive edit]
Deleting double post -- the first one errored off, but appears to have posted anyway.
 
 View user's profile Send private message  
Reply with quote Back to top
dbc
PostPosted: Apr 04, 2008 - 05:18 AM
Resident


Joined: Jul 08, 2006
Posts: 504
Location: Sunnyvale, CA

Quote:
To get the true rotation direction, you need to consider more than two values

Good point. True even with a perfectly bounceless encoder.
 
 View user's profile Send private message  
Reply with quote Back to top
dbc
PostPosted: Apr 04, 2008 - 05:30 AM
Resident


Joined: Jul 08, 2006
Posts: 504
Location: Sunnyvale, CA

Actually, that could be done with a simple direction state machine with three states: CCW, AMBIGUOUS, and CW, and one input for counting up or down.
 
 View user's profile Send private message  
Reply with quote Back to top
davef
PostPosted: Apr 04, 2008 - 06:38 AM
Resident


Joined: Sep 03, 2005
Posts: 684
Location: Christchurch, NZ

Search the forum as there were a number of related threads last year, I know as I was struggling with the same issue.

Good luck
 
 View user's profile Send private message  
Reply with quote Back to top
theusch
PostPosted: Apr 04, 2008 - 06:43 AM
10k+ Postman


Joined: Feb 19, 2001
Posts: 19075
Location: Wisconsin USA

Quote:

I think that the encoder has a lot of bounce. I really need to be able to support these cheap, crappy encoders though.

You "think"? You need to "support" the device, but there is no 'scope in your organization to actually look at the signals? And once you see the situation, you have no supply of Rs and Cs to clean it up?

Lee
 
 View user's profile Send private message  
Reply with quote Back to top
meslomp
PostPosted: Apr 04, 2008 - 08:16 AM
Posting Freak


Joined: May 02, 2007
Posts: 1034
Location: Nieuwegein, Netherlands

The R's should be there anyway(either internally in the AVR or externaly to either VCC or VDD), so he would only need C's in my opinion.

_________________
Best friends:
1) Datasheet (and application notes)
2) AVR freaks forum( specially the tutorials
3) Fellow freaks, Can answer to problems that could not be answered by 1 or 2
 
 View user's profile Send private message  
Reply with quote Back to top
bobgardner
PostPosted: Apr 04, 2008 - 01:56 PM
10k+ Postman


Joined: Sep 04, 2002
Posts: 13547
Location: Orlando Florida

Is the encoder turned by a machine or by a human? This gives some idea of the max counts per sec that have to be measured. To catch a 'snatch' of 90 degrees on the knob which would be 4 counts on a 16 detent encoder... if the snatch took 50ms, thats only 12.5ms per count... an eternity for a 16mhz processor.... in addition of some carefully chosen caps that will eat bounces faster than a ms or two, reading the encoder every 5ms should get past the bounce, but not miss the next count. This all sounds logical, but gremlims do defy logic I have found.

_________________
Imagecraft compiler user
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
mojo-chan
PostPosted: Apr 04, 2008 - 09:55 PM
Wannabe


Joined: Jan 24, 2008
Posts: 65


Okay, thanks for the replies.

I am using a mechanical rotary encoder, and turning it by hand. I don't turn it particularly fast (normal hifi volume control speed).

dbc: Your code looks interesting, I'm going to try and implement it. At the moment I have been debouncing just the input that I sense change on. I too was using a counter of unchanged states, and assumed that the other line we have settled by then too.

Man, I own a t-shirt that says "assumption is the mother of screw-up" Smile

c_hirst: I like your idea of considering more than one state to determine direction. I had been trying to do that but it was failing due to the amount of bounce. Based on your diagram, I might try a system of recording the order in which states are seen.

theusch: I don't have an "organisation", I'm just a hobbyist. I don't own a scope (might get one soon if I can find a good, relatively cheap PC scope that goes up to 20MHz) and I want the project to be buildable by other hobbyists, using easily available parts. Unfortunately crappy mechanical rotary encoders are common, where as nice optical ones are expensive and hard to get (at least here in the UK).

I don't know why you assume I don't have resistors and capacitors - of course I do. I am using the AVR's internal pull-up and currently don't have a cap.

I'll try and give these ideas a try today or tomorrow, thanks.
 
 View user's profile Send private message  
Reply with quote Back to top
jayjay1974
PostPosted: Apr 04, 2008 - 10:03 PM
Raving lunatic


Joined: Oct 30, 2002
Posts: 3922
Location: The Netherlands

I've interfaced a number of encoders, and with a series resistor and cap you get nice clean edges (albeit a tad slow but that's no problem). I found that usually one input will chatter rapidly when you move the knob around a detent in one particular direction slowly. This can't be solved by debouncing but needs to be solved in the detection logic.

_________________
Free e-books
Modern Mechanix: Yesterday's Tommorow Today
 
 View user's profile Send private message  
Reply with quote Back to top
bobgardner
PostPosted: Apr 05, 2008 - 12:40 AM
10k+ Postman


Joined: Sep 04, 2002
Posts: 13547
Location: Orlando Florida

Some encoders have the detent right in the middle between the edges of A and B, others have the detent right in the middle of A, which is right on an edge of B, which will dither up and down if you rock it back and forth in the detent. The fix is dont count those... just look for the rising edge on A or the falling edge on A, and inc or dec the count based on the state of B.

_________________
Imagecraft compiler user
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
RES
PostPosted: Apr 05, 2008 - 11:54 PM
Resident


Joined: Dec 31, 2005
Posts: 642


Some encoders (with detend positions) have for example cycles like this.

AB: 00 10 11 01 00 -> CW
AB: 00 01 11 10 00 -> CCW

For good reliability you can make 3 or 4 switch buffers (could be done with a single register -> 4 * AB = a byte -> ABABABAB.)
So first debounce AB -> when steady, then if another value than 00 apears in AB (change) will be 10 or 01 -> buffer value, then next round 11 must appear, then 01 or 10, and back to detend 00. So if you read a value of 45 (10 11 01 = 101101 INC a counter or set flag, if value = 30 (011110) DEC a counter or clear flag & clear value in buffers.
Wrong direction is impossible, a skip still possible.
Waterproof codes for mechanical encoders are not simple, use an optical encoder, much easier codes, but more expensive.

Cool

_________________
RES - http://www.attiny.com
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
mojo-chan
PostPosted: Apr 06, 2008 - 01:28 AM
Wannabe


Joined: Jan 24, 2008
Posts: 65


RES wrote:
So first debounce AB -> when steady, then if another value than 00 apears in AB (change) will be 10 or 01 -> buffer value


I did try that method, but it never seemed to work reliably. Often at normal turning speed B did not seem to settle enough to make an accurate reading.

I think I am going to get another rotary encoder.
 
 View user's profile Send private message  
Reply with quote Back to top
snarflemike
PostPosted: Apr 06, 2008 - 02:16 AM
Hangaround


Joined: Jan 06, 2008
Posts: 356


mojo-chan wrote:
I did try that method, but it never seemed to work reliably. Often at normal turning speed B did not seem to settle enough to make an accurate reading.

I think I am going to get another rotary encoder.


If we take "normal turning speed" to be e.g. 1 revolution per second, on a 20-position encoder that's 50ms per position, so your B signal should have had 50ms to settle down. If it's still bouncing around after all that time you may very well have a bad encoder. I looked up some cheap ($3) encoders and they specified 2ms maximum bounce time at 1 rps.
 
 View user's profile Send private message  
Reply with quote Back to top
mojo-chan
PostPosted: Apr 06, 2008 - 06:18 PM
Wannabe


Joined: Jan 24, 2008
Posts: 65


Okay, I have experimented some more, and so far all suggested solutions have failed Sad

I am going to see about hacking an optical encoder out of a mouse.
 
 View user's profile Send private message  
Reply with quote Back to top
microcarl
PostPosted: Apr 06, 2008 - 06:49 PM
Raving lunatic


Joined: May 30, 2004
Posts: 7801
Location: Cincinnati, Ohio

I have a variation of the following working in an interrupt driven servo motor control system.

I modified it, as applicable to a non-interrupt driven system.

See here http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=62118&start=20 for the current code.

_________________
Carl W. Livingston, KC5OTL
microcarl@roadrunner.com

It's a fundamental law of nature... All things gravitate toward total chaos!!!

The original Dragon Slayer !

Long live the AVR!!!


Last edited by microcarl on Apr 12, 2008 - 11:36 PM; edited 2 times in total
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
mojo-chan
PostPosted: Apr 07, 2008 - 05:47 PM
Wannabe


Joined: Jan 24, 2008
Posts: 65


I managed to get a scope on the encoder and it seems like it never ever stops bouncing when being rotated Sad

The output is so noisy, I was shocked. Even just touching the shaft causes bounce. I'm going to chuck it and get an optical encoder.

I'm looking at buying a scope too. I see for about £100 you can get USB ones that claim up to 40MHz bandwidth. I can't find much info on them though. Any good?
 
 View user's profile Send private message  
Reply with quote Back to top
jayjay1974
PostPosted: Apr 07, 2008 - 05:51 PM
Raving lunatic


Joined: Oct 30, 2002
Posts: 3922
Location: The Netherlands

There are much better (mechanical) encoders out there, no need to go optical. I have used Bourns, Alps en Piher encoders, they all work fine. You just got a very very bad one I guess.

_________________
Free e-books
Modern Mechanix: Yesterday's Tommorow Today
 
 View user's profile Send private message  
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits