Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Rotary encoder interfacing to a micro

5 views
Skip to first unread message

|D0T| macdougall@btinternet.com Colin MacDougall

unread,
Apr 18, 2004, 6:55:34 PM4/18/04
to
Hello,

I am trying to connect an ALPS two phase mechanical encoder to
a small micro ( AVR 90s2313 ). I can get it to work pretty much
how I want - at the moment it causes a row of eight LED's to
run back and forth. The problem I come across is that turning
the shaft to the next detent position sometimes causes the LED's
to double count. Looking at the output from the encoder on a scope
reveals a bit of noise on the outputs. I have set my micro to
interrupt on a falling edge of one of the phases and tried using
a 7 mS software timer but this does not totally cure the problem.
Does anyone have some tips for using these devices ? Is it usual to
hook the outputs straight on to a micro or should a Schmitt trigger
or similar be used first ? I have thought about using a 'best of three'
approach where the phase is sampled three times and a decision made
if all three results are the same.

TIA

Colin


nospam

unread,
Apr 18, 2004, 8:03:06 PM4/18/04
to
"Colin MacDougall" <colin |D0T| macdo...@btinternet.com> wrote:

>Hello,
>
>I am trying to connect an ALPS two phase mechanical encoder to
>a small micro ( AVR 90s2313 ). I can get it to work pretty much
>how I want - at the moment it causes a row of eight LED's to
>run back and forth. The problem I come across is that turning
>the shaft to the next detent position sometimes causes the LED's
>to double count.

If is not possible to track an incremental encoder while only checking its
state on one edge of one channel. You can not tell if the edge was
generated by the encoder advancing through a whole cycle or just reversing
slightly and advancing through the edge again.

For a low speed application a simple way of tracking is to sample the
channels in a regular timer interrupt. The current state of the channels
combined with their state on the previous sample gives 16 cases. Of these 2
* 4 indicate movement in either direction, 4 indicate no movement and the
remaining 4 should be impossible. This scheme is pretty simple to code.

Paul Carpenter

unread,
Apr 18, 2004, 10:04:38 PM4/18/04
to
On Sunday, in article
<xHDgc.9$6T...@news-binary.blueyonder.co.uk>
colin|D0T|macdo...@btinternet.com "Colin MacDougall"
wrote:

Both approaches sound good as you seem to be using a encoder that is a
switch that will have switch bounce so using the timer to do several
successive readings to check for several identical readings before
using it would be good. This of course depends on how much processing
time you have available.

I assume this an 8 bit o/p encoder, so if adding external chips you
might consider putting some form of debouncer chip to alleviate
your software overhead if that is important. A typical one to use
could be the Maxim MAX6818, which also has internal pull-up resistors.

--
Paul Carpenter | pa...@pcserv.demon.co.uk
<http://www.pcserv.demon.co.uk/> Main Site
<http://www.gnuh8.org.uk/> GNU H8 & mailing list info.
<http://www.badweb.org.uk/> For those web sites you hate.

Jack Klein

unread,
Apr 19, 2004, 12:13:08 AM4/19/04
to
On Sun, 18 Apr 2004 23:55:34 +0100, "Colin MacDougall" <colin |D0T|
macdo...@btinternet.com> wrote in comp.arch.embedded:

As others have already said, to get true quadrature decoding (speed
and direction) you need to look at least at both edges of one pulse.
A lot depends on the speed with which the encoder pulse train comes.

About 10 years ago I did a project for a special type of printer. The
pin feed paper was driven by an AC motor and tracked by an encoder,
approximately 4000 quadrature edges per second. A step motor had to
be controlled by a state machine to synchronize to the paper in
various complicated ways.

We did this with an 8051 running at 12 MHz. The quadrature inputs
were connected each connected to one input of an exclusive-or gate,
the other input to each exclusive-or gate was connected to a separate
port pin, and the outputs of the two gates were connected to the two
external interrupt lines of the chip.

When one phase changed state, it generated the corresponding
interrupt. The ISR read the input a few times to make sure it was
stable. Then, based on the direction of the change and the state of
the other phase, it generated an up or down count to the position
counter. Finally it toggled the output port pin driving the other
input to the exclusive-or gate to clear the interrupt input until that
phase changed state again.

Again as others have pointed out, if you need high speed encoder
tracking, there are dedicated chips. US Digital and Agilent (formerly
Hewlett Packard) are some sources.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html

Ben Bradley

unread,
Apr 19, 2004, 12:24:33 AM4/19/04
to
In comp.arch.embedded, "Colin MacDougall" <colin |D0T|
macdo...@btinternet.com> wrote:

