Yahoo Groups archive

AVR-Chat

Index last updated: 2026-04-28 22:41 UTC

Thread

Rotary encoder

Rotary encoder

2009-12-09 by Jeff Blaine AC0C

I have seen a lot of code on handling the rotary encoder.  But it seems there are a thousand approaches spreading over the years on the web.  

Given the popularity of this as an input device now, I hoped the board had a c-code snip that covered handling the rotary encoder in an IRQ context.

Many thanks.

73/jeff/ac0c


[Non-text portions of this message have been removed]

Re: Rotary encoder

2009-12-09 by Donald H

--- In AVR-Chat@yahoogroups.com, "Jeff Blaine AC0C" <keepwalking188@...> wrote:
>
> I have seen a lot of code on handling the rotary encoder.  But it seems there are a thousand approaches spreading over the years on the web.  
> 
> Given the popularity of this as an input device now, I hoped the board had a c-code snip that covered handling the rotary encoder in an IRQ context.

"The Board", which board ?

Have you tried any of the "thousand approaches" you have seen ?

If so, You should be done by now.

don

Re: [AVR-Chat] Re: Rotary encoder

2009-12-09 by David Kelly

On Wed, Dec 09, 2009 at 01:57:36PM -0000, Donald H wrote:
> 
> --- In AVR-Chat@yahoogroups.com, "Jeff Blaine AC0C" <keepwalking188@...> wrote:
> >
> > I have seen a lot of code on handling the rotary encoder.  But it
> > seems there are a thousand approaches spreading over the years on
> > the web.  
> > 
> > Given the popularity of this as an input device now, I hoped the
> > board had a c-code snip that covered handling the rotary encoder in
> > an IRQ context.
> 
> "The Board", which board ?
> 
> Have you tried any of the "thousand approaches" you have seen ?
> 
> If so, You should be done by now.

Ditto.

There are 1001 different expectations for use of an optical encoder,
that is why there are 1000 different implementations.

As Don said, if you know what you want it to do and you code for it,
you'd be done by now.

Generally there are 3 outputs from the encoder, A, B, and Index. Could
interrupt only on A. Ideally one would IRQ on any edge but not all AVR
IRQ inputs can do that so start with one edge or the other. If A rises
and B is also high decrement your position counter. If B is low then
increment your counter. Then reconfigure the IRQ for falling edge. When
A falls if B is high then increment the counter, if B low then
decrement. And reconfigure for rising edge.

Don't want to spoil your fun but there are ways to implement the above
with math rather than if-then-else.

You could use the index to reset (or modulo wrap) your counter but you
have to be careful as the index has a width and you always want to reset
on the same edge. For example if incrementing always reset on the rising
edge, if decrementing always reset on the falling edge.

Index doesn't need an interrupt input of its own, you can easily poll it
from the other encoder interrupt same as suggested above for B.

-- 
David Kelly N4HHE, dkelly@HiWAAY.net
========================================================================
Whom computers would destroy, they must first drive mad.

RE: [AVR-Chat] Rotary encoder

2009-12-09 by Steve Hodge

I agree with the other comments.   Here's an outline my son sent to me a
couple of years ago.   Maybe it will help you write your own code.   I was
able to very easily just on what he says below.   We were using an Atmel
644P at the time.   Steve

--------------------------------------------

Hi,

 

Rudder encoder is two data wires plus 5V power and ground. We'll need at
least one other wire either for an index on the encoder or some other
absolute positioning signal.

 

Encoders only change 1 of the two bits at a time - they count in "gray code"
or "in quadrature" rather than normal binary.

 

So iterating through steps in one direction, the bits will go through this
sequence:

 

00 01 11 10  00 01 11 00  ...

 

Contrast this with normal binary counting which would be:

 

00 01 10 11  00 01 10 11 ...

 

So what I did was make a lookup table of previous state + current state. The
result is either:

 

-1 (to the left)

0 (same)

+1 (to the right)

2 (invalid: the encoder jumped two steps which should never happen)

 

We are working with 4 bits so the table has 16 possible combinations which
represent the following state changes:

 

00<-00  00<-01  00<-10  00<-11

01<-00  01<-01  01<-10  01<-11

10<-00  10<-01  10<-10  10<-11

11<-00  11<-01  11<-10  11<-11

 

The values of the table will be:

 

  0  -1  +1    2

+1   0    2   -1

 -1   2    0  +1

  2 +1   -1    0

 

Say register R0 contains last reading in bits 2 and 3. The algorithm looks
like this:

 

Shift R0 two bits to the right so that the last reading moves into bits 0
and 1.

Read current reading into bits 2 and 3

