RSS feed

Linkedin Profile

Tags:
economy
programming
seattle
things that bug me
wall art

Posts by month: 12/08 (2)
10/08 (2)
08/08 (1)
06/08 (2)
05/08 (1)
03/08 (3)
02/08 (1)
01/08 (2)
12/07 (2)
11/07 (1)
07/07 (1)
05/07 (2)
02/07 (1)
01/07 (1)
12/06 (1)
11/06 (1)
10/06 (1)
08/06 (1)
07/06 (1)
06/06 (2)
05/06 (1)
04/06 (2)
02/06 (1)
01/06 (2)
12/05 (3)
11/05 (2)
09/05 (5)
08/05 (5)
07/05 (7)
06/05 (3)
05/05 (6)
04/05 (8)
03/05 (7)
02/05 (7)
01/05 (6)
12/04 (2)
11/04 (3)
10/04 (5)
09/04 (3)
08/04 (5)
07/04 (5)
06/04 (4)
05/04 (4)
04/04 (9)
03/04 (4)
02/04 (3)
01/04 (5)
12/03 (1)
11/03 (14)
10/03 (8)


GPS Code
2008-06-25

As promised, here is source code for reading GPS data from the Streets and Trips USB GPS on OS X. This is the most C code I have written in a while, so don't go putting it into production!

Here's how it works:

nmea.h/.c - Structs representing nmea data, and code for reading data from the serial port, and parsing this out of a comma separated string. I have restricted myself to only parsing bits of the gga sentence, but it would be straightforward to extend this to other data and sentences.

serial.h/.c - Code for opening and closing the serial port.

main.c - A small main method that reads the nmea data and prints the lat, long and altitude to the console.

If you want to try it out, don't forget to install the serial port driver as described in my previous post. Have fun with it!

Tags: programming


GPS on Leopard
2008-06-09

A while back I bought Microsoft Streets and Trips 2007 from the company store, and got a nice, small USB GPS with it. I messed around programming the GPS on Windows (post) and hooked it into my blog, but then I moved over to a Mac running Leopard as my daily machine and lost my neat GPS recording capability. No more! On Sunday I hacked together some code to pull data from the GPS on OS X.

nmea print out.

I found a few posts from people trying to do the same thing, so I am going to outline the steps involved now, and show some code in a later post.

1. USB to Serial - The GPS device uses the RS232 serial standard over USB. This won't appear as a serial device without the right driver, so download the BF-810 USB to Serial adapter from here and install it.

2. Vendor and Product ID - The driver installed in step 1 needs some tweaks before it will work, and to make those tweaks you need to know two numbers: The vendor and product IDs. Plug in the GPS and fire up IORegistryExplorer, and then look under IOUSB group (command-6) for the GPS. It will be the entry with USB Vendor Name = Prolific Technology Inc. If you are lazy like me you can also find it by yanking the GPS out of the machine and watching it go red in the explorer. Note that the values here are in hex, so it is a great opportunity to dust off your hex to decimal skills.

3. Edit kext - Plug the vendor and product IDs for your device into the kernel extension Info.plist file /System/Library/Extensions/ProlificUsbSerial.kext/Contents/Info.plist. This is just a plain old xml file, so sudo fire up your editor of choice and replace whatever values are there under idProduct and idVendor with your own.

4. Reload kext - With our product and vendor IDs in place, it is now time to reload the driver. First up, run "sudo kextunload -b com.prolific.driver.PL2303". It is ok if this unload command fails. Now run "sudo kextload -b com.prolific.driver.PL2303". Provided the device is plugged in, you should now be able to see a device file called cu.usbserial in the /dev directory on your file system (ls /dev/cu*).

5. Time to code - Apple has a useful serial programming in C tutorial here. The demo accesses a modem, but the code only needs a few tweaks to pull NMEA data off the GPS. I started by stealing swathes of the demo and hacking on them to re-target it at the GPS. The important changes are:

5.1 Discovery - There is no need to discover the device dynamically, just hard code the device path and get rid of a couple of hundred lines of code right away:

	char* gpsPath = "/dev/cu.usbserial"; 
	fileDescriptor = OpenSerialPort(gpsPath);

5.2 Config - The device is configured using the termios structure, and you'll need this to get the baud, parity, stop bits and word size right:

	cfsetspeed(&options, B4800); 
	options.c_cflag &= ~PARENB;
	options.c_cflag &= ~CSTOPB;
	options.c_cflag &= ~CSIZE;
	options.c_cflag |= CS8;

5.3 Reading data and NMEA parsing - Data isn't read back from the device in a predictable sequence, so you will need to scan the input as it is read and work out when the sequence starts. Luckily the NMEA data structure is simple to parse: every line starts with a $, holds some comma separated values, and ends with a checksum. Parse away!

Tags: programming

Back to weblog