Javascript Tabs Menu by

3DOF Tracker

Home Built 3DOF Tracker Project
The Plan

To build a reasonably inexpensive headtracker that will have 3 degrees of freedom providing accurate and stable yaw, pitch and roll readings. Please note that most of what I am documenting is pretty basic stuff. I am teaching myself most of it as I go and am writing it down with the hope that it may help someone else with their project. If someone has any suggestions or requests, please don't hesitate to contact me through the Contact page.

Test Bench
This is my test board. What a mess.

To start I have been playing with Atmel microcontrollers connected to a 3 axis accelerometer, 2 axis gyroscope and a 2 axis magnetometer. This is all a learning experience for me as before I started I didn't even know what these things really did. My test bench is an Atmel STK500 development board and I have been using Atmega16 microcontrollers to start with. I have an LCD screen connected to the Atmega16 which I use to display various pieces of data so I can view what is going on. I have also written a program in VB6 that connects to the Atmega through a comm port and retrieves data for me to also view and test. I have a simple 3D cube that I can rotate or move using the retrieved data which is teaching me a lot about what the data is doing and what I need to do to improve it.

A short video showing my results so far using the accelerometer to measure
pitch and roll. Boring .... I know.

A lot of noise in the results. Very jittery movements, the cube twitches
around even when the accelerometer is not moving.

My first testing is with the 3 axis accelerometer. So far I can read the accelerometer using the built in 10 bit ADC's on the Atmega16 and from the readings I can convert to gravities and then to pitch and roll. But the readings have a lot of noise and are very jittery. Originally I was hoping to be able to get accurate pitch and roll data using just an accelerometer, but I have found it is very difficult to filter out lateral movement from rotation.

A short video showing my results so far using the gyroscope to measure pitch and roll.

Nice smooth movements, not jittery at all but there is some drift that occurs after a while.

Next I played with a 2 axis gyroscope. With the gyroscope it took me a while to work out what to do, but eventually I found that if I measure the voltage from the gyro using the ADC at a regular and known time interval I can work out rotational movement rates and then keep track of pitch and roll. Once I got it all calibrated this worked very nicely, gave very smooth movements with almost no noise or jitter. But gyro's are prone to drift and need to be corrected every now and then using the accelerometer. I am yet to work the 2 devices together and combine the data. This may end up being pretty complicated.

A short video showing my results so far using the magnetometer to measure yaw.

Poor resolution at the moment and tilting the magnetometer causes wild directional changes.

Next I looked at the 2 axis magnetometer to measure yaw. Again using the ADC I get 2 voltages. After writing a calibration routine that measures the full range of the x and y voltages as they are rotated 360 degrees, I can easily convert the data to a directional heading. But I have found that I am not getting very good resolution. Even with an opamp I am only getting 90mV range which is only using a fraction of my ADC range. Another thing I found is that tilting the magnetometer makes the readings change a lot more than I expected. I thought I could correct for the tilt using the roll and pitch calculations from the accelerometer and gyro, but I have found I also need a 3rd axis for the magnetometer to do this correctly. I am in the process of working out better amplification for the magnetometer and adding a 3rd axis.

Next on the list:-

  • Incorporate a 16bit ADC to improve the resolution.
  • Work on the fusion of the accelerometer and gyroscope to get smooth pitch and roll results.
  • Incorporate a 3rd axis on the magnetometer and improve resolution to get tilt corrected yaw readings
  • Etc etc ..... Lots more to do

Posted: 13th August 2007.
Test Bench
An MMA7260Q Accelerometer Breakout board from SparkFun Electronics.

So far I am using these formulas to calculate pitch and roll from the accelerometer readings:-
pitch tilt in radians = atan2(xG,zG)
roll tilt in radians = atan2(yG,zG)
If the accelerometer is stationary and I just rotate it this works very nice. But if I do not rotate it at all but move it in any direction it will be interpreted as changes in pitch or roll which is no good.

The following code snippet is the c code used by the Atmega16 microcontroller to read the accelerometer data using the onboard 10 bit adc and to calculate the pitch and roll using this data.

+ Code Snippet

Now apparently when both of the following calculations are close to 1 the accelerometer is not moving.
|pitch Gs|=sqrt(xGs^2+zGs^2)
|roll Gs|=sqrt(yGs^2+zGs^2)

At the moment I have no idea how to use this to cancel out direction movement and only measure rotational movement. That is why I thought I'd need the gyroscopes. They measure only rotational movement and are not effected by directional movement.

Posted: 15th August 2007.
Test Bench
An ADS8344 16 bit ADC Evaluation Module and the accelerometer.