Do the lookup of the memory at the table start address + R0 If result is 2,
signal an error.

Else add result (-1, 0, or +1) to position counter.

 

Does that make sense?

 

Matt
Show quoted textHide quoted text
From: AVR-Chat@yahoogroups.com [mailto:AVR-Chat@yahoogroups.com] On Behalf
Of Jeff Blaine AC0C
Sent: Wednesday, December 09, 2009 1:16 AM
To: AVR-Chat@yahoogroups.com
Subject: [AVR-Chat] Rotary encoder

 

  

I have seen a lot of code on handling the rotary encoder. But it seems there
are a thousand approaches spreading over the years on the web. 

Given the popularity of this as an input device now, I hoped the board had a
c-code snip that covered handling the rotary encoder in an IRQ context.

Many thanks.

73/jeff/ac0c

[Non-text portions of this message have been removed]





__________ Information from ESET Smart Security, version of virus signature
database 4672 (20091209) __________

The message was checked by ESET Smart Security.

http://www.eset.com



[Non-text portions of this message have been removed]

Re: [AVR-Chat] Rotary encoder

2009-12-09 by Jeff Blaine AC0C

Gentlemen,

Sorry for the confusion on the initial question.  I do understand the various basic aspects of the encoder function and the trade off of IRQ vs poll, etc.

What I am really wanting to do is to build a generic set of polished functions so that the code is clean and easy to reuse in the future as a generic library function set.  And the code covers all the typical variations one is likely to encounter.

As several have suggested, getting a set of code that works for a single application is not hard.  My rookie hack at making the encoder function will be fine for the project in front of me.  

And I believe someone may have a more robust implementation - that would cover a wider range of eventual complications and have considered things that I may not have initially.  

By eventual complications, for example, would be the ability to cover the various types of encoders configurations on the market or a debounce strategy that is robust enough to work with many encoders even if some tend to wiggle onward for what seems an eternity - things like that.

My objective for this question to the Yahoo chat group ("the board") was simply to find out if there may exist already the work done in a vetted and optimized fashion already by seasoned vets of the AVR world.  

Hope that makes sense.

Jeff
Show quoted textHide quoted text
From: Steve Hodge 
Sent: Wednesday, December 09, 2009 9:52 AM
To: AVR-Chat@yahoogroups.com 
Subject: RE: [AVR-Chat] Rotary encoder


  
I agree with the other comments. Here's an outline my son sent to me a
couple of years ago. Maybe it will help you write your own code. I was
able to very easily just on what he says below. We were using an Atmel
644P at the time. Steve

--------------------------------------------

Hi,

Rudder encoder is two data wires plus 5V power and ground. We'll need at
least one other wire either for an index on the encoder or some other
absolute positioning signal.

Encoders only change 1 of the two bits at a time - they count in "gray code"
or "in quadrature" rather than normal binary.

So iterating through steps in one direction, the bits will go through this
sequence:

00 01 11 10 00 01 11 00 ...

Contrast this with normal binary counting which would be:

00 01 10 11 00 01 10 11 ...

So what I did was make a lookup table of previous state + current state. The
result is either:

-1 (to the left)

0 (same)

+1 (to the right)

2 (invalid: the encoder jumped two steps which should never happen)

We are working with 4 bits so the table has 16 possible combinations which
represent the following state changes:

00<-00 00<-01 00<-10 00<-11

01<-00 01<-01 01<-10 01<-11

10<-00 10<-01 10<-10 10<-11

11<-00 11<-01 11<-10 11<-11

The values of the table will be:

0 -1 +1 2

+1 0 2 -1

-1 2 0 +1

2 +1 -1 0

Say register R0 contains last reading in bits 2 and 3. The algorithm looks
like this:

Shift R0 two bits to the right so that the last reading moves into bits 0
and 1.

Read current reading into bits 2 and 3

Do the lookup of the memory at the table start address + R0 If result is 2,
signal an error.

Else add result (-1, 0, or +1) to position counter.

Does that make sense?

Matt

From: AVR-Chat@yahoogroups.com [mailto:AVR-Chat@yahoogroups.com] On Behalf
Of Jeff Blaine AC0C
Sent: Wednesday, December 09, 2009 1:16 AM
To: AVR-Chat@yahoogroups.com
Subject: [AVR-Chat] Rotary encoder

I have seen a lot of code on handling the rotary encoder. But it seems there
are a thousand approaches spreading over the years on the web. 

Given the popularity of this as an input device now, I hoped the board had a
c-code snip that covered handling the rotary encoder in an IRQ context.

Many thanks.

73/jeff/ac0c

[Non-text portions of this message have been removed]

__________ Information from ESET Smart Security, version of virus signature
database 4672 (20091209) __________