>Hello,
>
>I am trying to connect an ALPS two phase mechanical encoder to
>a small micro ( AVR 90s2313 ). I can get it to work pretty much
>how I want - at the moment it causes a row of eight LED's to
>run back and forth. The problem I come across is that turning
>the shaft to the next detent position sometimes causes the LED's
>to double count. Looking at the output from the encoder on a scope
>reveals a bit of noise on the outputs. I have set my micro to
>interrupt on a falling edge of one of the phases and tried using
>a 7 mS software timer but this does not totally cure the problem.
>Does anyone have some tips for using these devices ? Is it usual to
>hook the outputs straight on to a micro or should a Schmitt trigger
>or similar be used first ?

If there's some the micro can't devote a few extra cycles to
debouncing, then you should perhaps add extra hardware (or look into
raising the clock speed!), but a good software-only debounce works
fine for me.

>I have thought about using a 'best of three'
>approach where the phase is sampled three times and a decision made
>if all three results are the same.

I do something similar. I've gotten a mechanical encoder to work
quite reliably, with switches directly into the microcontroller port
pins, with the chip's internal pullups enabled (no external resistors
or capacitors). I read the two lines inside a once-every-1-mS timer
interrupt, and read it each time for ten times through (giving an
'actual switch value' every 10mS). Since the switch goes to ground and
the internal pullup goes to VCC, the switch 'on' is read as a zero. I
initialize a buffer to all 1's and do an 'and' of each reading with
the buffer so that if a bit value is zero (switch on) during any of
those reads, I presume the switch is on (and all the other 1 readings
were due to a scratchy switch - if the switch contacts are nowhere
near each other, then ALL readings of it will be 1, correctly
indicating switch off). At the end of the tenth reading I pass this
off as The Encoder Value, then reinit the buffer and counter.
I had looked at the switch output with a scope, both turning slowly
(to see any noise, as well as the rise time of the pullups) and
quickly (to see how fast the quadrature signals might reasonably
change at maximum hand-turning speed), so this code is the result of
Deliberate Research into Cheap Mechanical Rotary Encoders (these are
made by Panasonic, digikey part# P10859-ND).
It's AVR 90S1200 assembly code, I wrote it on my own time, as
opposed to being paid to do it, so I have full rights to the code. If
someone asks nicely I coould put the whole thing online, I might even
add some [more!] documentation to it.

>TIA
>
>Colin

Spehro Pefhany

unread,
Apr 19, 2004, 12:59:57 AM4/19/04
to

Sample both inputs @~400Hz and debounce (store previous reading and
accepted reading) to get rid of the rated contact bounce (usually
something like 5msec). You can then determine up/down/ignore from the
transition of states. It's possible to get illegal states if the knob
is turned too fast, in which case you are best to just ignore. Note
also that one input may be guaranteed stable at the detent, wheras the
other may not.

Here's the encoders we have, which are probably similar to the ones
you have:

http://www.trexon.com/pdfs/trexon_encoder_revA.


Best regards,
Spehro Pefhany
--
"it's the network..." "The Journey is the reward"
sp...@interlog.com Info for manufacturers: http://www.trexon.com
Embedded software/hardware/analog Info for designers: http://www.speff.com

Mickey

unread,
Apr 19, 2004, 1:38:13 AM4/19/04
to
You should make a sampling rate that is fast enough for your encoder,
lets say 10ms or something like that, and when you detect that current
state is "0", and previous state was "1" then you have a negative edge.

Mickey

Robert Scott

unread,
Apr 19, 2004, 8:26:05 AM4/19/04
to
On Sun, 18 Apr 2004 23:55:34 +0100, "Colin MacDougall" <colin |D0T|
macdo...@btinternet.com> wrote:

>Hello,
>
>I am trying to connect an ALPS two phase mechanical encoder to

>a small micro ( AVR 90s2313 )....

A few months ago I posted about this schematic:

http://www.tunelab-world.com/decode.gif

It converts quadrature into up-counts and down-counts. If your micro
has two counters that each can count external edges, then the
quadrature position count can be calculated at any time by subtracting
the two counters. The only problem becomes how to read often enough
to handle overflow and how to read two counters on the fly while one
or both of them may be counting. I solved the second problem by
reading both counters twice and checking that the readings didn't
change. For fast enough quadrate, this may need to be refined.


-Robert Scott
Ypsilanti, Michigan
(Reply through this forum, not by direct e-mail to me, as automatic reply address is fake.)

Joe Legris

unread,
Apr 19, 2004, 9:02:53 AM4/19/04
to
That link appears to be dead.

Spehro Pefhany

unread,
Apr 19, 2004, 9:19:11 AM4/19/04
to
On Mon, 19 Apr 2004 09:02:53 -0400, the renowned Joe Legris
<jale...@xympatico.ca> wrote:

>That link appears to be dead.

Sorry, it should be:

http://www.trexon.com/pdfs/trexon_encoder_revA.pdf

CBarn24050

unread,
Apr 19, 2004, 2:09:58 PM4/19/04
to
> I have set my micro to
>interrupt on a falling edge of one of the phases

If you want to use interupts then you need to use both edges of one channel or
use the falling (or rising) edges of both channels. For low speed work polling
would work, for high speed you should consider a processor with an onboard
up/down counter.

Lewin A.R.W. Edwards

unread,
Apr 19, 2004, 8:35:21 PM4/19/04
to
> It converts quadrature into up-counts and down-counts. If your micro
> has two counters that each can count external edges, then the

IMHO the simple hardware counter is not a good solution unless you
have hardware debouncing of the switch inputs. BTW, you can do it more
simply with a counter that has a direction input - connect one quad
output to the counter's clock and the other to the direction input. IN
THEORY, if everything is debounced perfectly, the state of B at an
edge on A is high for one direction, or low for the other. In
practice, these switches - at least the hand-operated ones like the
Matsushita EVQ series - are horribly bouncy and have dead zones around
the detents.

If you want to do it with the minimum hardware, use two GPIOs and have
an ISR that maintains a history of state-changes on the GPIOs. A
falling edge on A followed by a falling edge on B with no intervening
rising edge on A is a count in (say) the + direction. A falling edge
on B followed by a falling edge on A with no intervening rising edge
on B is a count in the other direction. Any other sequence of
state-changes is ignored.

I used this method in a low-speed polled interrupt handler for a
thumbwheel (front panel) type encoder and it worked very well. I was
constrained by evil factors - no interruptible GPIOs and my ISR
couldn't run faster than approximately once every 50ms. But the end
result was very good <http://www.digi-frame.com/df560.html> (out of
production for a couple of years, so I'm absolved from any charge of
shilling :).