I have been working with an 8 channel 16 bit ADC. Only using the accelerometer so far. Previously with the 10 bit ADC on the MCU I was getting around 500 steps from -1g to +1g. With the 16 bit ADC I now get around 32000 steps so much much better resolution. Unfortunately I am getting a lot of noise from the accelerometer even with hardware and software filters. It is a MMA7260Q accelerometer from Freescale. I'm going to keep working with it for now but I think I'll try a ADXL330 from Analog Devices as it claims to be extremely low noise. Or another choice is a LIS3LV02DQ accelerometer from ST Micro which has a digital interface so should have it's own noise filters.

The following code snippet is the c code used by the Atmega16 microcontroller to setup and retrieve data from the ADS8344.

+ Code Snippet

Next to connect the gyroscope to the 16 bit ADC....

Posted: 27th August 2007.
Gyro Breakout Board
IDG300 Dual Axis Gyro Breakout Board from SparkFun Electronics.

I am still working on removing the noise from the accelerometer data, but at this stage I am not too fussed as the gyroscope has proven to be a success both in it's ease of use and the nice smooth readings I am getting from it. There is some drift that would normally be a problem, but I can use the accelerometers to reset the angles from the gyroscope when certain "yet to be determined" conditions are met.

The following code snippet is the c code used by the Atmega16 microcontroller to retrieve data from the IDG300 gyroscope. This code is using the Atmega 16 onboard 10 bit ADC. Note the timer interrupt routine does all of the work.

+ Code Snippet

Next to filter the noise from the accelerometer readings...

Posted: 28th August 2007.
Noise Graph
Graph of the raw voltage from the accelerometer.

Here are some graphs I made by connecting the usart of the Atmega16 to a PC comm port via a Max232 chip. Using a Visual Basic program that I wrote I am plotting the voltage from one channel of the accelerometer on the graph. The first graph is the raw voltage data with no filtering at all. From these graphs I am hoping to get some advice on the best hardware filtering to use to reduce the noise.

Noise Graph2
Graph of the software filtered voltage from the accelerometer.

The second graph is using some averaging of old readings and new readings to filter some of the noise out. I haven't marked the lines on the graph, but basically these graphs are displaying millivolts from a single accelerometer channel while it is totally stationary. The fluctuations are from 1500mV to 1526mV which is a lot when I am splitting a 1600mV range into 32000 pieces. The software filtering as reduced the noise considerably but still needs a lot more.

Noise Graph3
Graph of the raw voltage from the accelerometer whilst moving slowly.

This graph shows me moving the accelerometer fairly slowly one way, stopping then back the other way and stopping, a number of times. I had to lower the resolution of the graph to fit movements on the screen.

Noise Graph4
Graph of the raw voltage from the accelerometer whilst moving rapidly.

This graph shows me moving the accelerometer quite fast backwards and forwards a number of times.

Noise Graph5
Graph of the raw voltage from the accelerometer whilst tilting it back and forth.

This shows me tilting it slightly one way then the other a few times.

To improve the noise I am increasing the filter capacity of the RC filters that are on the accelerometers breakout board. The existing resistors are already 1K so I will leave them as they are and experiment with increasing capacitor values. I started with a 47uF cap which reduced the noise amplitude to 1mV but it did induce too much latency. I ended up with a 22uF cap which left me with around 4mV noise amplitude but no latency. I'll fine tune this a bit more when I get some time.

Noise Graph6
Graph of the filtered voltage from the accelerometer whilst tilting it back and forth.

The results were very succesful as can be seen in this graph which is a reproduction of the last graph showing the accelerometer being tilted slowly back and forth. Most of the noise you can see in this graph is from my shaky hand.

It's not perfect, but using this data combined with the gyroscope data, which has no noise, should give me some nice clean pitch and roll calculations. Thanks to Marc Bernatchez from for his advice on the RC filters.

Next to work out getting the data from the 3 axis magnetometer....

Posted: 30th August 2007.
The Micromag3 3 Axis Magnetometer from PNI.

One step forward, two steps back.

Took me a while to get the code working right with the connection to a PNI micromag3 3 axis magnetometer. It uses a serial interface and I haven't done much with them before. So I can now calculate a compass heading using the results. I have also been playing with a calculator testing the tilt compensation algorithms I have and they seem to work OK.

Tilt compensation algorithms -

+ Code Snippet

So the next step was to take the pitch and roll readings from the accelerometer/gyroscope and use this to calculate the tilt compensated compass headings. This is where the real problem started. Once I connect both SPI devices, ie the 16 bit ADC and the 3 axis magnetometer I couldn't get them to work. Separately I can get them to work fine. Together I can get the magnetometer working but not the ADC. I think the problem might be that the magnetometer doesn't have tri-state outputs. It doesn't say in the datasheet. This means the outputs don't disconnect when I deselect this device. The ADC does have tri-state outputs so it does disconnect.

