Issue
152 March 2003
2-D
Optical Position Sensor
by
Roger Johnson & Chris Lentz
CIRCUITRY
If you decide
to build this system, the layout is important for the
detector pre-amps and ADC. A ground plane-type board
is recommended.
We decided
to design a PCB because it makes development much easier
(see Figure 6). To limit noise pickup, the distance
between the PSD and pre-amps should be no more than
1" (see Figure 7). The four-channel 12-bit ADC
should be well bypassed and located near the gain-stage
amps. Our circuit was laid out on two PCBs. We used
a small pre-amp module for the pincushion 10 mm × 10
mm Hamamatsu S5991-01 lateral-effect photodiode and
the larger one for the rest of the circuitry.
|

(Click
here to enlarge)
|
Figure
6—The 2-D optical position sensor uses two op-amps
in each leg of the PSD. The first stage is located
near the PSD, and the voltage generated is negative
with respect to ground. The second stage is located
on the main board. It inverts the signal from the
pre-amp stage back to a positive voltage for the
12-bit ADC. |
|

(Click here to enlarge)
|
Figure
7—The first and second stages must use micropower
rail-to-rail op-amps (LT1490s are used here). A
programming port is located at J3 for downloading
and flashing the PIC16C873 processor. The gain resistors
in the second stages R12 through R19 and those in
the pre-amp stages should be 0.1%-tolerance types
to achieve the better than 1% accuracy that’s possible
with the PSD. |
Power comes
from the two AA alkaline batteries that we mounted underneath
the main board. The batteries drive an efficient charge-pump
regulator and voltage inverter for operating the rail-to-rail
op-amps. We recommend Linear Technology LT1490s.
All of the
op-amps use 0.1% precision resistors (these tolerances
must be used for measurement accuracy); the rest of
the component tolerances are standard. For biasing this
PSD, R9 is omitted, and R8 is 100 W. The design of this
instrument assumes a laser pointer of less than 5 mW
of power (most operate in the 2- to 3-mW range) and
a PSD wavelength responsivity of 0.40 A/W.
The first-stage
pre-amp gain must be set so that a 5-mW pointer can’t
saturate it. Also, this type of PSD divides the total
photocurrent seen by each lead by four. Finally, the
rail-to-rail pre-amps will saturate when the output
reaches 5 V. The feedback resistor value is determined
by the equation depicted in Figure 4g. Therefore, the
pre-amp gain resistors should be no larger than 10 kW.
You must allow for ambient light, which will force Rf
to be smaller. Four 0.1%-tolerance, 2.4-kW
resistors were finally selected.
The second
gain stages U7 and U8 invert the negative output from
the pre-amps and offer a means to change the overall
gain if a lower-power pointer is to be used. Note that
the PSD used here will become nonlinear if the power
density on its surface exceeds 3 W/cm2. The typical
2- to 3-mW laser level has a beam diameter of roughly
3 mm and a power density 70 times less than this limit.
Saturation will occur when milliwatt power levels are
focused to small spots on the PSD surface.
The outputs
of the second stages go through 10-Hz, anti-aliasing,
low-pass filters and are input to a Microchip MCP3204
four-channel, 12-bit analog-to-digital converter. Tactile
push buttons serve to initiate the nulling functions
and to change display modes. A MAX232 sends position
data to an external device. Finally, a 2 × 16 LCD that’s
addressed in nibble format and based on the Hitachi
HD44780 controller is used as the display.
SIGNAL
PROCESSING
The four photocurrents
are turned into voltages by the pre-amps and then converted
into 12-bit values. Remembering that the normalized
position value (n) always ranges from –1 to 1, the problem
is how to convert it to dimensional units. So, the first
question to ask is: what resolution is desired?
Our goal for
this instrument was 0.0001" resolution (2.5 µm).
Because the measurement range from the center of the
PSD is L/2, 5 mm or 0.1968", multiply the normalized
position value by 1968—the largest position that can
be sensed in units of tens of thousandths of an inch.
Now, we’ll
recap. To display data with 0.0001" resolution,
the PSD signals are processed by: obtaining X1, X2,
Y1, and Y2 from the 12-bit ADC and bounds check for
high and low; calculating the numerators in Figures
4e and f; multiplying the numerators by 1968; dividing
both results by the sum signal (i.e., S = X1 + X2 +
Y1 + Y2); and discarding the remainder.
POWER DATA
The power
of the incident beam is proportional to the aforementioned
sum signal, S = X1 + X2 + Y1 + Y2. The optical power
(in milliwatts) is obtained via the equations in Figures
4h and i, where S is in A/D counts, G is the gain of
the second stage, and R is the responsivity of the PSD
in amps per watt. Rf is the value of pre-amp feedback
resistors.
FIRMWARE
The firmware
for this project was written in C using a CCS compiler.
The main task is interrupt driven from Timer0 and continually
acquires data from the four-channel ADC, solves the
position equations, and then displays the data. The
Mode and Null push buttons are polled to determine if
the operator has pressed them.
There are
additional points that must be emphasized. The low-pass
filter on the outputs of all four gain stages won’t
completely remove the strong 120-Hz optical noise signal
created by room lights. We also wanted the PSD to be
able to produce good results without the use of an optical
filter. The firmware implements a first-order infinite
impulse response (IIR) low-pass filter. The algorithm
for this type of low-pass filter is given in Figure
4j. Note that Cn is the current filter output, and Cn–1
is the previous filter output. Rn is the current input
to the filter, and Rn–1 is the previous input to the
filter. Finally, f is the 3-dB breakpoint frequency
of the filter in hertz, and T is the sample period in
seconds.
For this filter,
the sample period was 10 ms, and the 3-dB breakpoint
was 5 Hz. Thus, the algorithm becomes a simple one with
two coefficients (see Figure 4k). The actual code fragment
is:
filter = ((signed
int32)
olddata
* coefs.a) + (((signedint32) newdata + (signedint32)
lastsample) * coefs.b); olddata = (signed long
int) (filter >> 15);
The two coefficients
were multiplied by 32,768 before being multiplied by
the delayed terms. Then, the result was shifted to the
right by 15. This software filter effectively reduces
the induced optical noise to low levels. Even under
extremely intense lighting, the displayed position is
rock steady.