The message was checked by ESET Smart Security.

http://www.eset.com

[Non-text portions of this message have been removed]





[Non-text portions of this message have been removed]

Re: [AVR-Chat] Rotary encoder

2009-12-09 by Dave Hylands

Hi Jeff,

On Wed, Dec 9, 2009 at 9:17 AM, Jeff Blaine AC0C
<keepwalking188@yahoo.com> wrote:
> Gentlemen,
>
> Sorry for the confusion on the initial question.  I do understand the various basic aspects of the encoder function and the trade off of IRQ vs poll, etc.
>
> What I am really wanting to do is to build a generic set of polished functions so that the code is clean and easy to reuse in the future as a generic library function set.  And the code covers all the typical variations one is likely to encounter.
>
> As several have suggested, getting a set of code that works for a single application is not hard.  My rookie hack at making the encoder function will be fine for the project in front of me.
>
> And I believe someone may have a more robust implementation - that would cover a wider range of eventual complications and have considered things that I may not have initially.
>
> By eventual complications, for example, would be the ability to cover the various types of encoders configurations on the market or a debounce strategy that is robust enough to work with many encoders even if some tend to wiggle onward for what seems an eternity - things like that.

My solution is here (QD.h and QD.c)
<http://websvn.hylands.org/filedetails.php?repname=Projects&path=%2Fcommon%2Favr%2FQD.h&rev=0&sc=0>
<http://websvn.hylands.org/filedetails.php?repname=Projects&path=%2Fcommon%2Favr%2FQD.c&rev=0&sc=0>

It doesn't do any debouncing, and doesn't deal with index pulses.

It does use lookup tables, and you can swap out the lookup table to
count A & B, just A, or just B.

The compiler will optimize out the unused side of the if statement in
the QD_CountInternal and QD_SetCountInternal function (since it uses a
constant expression).

Personally, I prefer to use a polling approach, rather than an ISR
based approach. The polling approach is self-correcting for noise. The
polling approach also represents what I call "constant load" in terms
of CPU cycles, which is generally better from a real-time perspective
(more deterministic - not necessarily better performance).

-- 
Dave Hylands
Shuswap, BC, Canada
http://www.DaveHylands.com/

Re: [AVR-Chat] Rotary encoder

2009-12-09 by Jeff Blaine AC0C

Thank you Dave.  

I really appreciate the advice.  

73/jeff/ac0c
Show quoted textHide quoted text
From: Dave Hylands 
Sent: Wednesday, December 09, 2009 1:37 PM
To: AVR-Chat@yahoogroups.com 
Subject: Re: [AVR-Chat] Rotary encoder


  
Hi Jeff,

On Wed, Dec 9, 2009 at 9:17 AM, Jeff Blaine AC0C
<keepwalking188@yahoo.com> wrote:
> Gentlemen,
>
> Sorry for the confusion on the initial question.  I do understand the various basic aspects of the encoder function and the trade off of IRQ vs poll, etc.
>
> What I am really wanting to do is to build a generic set of polished functions so that the code is clean and easy to reuse in the future as a generic library function set.  And the code covers all the typical variations one is likely to encounter.
>
> As several have suggested, getting a set of code that works for a single application is not hard.  My rookie hack at making the encoder function will be fine for the project in front of me.
>
> And I believe someone may have a more robust implementation - that would cover a wider range of eventual complications and have considered things that I may not have initially.
>
> By eventual complications, for example, would be the ability to cover the various types of encoders configurations on the market or a debounce strategy that is robust enough to work with many encoders even if some tend to wiggle onward for what seems an eternity - things like that.

My solution is here (QD.h and QD.c)
<http://websvn.hylands.org/filedetails.php?repname=Projects&path=%2Fcommon%2Favr%2FQD.h&rev=0&sc=0>
<http://websvn.hylands.org/filedetails.php?repname=Projects&path=%2Fcommon%2Favr%2FQD.c&rev=0&sc=0>

It doesn't do any debouncing, and doesn't deal with index pulses.

It does use lookup tables, and you can swap out the lookup table to
count A & B, just A, or just B.

The compiler will optimize out the unused side of the if statement in
the QD_CountInternal and QD_SetCountInternal function (since it uses a
constant expression).

Personally, I prefer to use a polling approach, rather than an ISR
based approach. The polling approach is self-correcting for noise. The
polling approach also represents what I call "constant load" in terms
of CPU cycles, which is generally better from a real-time perspective
(more deterministic - not necessarily better performance).

-- 
Dave Hylands
Shuswap, BC, Canada
http://www.DaveHylands.com/




[Non-text portions of this message have been removed]

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.