There are several times that you may
want to interface to a device that uses quadrature encoding. Here
are a few
This application note is not on how to
build one of these devices but more on how to program the Dios to read
one. I have a CNC system that I wanted to create a closed system so
that when I had overdriven the stepper motors I could still determine the
position of the axis in question. The same thing could be done to
determine if a robot wheel is turning.
These deices use two phase states
created by optical or mechanical means. they can be as simple as a
rotary wheel with holes and two leds and photo transistors.
The two phase output allows you to
detect not only movement but direction as well. Lets look at the
typical output of a 2 phase device.
Direction 1
00 01 11 10 ......(repeats)
Direction 2
00 10 11 01 ......(repeats)
As you can see a very simple pattern
is created depending on the direction the device is moved. So what
our program has to do is two fold.
-
Detect a change
-
Detect direction
First we detect change. If there
has been no change we exit the routine. No sense checking any thing
else if the device has not moved. To detect change we just
store the values of the last two phases (bits) and compare them with the
current ones. The simples way to do this is Xor them together.
If the result is 0 then no change has occurred and we exit with a value of
0 (no change)
Once we no there is a change we need
to detect the direction of travel. To do this we create a pattern of
what the device would look like if it was rotated in direction 1. We
know the last state so its simple bit fiddling to create the proper
pattern.
Again we xor the current pos with the
proposed pos. If the result is 0 we are moving in direction 1 if its
not we are moving in direction 2. We then return the appropriate
code to determine direction.
You will notice that I done refer to
directions specifically but rather by general terms. There is
a reason for this. All that need be done to reverse the true
direction is to reverse the leads of the two phase outputs.
The following program demonstrates the
procedures I just described. The main function calls the
getquad function to determine direction. It passes the IO ports the
phase outputs are connected to.
Program
1
'Demonstrates the interface to a Quaditure encoded device.
func main()
dim count
dim quaddir
count = 0
loop:
quaddir=getquad(0,1) 'Pass IO ports phase outputs are connected to.
branch quaddir,loop,incit,decit
goto loop
incit:
count = count + 1
print count
goto loop
decit:
count = count -1
print count
goto loop
endfunc
'-----------------------------------------------------------
'Returns the direction of a quaditure State Device
'Return 0=no change
'Return 1=Direction 1
'Return 2=Direction 2
'
'Pass the 2 port number for the phase A and phase B signals
'-----------------------------------------------------------
func getquad(port1,port2)
'Some variables that are needed
dim curport,tbit
'This on stores the last reading
global oldport
clear curport
'Get the encoder bits and store in variable
curport.bit(0)=ioport(port1)
curport.bit(1)=ioport(port2)
'Test to see if change
if curport ^ oldport = 0 then
exit 0
endif
'----------------
'We had a change
'----------------
'Lets build what we expect for dir 1
tbit=oldport.bit(0) 'We will need this bit later
oldport = oldport /2 'Shift bits
oldport.bit(1)= tbit ^ 1 'Add saved bit back in but invert
'Now test for what we expect
if oldport ^ curport =0 then
oldport = curport
exit 1
else
'Did not get what we expeced so its the other dir
oldport = curport
exit 2
endif
endfunc
The last program is not the fastest in the
world nor the most efficient. If the encoder changes faster than
this program can handle count will slip or reverse direction.
With this next program we will use some
inline assembly and speed things up a bit.
Note You need Dios
Editor 2.3 or later to run this code.
Program
2
'Demonstrates the interface to a Quaditure encoded device.
func main()
dim count
dim quaddir
count = 0
loop:
quaddir=getquad()
branch quaddir,loop,incit,decit
goto loop
incit:
count = count + 1
print count
goto loop
decit:
count = count -1
print count
goto loop
endfunc
func getquad()
startasm
retport equ ASMDAT0
TPORTS equ ASMDAT1
OLDPORTS equ ASMDAT2
clrf retport
clrf TPORTS
btfsc ioport 0
bsf TPORTS,0
btfsc ioport 1
bsf TPORTS,1
movf OLDPORTS,w
xorwf TPORTS,w
btfsc STATUS,Z
goto nochange
'--------------
'We had change
rrcf OLDPORTS,w
bcf WREG,1
btfss STATUS,C
bsf WREG,1
xorwf TPORTS,w
btfss STATUS,Z
bsf retport,0
btfsc STATUS,Z
bsf retport,1
movff TPORTS,OLDPORTS
goto alldone
nochange:
alldone:
endasm
exit ASMDAT0
endfunc
While this program is a bit faster it still
could miss something. There are only two way to catch all the steps
of a very high speed encoder.
-
Interrupt driven reader
-
Coproc
I will be doing both these a little bit
later. For now this should get you going with the interface
you your own encoders. As a closing note old computer mice
make an excellent source for encoders.

Parts
list
DiosPro 40 Pin Chip
Dios Workboard
Deluxe
Easy RS232 Driver
DiosPro 28 Pin Chip
Dios 32 Pin Carrier
(Carrier #1)
9 Pin Cable
Breadboard Regulator
DigiKey Encoder Part# CT3002-ND
www.digikey.com