Related lists

This project is submitted for

Description

GPS-enabled location and timing services has become a key technology in the current age of mobile technology. This project is to explore how they work, at a level below that of the standard NEMA sentences that most GPS modules provide for the user interface.

Although it includes the details of obtaining raw GPS samples at an intermediate frequency using a little bit of hardware and FPGA hacking, this project is a software GPS receiver.

Over time I expect to improve this (in both positioning performance and software performance), and eventually use it as a model for an open FPGA based GPS receiver.

Many debugging and instrumentation features will be added, allowing tweaks and tuning of the algorithms to be objectively measured.

I also hope that it will be used as a reference for others, who explore GPS technology at its lowest levels.

Details

This project has a small hardware component.

Development boards and custom FPGA software were used to obtain data sets consisting of raw 1-bit samples, taken at 16.368 MHz. A complete set of GPS NAV data is transmitted every 30 seconds, so it is essential that at least a minute's data is captured - requiring 120MB of storage. Because of the importance of timing information, it is also essential that every sample is captured. To do this with the equipment I had on hand, a small FPGA-based solution is used.

The bulk of the project is software. The software has to perform the following actions:

- Acquire the GPS signals from the satellite - finding the approximate frequency and phase . All satellites transmit on the same frequency, but signals a Doppler shifted and have taken many milliseconds to travel the to reach the antenna.

- Locking onto the carrier. From a rough ball-park frequency we need to get an absolute frequency lock to ensure good data reception

- Locking onto the phase of the GPS C/A code that is transmitted by the satellite. This generates the sub-microsecond timing information which is required to produce a location fix. As light travels at about 300,000,000 m/s this needs to be resolved with about 30ns of accuracy

- Reception of 50bps BPSK data (the 'NAV' messages)

- Decoding of the NAV data

- Calculating the position and time at which the signals were transmitted

- Calculating the solution for the antenna's location.

Components

1×
Kiwi SDR board, plus BeagleBone Black
This board was used as a source of the GPS samples, by attaching test points to the FPGA dev board

1×
Digilent Nexus-2 FPGA board
This board was used to capture the raw GPS sample information, buffer ir, and then provide the data stream to a PC over USB

Over the weekend I wrote some simple acquisition code. The method is rather simple, but effective.

The +/-5kHz band is 31 evenly spaced local oscillators - each 330 Hz apart. At any given time, one Space Vehicle is being searched for, over all 31 frequencies. Each of 1023 phase alignments is tested for 2ms, and each test is offset by 1us from the last one. When a 'sniff' of a signal is received, a channel is assigned to it and it tries to achieve lock. If a better 'sniff' is seen, the channel is reset with the new values, and once again tries to achieve lock.

The scheduling of which SV is being acquired changes depending on if lock is achieved, if any 'sniffs' were found, and an initial setting of priorities from a text file. At the moment, this uses about 15% of a CPU Core (out of a current total of around 30%).

One problem was that when a channel starts to lock, it can fall one of two ways - either onto the correct frequency (yay!) or fall to 500Hz to one side (wah!). If it falls to one side the channel's in-phase value alternates between + and - every millisecond, rather than staying steady for 20ms. My fix for this was when you have half a second of bad NAV data, but still have a signal lock then adjust the NCO by 500 Hz, towards (and past) the initial frequency. This jumps the channel pretty much directly into lock.

All in all the results have been pretty good: - It has been able to tease out 8 channels from a test data set:

I thought up a away to improve the speed - now uses about 3% of a CPU core per channel. The speedup also allows the early/late tracking that is used to follow the Space Vehicle's Gold code to be change from +/- 1 .0 chip (1/1023th of a ms) to +/-0.75 chip.

This allows more accurate tracking, giving more accurate pseudoranges and more precise fixes. Adding an averaging filter removes quite a bit of the remaining noise too.

Now I am in the ballpark of a commercial GPS module!

Here is the console output as it runs, showing it as it tracks 7 channels:

The initial version of the software was slow - it took over 6 hours to process 200 seconds of 16Mb/s data. This was expected, as the system was processing one bit at a time, one channel at a time, and was made that way to allow me to get the techniques correct before focusing on performance.

I've completed a new version of the channel tracking code (in the fast_fsgps directory) that now processes data in 'gulps' of 32 bits at a time.

This greatly speeds things up, and I can now process the same dataset in 110 seconds.

Debugging this code was one of the harder things I've done. I hit odd compiler behavior (you can't shift an 'int' 32 bits) and just my own stupidity a few times, but it now works cleanly and very quick.

Now to incorporate the NAV message code, to get position fixes in real time.

It will also make control loop tuning a lot quicker to test.

PS. I Just notice that I left some debugging code in place, where math was replaced with a loop to help find a fault. It is now 300x faster!

I've been fine-tuning the the process by which the timing and phase of the Gold codes is followed. This has approximately halved the spread of the fixes.

The points are 20ms apart, so an average of a second's worth of points would be less spread - absolute error is about 15m.

There is still a bit of room for refinement of the process. I played around with a PID loop for a few nights, but it doesn't seem to be that suited to the process. It tends to bounce around due to the noise in the system. However the (a-b)/(a+b) discriminator (where 'a' is the late code power and b is the early code power) is great for assessing the relative performance of new methods.

This looks intuitively OK (somewhere in England, at a reasonable altitude). So the next step is to check this on a map. For Latitude, N is positive and S is negative. For longitude W is positive and E is negative.

A quick search on Google Maps for "52.93473, -1.16467" will show where the solution is. For these numbers you should be somewhere just south of Nottingham in England.

But what do you do if the final location is wrong?

For debugging, you can also run this process backwards, but you will also need to find your altitude. For me the best tool for this is google Earth.

Once you have latitude, longitude and altitude you can convert your known position to ECEF position using the above website.

You can then run the calculations backwards to see what errors exist in your Space Vehicle positioning.

For example, the five Space Vehicles used had the following X,Y,Z and transmit time:

You would be better of logging the raw RF data and processing it after recovery. Without testing I suspect that some of the tracking loops would most likely unlock with sudden heavy acceleration, as they can't react quick enough.

If you did that you could process the same data multiple times, to get a good solution even over the expected "unexpected" discontinuity.