Robert Scott

unread,
Apr 20, 2004, 7:40:35 AM4/20/04
to
On 19 Apr 2004 17:35:21 -0700, la...@larwe.com (Lewin A.R.W. Edwards)
wrote:

>> It converts quadrature into up-counts and down-counts. If your micro
>> has two counters that each can count external edges, then the
>
>IMHO the simple hardware counter is not a good solution unless you
>have hardware debouncing of the switch inputs.

In my schematic, the synchronization shift register on the input
ensures that all "bounces" are either recognized as full pulses or not
recognized at all. If they are recognized as full pulses, they will
result in both an up-count and a down-count. In either case, the
difference between the two counters will always represent the correct
count. No other debouncing is necessary.

> BTW, you can do it more
>simply with a counter that has a direction input -

Perhaps. But I was designing toward the kind of counters built-in to
common micros. Those counters do not have direction inputs.

>If you want to do it with the minimum hardware, use two GPIOs and have
>an ISR that maintains a history of state-changes on the GPIOs. A
>falling edge on A followed by a falling edge on B with no intervening
>rising edge on A is a count in (say) the + direction. A falling edge
>on B followed by a falling edge on A with no intervening rising edge
>on B is a count in the other direction. Any other sequence of
>state-changes is ignored.

This can work fine for low encoders speeds. You just have to see what
the worst-case time is between ISRs and make sure that time is less
than the shortest possible time between a transition on the A-phase
and a transition on the B-phase. The software solution may work fine
for manually-operated dials. But all the applications I see are in
industrial machine control where the encoder is on some shaft turned
by a motor. 500 nsec. pulse times are not uncommon.

Ben Bradley

unread,
Apr 20, 2004, 12:40:47 PM4/20/04
to
In comp.arch.embedded, no-...@dont-mail-me.com (Robert Scott) wrote:

>On 19 Apr 2004 17:35:21 -0700, la...@larwe.com (Lewin A.R.W. Edwards)
>wrote:
>
>>> It converts quadrature into up-counts and down-counts. If your micro
>>> has two counters that each can count external edges, then the
>>
>>IMHO the simple hardware counter is not a good solution unless you
>>have hardware debouncing of the switch inputs.
>
>In my schematic, the synchronization shift register on the input
>ensures that all "bounces" are either recognized as full pulses or not
>recognized at all. If they are recognized as full pulses, they will
>result in both an up-count and a down-count. In either case, the
>difference between the two counters will always represent the correct
>count. No other debouncing is necessary.
>
>> BTW, you can do it more
>>simply with a counter that has a direction input -
>
>Perhaps. But I was designing toward the kind of counters built-in to
>common micros. Those counters do not have direction inputs.
>
>>If you want to do it with the minimum hardware, use two GPIOs and have
>>an ISR that maintains a history of state-changes on the GPIOs. A
>>falling edge on A followed by a falling edge on B with no intervening
>>rising edge on A is a count in (say) the + direction. A falling edge
>>on B followed by a falling edge on A with no intervening rising edge
>>on B is a count in the other direction. Any other sequence of
>>state-changes is ignored.