After playing with the magnetometer and looking at the readings I think I can make a reasonable guess at the Z axis readings based on the X and Y readings using the theory that the total magnetic field is sqrt(x^2+y^2+z^2). By rotating the 2 axis magnetometer around all 3 axis I should be able to work out what the total magnetic field value is and from that work out a good guess of z using the x and y values. So next I will go back to using the 2 axis magnetometer with analogue outputs and see how I go working out the tilt compensated compass headings. I think I'll also incorporate a yaw rate gyroscope as well so I can work it's data in with the magnetometer to get a more accurate yaw calculation.

Posted: 19th September 2007.
Micromag3 with accelerometer
The Micromag 3 and Accelerometer test board.

I decided to test the tilt compensation algorithms using the Micromag3 with the Accelerometer connected to the Atmega16 ADC to get around the problem I had with the 2 SPI devices. It took me a while to get everything right, the pitch and roll need to be exactly the right way for the algorithm to work correctly.

Some of the code I used to get tilt compensation headings, included is code for the SPI interface as well as reading the Micromag3 -

+ Code Snippet

Posted: 27th September 2007.

Now that I have connected the analogue magnetometer to the ADC I have found that I can read it about 300 times faster than the PNI device. Not sure why. I discovered this during my calibration routine. I run a sampling loop long enough for me to rotate it 360 degrees. I can take about 100,000 samples through the ADC in about the same time it takes to take 300 samples from the PNI device.

Posted: 28th September 2007.

I finally have all the hardware set up and am able to calculate pitch, roll and yaw with reasonable accuracy. Integrating the data from the magnetometers and the yaw gyro is proving difficult as the magnetomer readings are not constant, ie I might get an 80 degree count from 0 to 90 and then a 100 degree count from 90 to 180. Whether this is from interference or not, I am not sure.

With all the number crunching I am having to do I am coming to the end of the Atmel AVR's ability to cope. It is just not fast enough. I can send raw data to the PC and get it to crunch the numbers, but I want as little load on the PCs CPU as possible. So I am moving to a DSP that can do 30MIPS. It also has a 500Ksps ADC on board too. I am just waiting on a development board at the moment so I will be back to learning to program a new chip very soon. More learning....

I have also been working on the PC software for the tracker and at the moment have set up my program as a TCP/IP server. This will allow other programs to request data from it using TCP/IP. I am not sure if this is the right approach but it works well on my tests. I have also improved the data transfer from the chip to the PC quite a lot and can send and receive all the data in just 6 bytes.

Posted: 28th October 2007.
Tracker test board
The dsPIC30F on the test board.

I haven't documented much of the latest work I have done as it was just redoing a lot of what I have already done but using a new microcontroller. But today I finally had a breakthrough. I have been learning to program a completely new chip, struggling with a lot of the code, especially getting the timing right reading the gyros. I am now using a 16 bit dsPIC30F chip now with a 13 channel onboard 12bit ADC. I have it running around 30MIPS which is way better than the Atmel chips I was using.

Yesterday I was almost ready to give up and started shopping around to buy some trackers, today I finally worked out a few bugs and now have a tracker which has nice smooth pitch, roll and yaw readings. I can shake the tracker and it doesn't effect the pitch and roll, which is a big breakthrough for me. The yaw is only obtained through a gyro, but it is reasonably stable and will be OK for me to begin work on the software stage of the project. Even though I had previously managed to get tilt compensated headings with the Atmel chip and the Micromag3, the readings were just not accurate or stable enough to use. So I have given up on the magnetometers and am only using the gyro for yaw, and the combined data from the accelerometers and gyros for pitch and roll.

The schematic of the dsPIC with accelerometers and gyroscopes.

The schematic I have drawn using Eagle. Please excuse how poorly it has been drawn. I have no idea on the correct way to draw schematics. It shows the connections between the dsPIC30F4013 and the various other components. The schematics for the individual breakout boards are not included. Follow the links to view the schematics for the MMA7260Q Tri-Axis Accelerometer, IDG300 Dual Axis Gyroscope and the ADXRS Single Axis Yaw Rate Gyroscope.

Believe it or not, all of those components can be squeezed onto a board around 1" x 1".

Next step ... the data glove and start working on the VR software.

Posted: 22nd February 2008.

The tracker test board being moved through it's 3DOF.

I just thought I'd do a small video of the tracker test board while it is hooked up to the Visual Basic test program. It is not a very good video but you can see the tracker moving the 3D box through all 3 angles. Most of the jitter you see is my hands shaking, it is quite smooth when it is held carefully.

Posted: 3rd March 2008.

Javascript Tabs Menu by