POSTS
Valve Index base station reflection detector
Description
The Valve Index is a virtual reality headset created by Valve.
The position of the headset and controllers are tracked using at least two lighthouses. Each lighthouse has two lasers in it, each of which produces a flat beam of infrared light. The beams are perpendicular and offset from each other, and spin at a high speed such that each beam scans across the entire VR space at about 100 times per second.
By precisely measuring the time at which the beam strikes several photodetectors on the headset and controllers, it is possible to infer the position and orientation of the device.
One of the main sources of tracking issues with this design comes from reflective surfaces. Reflections from the lighthouses can cause signals to be detected by the device at unexpected times, confusing the algorithms that determine the position of the controllers.
This project has two components: a fixed “sync” detector that produces a pulse when the beam from a lighthouse passes over it, and a remote light sensor that can be moved freely through the VR space to look for reflections.
The sync pulse is fed into the trigger input of an oscilloscope, and the light sensor is fed into one of the input channels. Two distinct peaks are visible for each cycle of the sync pulse, one for the first sweep and one for the second. Any sources of reflection will produce smaller peaks in addition to these two, which are visible on the scope.
Initially, I tried to use a simple single-ended transimpedance amplifier and photodiode for these detectors.
The first prototype was built “dead-bug” style, with an LM1458n glued upside-down to a copper clad board.
This worked very well for the sync pulse, since the photodiode for that could be mounted directly to the circuit board, and because the pulses could be focused by a lens to improve signal-to-noise ratio (SNR). It did not work well for the remote input though, which had the same photodiode at the end of a long ethernet cable. The input impedance of the TIA is close to 0 ohms, and the poor matching caused a significant oscillation problem. The single-ended nature of this TIA also made it very prone to picking up 60Hz AC noise from the environment, especially when held.
To resolve these issues, I designed a new driver with a differential input design and a 120 ohm input impedance. This impedance was chosen so I could use standard ethernet cables.
The new circuit is broken into 3 stages; the first is an input stage which provides the 2.5V reverse bias and 120 ohm input impedance, as well as an initial gain of 20mV/uA. Reverse biasing the diode decreases the junction capacitance which improves frequency response.
The second stage is a difference amplifier that subtracts V(OUT-) from V(OUT+), to convert the differential signal into a single-ended one.
The final stage is an adjustable gain stage. By default, with RG=1Megaohm, the gain is 100x, but a header is exposed that makes it possible to change this by installing different resistors.
I designed this as a PCB so it could be easily integrated into future projects.
The design was done in KiCAD. The op amp in use (OPA4354) has a much higher gain-bandwidth product than the LM1458 I started with, because I found that at high gains the frequency response became a limiting factor.
Resistor networks were used for both of the two input stages for two reasons. Firstly, they take up less board space and are quicker to solder. Secondly, resistor networks are available with very tight in-network matching compared to discrete resistors, which is critical for the difference amp and reverse bias circuitry. Using 0.1% discrete resistors for these would have been quite expensive, but taking advantage of the tight matching between the resistors in a 1% or 5% resistor network can yield even higher performance at lower cost, since the relative matching of the resistors is much more important than their absolute resistance.
I assembled the PCB using a stencil, hot air gun, and soldering iron:
PCBs and solder stencil were ordered from JLCPCB and arrived about a week after I ordered them. Components were ordered from DigiKey. The design for the PCB (annotated with part numbers) can be downloaded from my bitbucket page
Using the board with a 3 foot section of ethernet cable, with a photodiode on the end worked much better than the dead bug prototype (lower noise and much higher bandwidth), but the board had noise issues with longer lengths of cable. This could be improved by adding a resistor network to better reject common mode noise on the first amplification stage, and adding a 120 ohm termination on the photodiode side.
As a test I tried attaching the photodiode and a battery directly to the board (initially I was using a fixed linear power supply). This improved the noise performance tremendously. In the below image you can see the relative output of the dead bug amplifier (purple) and the new PCB amplifier (yellow).
The frequency response and gain is much higher on the new board. The ripples in the waveform do not seem to be noise. When synchronizing the scope sweep on the slower amplifier (which is on a completely separate circuit) and moving the detector on the PCB, the position of the envelope moves, but the position of the ripples appears fixed on the scope trace. I think this is either caused by a speckle pattern from the base station, or may be the result of high frequency modulation of the laser to improve tracking accuracy.
To establish synchronization on only one of the two laser sweeps, a bi-convex lens with a rectangular slit in front of it is used to focus an image of the base station on the low-speed detector. The slit is oriented so the long side is parallel to the sweep beam that is used for synchronization.
The idea is that when the beam is parallel to the slit, a short and intense pulse will be produced, but when it is perpendicular a lower amplitude longer pulse will be produced.
The below image is meant to illustrate this conceptually. The red bar shows the laser sweep and the grey bar represents the aperture in front of the lens.
The red traces at the bottom show the waveform that is produced as the beam scans over the aperture.
This is the physical setup:
And here you can see the two pulses that are produced. The perpendicular pulse is bright purple and the parallel is dark purple:
By setting the trigger level to only be above the parallel pulse, a reliable synchronization is achieved.
By moving the photodiode around while blocking the direct path from the detector to the base station, sources of reflections can be identified.
Here is an example of moving the detector in front of a window (a common cause of tracking problems)
In the video, the moving spike on the yellow trace is caused by the reflection off the window. The window is to the left of the probe, and the base station is to the right.
For next steps on this project I’d like to design an enclosure for the battery + amplifier + photodiode, and add a 50 ohm terminated BNC connection on the bottom so it can be used like a wand on the end of a long cable for easier diagnosis of tracking issues.
It is worth noting that for this device to be useful in its present state, only one base station can be turned on at a time. Otherwise you will see pulses from the other station that is not being synchronized to.
This is meant to just be a simple diagnostic tool, but it could further be improved by integrating USB battery charging/voltage monitoring and a high speed comparator + FPGA to digitize the pulses and report them on the device, rather than depending on an oscilloscope and user observation for analysis.
The design could also be improved by integrating an infrared filter onto the photodiode, to reduce sensitivity to lights in the room. The BPW34 photodiode I am using is sensitive to most of the visible spectrum.