A problem with this scheme is the encoder can be 'teased' by moving
it halfway off of a detent then back, causing the falling-A-falling-B
sequence, causing a count increase, without the corresponging
falling-B-falling-A sequence to give a corresponding count decrease.
It may not be that big a deal to some people or in some apps, but I
consider it a 'bug' in the interface.
I decode the whole sequence (after the debouncing in my earlier
post), as described by nos...@nospam.invalid. I shift the previous
state two bits to the left, or in the current state, and use this
four-bit value in a lookup table with four values, meaning: do
nothing, decrement count, increment count, error (I increment an error
count for debugging/performance measurement). This causes a count
change of four for every detent.
When the sequence goes to the detent value, I give the app the
count divided by four. This causes a change as the encoder falls into
the detent in either direction, so it has a good 'feel' (like an old
TV tuner, the value changes when it 'clicks') and it can't be teased.

There's this article:
http://www.circuitcellar.com/library/print/0303/millier152/index.htm
that talks about partial decoding for encoders with detents and
mentions 'teasing' with encoders without detents. I really think full
decoding is the right thing to do regardless.

>This can work fine for low encoders speeds. You just have to see what
>the worst-case time is between ISRs and make sure that time is less
>than the shortest possible time between a transition on the A-phase
>and a transition on the B-phase. The software solution may work fine
>for manually-operated dials.

It does...

>But all the applications I see are in
>industrial machine control where the encoder is on some shaft turned
>by a motor. 500 nsec. pulse times are not uncommon.

That kind of application is 'in principle' the same function of
quadrature decoding, but in practice is quite different - it obviously
demands hardware (or a very fast processor). Also, such high speed
encoders invariably use optical detection (or some other non-contact
method), so there's no need for debouncing.
Optical encoders are available for front-panel applications, but
they're rather expensive and used in scopes and logic analyzers, where
engineers with five thumbs on each hand would easily break the shaft
of a cheap encoder. I've been frustrated that I haven't found an
optical encoder in the under-five-dollar range when for years computer
mouses were sold in that price range which had TWO encoders in it.

Robert Scott

unread,
Apr 20, 2004, 3:30:09 PM4/20/04
to
On Tue, 20 Apr 2004 12:40:47 -0400, Ben Bradley
<ben_nospa...@mindspring.example.com> wrote:

>..Also, such high speed


>encoders invariably use optical detection (or some other non-contact

>method), so there's no need for debouncing...

Actually, there is. The same "teasing" that you talked about earlier
can happen with an optical encoder when it is coupled with a motion
that is periodically changing direction. At the point where the
direction changes, you can get signals just as jumpy as with a contact
encoder. The shift register method that I use in hardware and that
you described in a software implementation acts as adequate
debouncing.

Lewin A.R.W. Edwards

unread,
Apr 20, 2004, 5:01:22 PM4/20/04
to
Ben Bradley <ben_nospa...@mindspring.example.com> wrote in message news:<area80his0nmae1th...@4ax.com>...

> >>falling edge on A followed by a falling edge on B with no intervening
> >>rising edge on A is a count in (say) the + direction. A falling edge
>

> A problem with this scheme is the encoder can be 'teased' by moving
> it halfway off of a detent then back, causing the falling-A-falling-B
> sequence, causing a count increase, without the corresponging
> falling-B-falling-A sequence to give a corresponding count decrease.

Is that a problem in my scheme (requoted above) or in Robert's Scheme
O'Bafflingly Numerous Gates? I don't see how my system is susceptible
to that problem, because tease-n-return will not lead to a valid abA
or aBA sequence.

I got so curious about this little issue that I spent a few minutes
fiddling with my car stereo, and my wife's. They are probably
geneologically close, because both are from Visteon (Ford vehicles).

BOTH of them will either miss a count or count the wrong way if you
tease-n-release to the original detent. Interestingly, if you turn the
wheel *very* slowly from one detent to the next, my car's stereo will
"wake up" and show "VOL +9" or whatever, but won't actually change the
value - it recognizes that some activity is going on at the wheel, but
can't work out what direction it's being turned in.

> of a cheap encoder. I've been frustrated that I haven't found an
> optical encoder in the under-five-dollar range when for years computer
> mouses were sold in that price range which had TWO encoders in it.

The EVQ-WK is about $0.80, but it's not convenient to mount it on a
front panel (it's flat and bitty, has a "click" function as well as
quadrature, and is designed to stick out of a corner of something).

0 new messages