
The new PAK-VIIb has a special feature that allows it to read quadrature data inputs. What's a quadrature input? Consider a typical (non optical) mouse that connects to a PC. Inside there are two shafts that the ball moves. Each shaft has a slotted wheel on the end. On one side of the wheel is an LED. On the other side are two phototransistors.
The mechanical arrangement is such that when the wheels turn, the slits let light pass to one transistor before it hits the other. Which transistor gets lit up first depends on the direction of the wheel. Obviously, the width of the pulses will tell you the speed the wheel is moving and the number of pulses can tell you how far the wheel has traveled. The PAK-VII can easily measure all of these quantities!
Here's a scope trace of a wheel turning counter clockwise:

Note that channel 2's pulses are ahead of channel 1's pulses. Here's a trace of the wheel turning clockwise:

Here, the situation is reversed. Channel 1's pulses arrive before the pulses from channel 2.
Each channel on the PAK-VIIb has an enable input. Suppose you connect the signal from trace 1 to the enable pin and the signal from trace 2 to the corresponding PAK-VIIb input. The enable input only allows the PAK to count edges when it is high. In the first scope picture, then, the PAK will ignore the rising edges on channel 2 because the enable pin will be low. However, it will count the falling edges, since by then the enable signal will be high. Therefore, the falling edge count will tell you how far the wheel traveled in the counter clockwise direction. The duration registers will tell you how fast the wheel is moving if you need to know that.
In the second scope trace, the situation is reversed. The rising edge of pulse 2 occurs during the enable, but the PAK ignores the falling edge. Therefore, the falling edge register tells you the travel distance in the clockwise direction. Of course, which register is which depends on how you hook up the signals. If you put channel 1 on the input and channel 2 on the enable pin, the registers would be reversed (the rising count would indicate counter clockwise).
The exact circuit you'll need will depend on the mouse you use. I gutted a cheap serial mouse. A quick probe with the scope showed me which pins were changing when the wheels spin (you do have to supply the mouse with 5V, of course). The outputs of the phototransistors were not very high level, so I connected each output to the base of a 2N222 through a 1K resistor. The whole circuit looked like this (you have to build two copies; one for each input):

Of course, your mouse may be different. If you are using a commercial shaft encoder, it probably already has 5V outputs.
I connected the PAK to a Basic Stamp 2p just as it shows in the manual:

