DIY USB-powered GPS for
$100 $90 (Price drop!)
July 4, 2006 (backdated. Last updated Aug 7,2009)
"Where are we?"
This article describes how I used a bare GPS module, a USB-to-serial interface board, and a project box to build a small USB-powered GPS unit for my laptop for around $100 in under an hour. Note: Since I wrote this article two years ago, prices have changed, and the total cost today would be around $90
First, some background: I already owned a fancy Garmin GPS. The problem with it is that it uses a proprietary protocol for interfacing with a PC. As far as I could tell, about the only software that would talk to it is the software that came with it and other software that Garmin sells. I wanted something that would be easy to interface with, and compatible with various open-source GPS tools, so NMEA compatibility was a must. I dual-boot my Dell laptop between Linux and Windows, so being able to use it in either environment was important as well.
I probably could have purchased a consumer GPS unit for around about the same amount, but where is the fun in that?
Spark Fun sells a wide variety of products for electronics experimenters, and this includes several different GPS modules. The EM-406 GPS module that they sell is one of their best GPS modules. It has a serial interface that outputs NMEA compatible codes, and an integrated patch antenna. All of the incredibly hard work of receiving and interpreting the GPS signals is already done for you by the module. All you have to do is supply power and connect the Rx/Tx lines to something that understands serial I/O and NMEA codes. The serial lines from the module are both 3.3v (they can NOT be connected directly to an RS-232 port). For power it expects 4.5-6.5v (at ~70mA). This combination is perfect for interfacing with most USB-to-Serial chips (such as FTDI), as the USB interface can supply 5v for power and most of the chips support 3.3 volt I/O.
Spark Fun also sells USB-to-Serial breakout boards that have the correct electrical requirements. I ordered one based on the CP2103 chipset along with the GPS module. The USB board uses Windows, Mac or Linux drivers that allow it to emulate a physical serial port to user applications.
The GPS module came with a small 1.5" cable with JST connectors on each end. I simply clipped one of the JST connectors off of the cable, stripped the wires and soldered them to the appropriate pads on the USB breakout board. My advice to anyone who wants to try this: be sure to order an extra JST cable along with the GPS module. The wires are very tiny and short, stripping them without breaking a wire may be a little challenging. Also, be prepared to spend a little time studying the datasheets for each of the modules to determine what connections to make.
A $2 project box from All Electronics was used to house the module and the USB board. The size of the project box was near-perfect: as you can see from the picture the two boards just did fit inside of the box. I used double-sided tape to hold the module and the USB board to the bottom of the project box. I also used screws to secure the USB board since it would be getting some stress from plugging and unplugging the USB cable.
The USB board was recognized by my Linux install (Mepis 3.4.3), so nothing extra in the way of drivers was needed for Linux. I downloaded and installed the appropriate drivers under Windows and Mac without any issues. I plugged the GPS into my laptop with a USB cable and connected to it with a terminal program (4800 baud, 8N1), and immediately got a stream of NMEA sentences.
Next step was to convert the NMEA sentences to something more human-readable. The NMEA output looks something like this:
$GPGGA,000046.060,,,,,0,00,,,M,0.0,M,,0000*52 $GPGSA,A,1,,,,,,,,,,,,,,,*1E $GPRMC,000046.060,V,,,,,,,060305,,*2B $GPGGA,000047.046,,,,,0,00,,,M,0.0,M,,0000*57 $GPGSA,A,1,,,,,,,,,,,,,,,*1E $GPGSV,3,1,12,20,00,000,,10,00,000,,25,00,000,,27,00,000,*79 $GPGSV,3,2,12,03,00,000,,31,00,000,,24,00,000,,15,00,000,*78 $GPGSV,3,3,12,16,00,000,,05,00,000,,01,00,000,,26,00,000,*7D $GPRMC,000047.046,V,,,,,,,060305,,*2E $GPGGA,000048.046,,,,,0,00,,,M,0.0,M,,0000*58
The first field on each line denotes the NMEA sentance type, the rest of the fields contain data. Each line ends with a '*' followed by a 2 digit checksum code. The sample output above was taken before the GPS could get a 'fix', so most of the fields are empty. The module generates the various sentences almost continuously, so when you view it in a terminal program, it tends to scroll by pretty quickly.
I first tried interfacing it to TopoFusion, and found that this worked flawlessly. TopoFusion has a "live-tracking" mode that interprets the data from a NMEA-compatible GPS and display the longitude and latitude, as well as marking the position on a map. It doesn't interpret all of the NMEA data, however, and I wanted to write my own software so I could get more out of the data that is coming from the GPS module.
So, with the datasheet for the GPS module and a NMEA reference manual, I whipped up a crude Java program to display the NMEA output in a (somewhat) more readable form. The UI is extremely simple, just a bunch of text dropped into a JEditorPane. I get to see all of the output though, which is nice, things like how many GPS satellites are in view and how strong the signal is from each one of them.
After doing a little research on the net, I found that it was pretty easy to incorporate the GPS output into Google Earth by having my Java app generate a KML file. The trick to "real-time" updating of the Google Earth display is to use two KML files. The first one is re-written continuously by my Java app, and contains the longitude, latitude and other values related to the current location. The second KML file contains a "network link" to the first file. This second file never changes, but it tells Google Earth to reload the first file every two seconds. Opening the "network link" KML file in Google Earth causes it to then load the position file and update the current location every couple of seconds.
There is still some more work to be done on the Java app. The UI is ugly, and just barely usable. I would like to add some configuration options for the KML file to the interface. Also, the NMEA output contains some values for "Dilution of Precision", which I should be able to interpret to determine the accuracy of the current GPS fix.
Conclusion (We have a finished project!)
Overall I am quite pleased with this project. The hardware components we easy to assemble, and the software end of it should give me something to tinker with for a while. The GPS module locks on quickly and gives pretty accurate readings. If I take the GPS and my laptop out in the front yard, the position shown in Google Earth looks to be within about 10ft or less of where I'm actually standing. More experimentation will be needed to confirm this, but it looks to be at least as accurate as my Garmin, if not more so, and on average about as fast at acquiring a fix.
Bill of Materials
EM-406 GPS module (Spark Fun) -
$80 Now $60!
Extra interface cable (just in case) -- $2
CP2103 USB-to-Serial board (Spark Fun) -- $22
USB A to USB B cable (Spark Fun) -- $4
GRAY ABS BOX, 3.15" X 1.57" X 0.8"(All Electronics Corp) -- ~ $2
Total cost was about $105, plus shipping. With recent price changes, it would now be about $90!
(Rather crude) Java source code: Nmea2Kml-20090907.zip . This is just the proof-of-concept code, nothing special. If you're looking for something actually useful you may want to look for a full-fledged app like TopoFusion or Google Earth.