Issue
152 March 2003
Using
Rotary Encoders as Input Devices
PROGRAM
CODE
Let’s
look at the code needed to read the Grayhill 2-bit Gray
code encoders (see Listing 1).
The code was written in BASCOM-AVR and should run on
any AVR microcontroller. To make matters easier, BASCOM-AVR
has built-in I2C routines. The early statements in the
program Config sda and config scl define the port lines
used for the I2C bus. There are various statements needed
to configure the INT1 line as an input, enable weak
pull-ups on this line, and configure INT1 for falling-edge
interrupt response. The PCF8574 is then set so that
all of its lines are inputs by writing all ones to it.
The
INT1 ISR, labeled Frontpanel in this case, handles the
actual reading of the encoders. When an encoder position
changes and causes an interrupt to occur, the first
chore is to read the PCF8574’s 8-bit input latch. The
two bits corresponding to the first encoder are selected
using the AND function. This value is concatenated with
the prior 2-bit value to form a 4-bit nibble. Of the
16 possible values of this 4-bit nibble, only eight
of them are valid. The other eight result from cases
in which the current encoder value is the same as the
prior encoder value, in which case the ISR routine isn’t
called because a change didn’t occur.
This
4-bit value is then fed to the BASIC Lookup function.
This function returns a number by looking up a value
from a 16-entry table, using the original 4-bit value
as an index into that table. If you look at the table
(labeled Relookup), you’ll see four positive ones and
four negative ones corresponding to the eight possible
transitions of the encoder outputs. There are eight
zeros in the table that correspond to the eight cases
in which the encoder hadn’t changed position. Strictly
speaking, the latter eight entries will never be used,
but they’re necessary as placeholders in the table.
After
the look-up process, either a positive one or a negative
one is added to the variable representing the position
of the encoder shaft. This variable will generally represent
some parameter in the actual program itself (i.e., it’s
seldom ever used to represent the actual position of
the encoder’s shaft itself). The second encoder is read
in the same fashion, using different bits from the PCF8574’s
input port. Additional code can be added to the ISR
to handle various other switches that might be connected
to the PCF8574. For this example, the main program just
sits in a loop and prints the encoder values when they
change.
The
code for the Bourns ECW1J-B24-BC0024 encoders isn’t
shown here, but you may download it from Circuit Cellar’s
ftp site along with the rest of the code. The Bourns
signal output is not as perfect a match to the PCF8574’s
architecture as the Grayhill unit, but it still works
with some modifications to the code.
If
you’re like me, then you’re probably always running
out of I/O lines on your favorite microcontroller before
your projects are finished. Using the PCF8574 to handle
your rotary encoder/panel switch interfacing will help
to alleviate this problem.