I connected the Data line to Stamp pin 15 and the Clock line to Stamp pin 14. I also connected a standard RC servo to pin 7 of the Basic Stamp so I could do something interesting with the wheel data. The mouse inputs I connected to P0 (on the diagram above) and pin 18 (this is marked N/C on the schematic, but it is actually the P0 enable).
The RC servo needs power, too, of course. I used 4 AA cells for that (be sure to make a common ground between the digital circuit power supply and the motor supply).
I had in mind to make sort of a software synchro (they tell me no one says selsyn anymore). The idea is that motion in the wheel will cause similar motion on the servo.
Using the PAK-VII library, the main program is pretty simple:
GOSUB freset ' always reset! ' Turn on pull up resistors for input fpx=0 GOSUB fpullup ' Read channel 0 all the time chan=0 clearreg=0 xloop: clearchan=0 ' Get the RISE register w/o clearing anything register=RISE GOSUB FCommand i=fpx ' store answer in temp variable register=FALL ' Now get the FALL register AND clear everything clearchan=1 GOSUB FCommand GOSUB style2 ' Now fpx and i have the direction data, so control the servo GOTO xloop
I used two different servo routines to get different behavior. Here's my first routine that starts the servo spinning in the direction of the wheel turn until you turn the wheel back (this was a modified servo that continuously rotates; you probably shouldn't try this one with a standard servo):
' wheel sets rotation direction speed
style1:
IF i<>0 OR fpx<>0 THEN ' if the wheel moved
IF i>fpx THEN ' set pulse width
pw=pw+(i*100)
ELSE
pw=pw-(fpx*100)
ENDIF
DEBUG DEC i,":",DEC fpx," ",SDEC pw," ", SDEC CENTER+pw,CR
ENDIF
PULSOUT SERVO,CENTER+pw ' spin servo in any case
PAUSE 20
RETURN
Changes in the wheel add up to the pulse width in this code.
Here's some code that acts like a synchro (when using a continuously rotating servo):
' Alternate code: servo tracks wheel
style2:
IF i<>0 OR fpx<>0 THEN
IF i>fpx THEN
pw=i*100
ELSE
pw=-(fpx*100)
ENDIF
DEBUG DEC i,":",DEC fpx," ",SDEC pw," ", SDEC CENTER+pw,CR
FOR i=1 TO 10
PULSOUT SERVO,CENTER+pw
PAUSE 20
NEXT
ELSE
PULSOUT SERVO,CENTER ' idle
ENDIF
RETURN
In this case, the servo stays centered unless the wheel moves. When the wheel moves, the code sends 10 pulses in the correct direction to move the servo along with the wheel.
This code is relatively simple. It doesn't track the speed of the wheel. Also, it is possible for the wheel to stop where one of the inputs is always high or even mechanically oscillate. You can detect these conditions by scanning the input pin or examining the duration registers, if it is important.
Of course, mice aren't the only thing that produce quadrature signals. Many shaft encoders (including some built into motors) produce quadrature output. It is easy to make your own encoder wheels (see http://www.portlandrobotics.org/robots/encoders/index.html).
You can visit our PAK-VII page for more information about the device.
Here's the entire program including the PAK-VII library:
'{$STAMP BS2p}
'{$PBASIC 2.5}
'{$PORT COM1}
DATAP PIN 15
CLK PIN 14
SERVO PIN 7
CENTER CON 1900 ' center servo position
' Register names
DURLOW CON %000
DURHIGH CON %001
RAWLOW CON %010
RAWHIGH CON %011
RISE CON %100
FALL CON %101
TICK200 CON %110
TICK CON %110
INP CON %110
VER CON %110
SUM CON %111
OUTPUT clk
OUTPUT datap
fpx VAR Word ' Integer used by some routines
fpb VAR Byte ' byte
' parameters for FCommand
chan VAR Nib
register VAR Nib
clearreg VAR Bit
clearchan VAR Bit
i VAR Word
pw VAR Word
GOSUB freset ' always reset!
' Turn on pull up resistors for input
fpx=0
GOSUB fpullup
chan=0
clearreg=0
xloop:
clearchan=0
register=RISE
GOSUB FCommand
i=fpx
register=FALL
clearchan=1
GOSUB FCommand
GOSUB style2
GOTO xloop
' wheel sets rotation direction speed
style1:
IF i<>0 OR fpx<>0 THEN
IF i>fpx THEN
pw=pw+(i*100)
ELSE
pw=pw-(fpx*100)
ENDIF
DEBUG DEC i,":",DEC fpx," ",SDEC pw," ", SDEC CENTER+pw,CR
ENDIF
PULSOUT SERVO,CENTER+pw
PAUSE 20
RETURN
' Alternate code: servo tracks wheel
style2:
IF i<>0 OR fpx<>0 THEN
IF i>fpx THEN
pw=i*100
ELSE
pw=-(fpx*100)
ENDIF
DEBUG DEC i,":",DEC fpx," ",SDEC pw," ", SDEC CENTER+pw,CR
FOR i=1 TO 10
PULSOUT SERVO,CENTER+pw
PAUSE 20
NEXT
ELSE
PULSOUT SERVO,CENTER ' idle
ENDIF
RETURN
' PAK VII library code from here down
FReset:
LOW DATAP
LOW CLK
HIGH CLK
HIGH DATAP
LOW CLK
RETURN
FCommand:
' inputs chan = channel, register = register, clearreg and clearchan
fpb=(clearchan<<7) + (clearreg<<6) + (register<<3) + chan
GOSUB FSendByte
FReadWord:
SHIFTIN datap,clk,MSBPRE,[fpx.LOWBYTE,fpx.HIGHBYTE]
RETURN
FTotalReset:
fpb=$FF
FSendByte:
SHIFTOUT datap,clk,MSBFIRST,[fpb]
RETURN
FReadByte:
SHIFTIN datap,clk,MSBPRE,[fpb]
RETURN
FPrescale:
' set fpb to the prescale constant
fpb = fpb + $C0
GOTO FSendByte
FPullUp:
' set fpx to the pull up mask
fpb=%11010000
Fscmd:
GOSUB FSendByte
fpb=fpx
GOTO FSendByte
FThresh:
' set fpx to the threshold mask
fpb=%11010001
GOTO Fscmd
FSchmitt:
' set fpx to the Schmitt trigger mask
fpb=%11010010
GOTO Fscmd
Site contents © 1997-2018 by AWC, Houston TX (281) 334-4341