Pirate Ship : GPS Experiments

From Bob's Basement

Jump to: navigation, search

GPS

I bought an extremely cheap USB GPS thingy from an eBay store (£25). I don't expect it to be great quality, but it'll do whilst I'm experimenting.

It's a UT-41 USB 12-Channel NMEA-0183 GPS Receiver, which I got from TekGems

I'm using Sabayon Linux and it seems that it has the correct modules already installed:

[11281.527000] usb 4-1: new full speed USB device using uhci_hcd and address 4

[11281.674000] usb 4-1: configuration #1 chosen from 1 choice

[11281.677000] pl2303 4-1:1.0: pl2303 converter detected

[11281.678000] usb 4-1: pl2303 converter now attached to ttyUSB0

I searched CPAN for a perl module to grab NMEA data, and found GPS::NMEA which looked promising. HOWEVER there is a problem with the one of the test scripts, namely connect.t

Here is the process I used to get the module installing properly

cpan> install GPS::NMEA
 - bla bla bla, FAIL!
cpan> look GPS::NMEA

You get a shell prompt in the distribution's directory.

cd t/
nano connect.t

On line 26 there is a problem. It doesn't specify what serial port to use. Change this:

eval {

    my $gps = GPS::Garmin->new(timeout => 1);

};

to

eval {

    my $gps = GPS::Garmin->new(Port => '/dev/ttyUSB0',timeout => 1);

};

One last thing! At the root prompt:

chmod 776 /dev/ttyUSB0

Now exiting back to the cpan prompt...

cpan> install GPS::NMEA

And it installs perfectly.

Using the following code snarfed from the CPAN page...

    #!/usr/bin/perl
    use GPS::NMEA;
    
    my $gps = GPS::NMEA->new(Port => '/dev/ttyUSB0',
                             Baud => 4800);
    while(1) {
        my($ns,$lat,$ew,$lon) = $gps->get_position;
        print "($ns,$lat,$ew,$lon)\n";
    }

You can output your GPS position. I modified it a bit so it would only output it when the position changes. As such:

    #!/usr/bin/perl
    use GPS::NMEA;
    
    my $gps = GPS::NMEA->new(Port => '/dev/ttyUSB0',
                             Baud => 4800);
    my @old_data = ();
    while(1) {
        my @data = $gps->get_position;
        if (@data != @old_data) {
             my($ns,$lat,$ew,$lon) = @data;
             print "($ns,$lat,$ew,$lon)\n";
             @old_data = @data;
         }
    }

This kinda works. I will post outputs of this code soon. From my preliminary tests, It places me at 51.369922N 0.455768W, which according to Google Maps is about 30 MILES away from my real position. I'm trying to work out what exactly the issue is - I have a feeling the format I'm outputting this in may be dodgey.

I also played with gpsd, which allows other apps to use the data. Unfortunately, I can't install Position as the distribution tarball has no config scripts and I can't be bothered to autoconf it up. There are other applications, like gpsdrive, which I've tried out. Unfortunately the maps are just too low res to come to any conclusions as to how accurate it may be.

I have a feeling when we implement this we'll use gpsd, as there are some nice C/C++ wrappers which makes life a lot easier.

gpsd

This is an odd one. Preliminaries, first...

# chmod 777 /dev/ttyUSB0
# ln -s /dev/ttyUSB0 /dev/gps

You need to do this every time you connect the device, or you cannot access it via gpsd or any other application for that matter.

If you don't do this, then gpsd will exit either straight away or when you connect to it - giving you no error whatsoever. Infuriating! To run gpsd in debug mode, you use the following:

$ gpsd -D 10 -F /dev/ttyUSB0
command line options:
  debug level:        10
  gps file name:      /dev/ttyUSB0
  file line timing:   0.200 sec
  gpsd port:          2947
  latitude:           3600.000N
  longitude:          -12300.000W

This is what will come up when the device does not have a fix. Checking with the hardware, I see a frequently blinking light - which according to the manual means it has a fix. gpsd, even with the highest debug level, is a shy thing. To get a bit more out of it, I strace it. This is much more useful, however gives a hell of a lot of output which I won't post here.

However it does give you debug information when you connect to it. I throw together a simple perl script (ensure that you get Net::GPSD installed with cpan first). Note that I have included the ability to start gpsd automatically from the script itself, but currently it's been commented out to aid debugging.

#!/usr/bin/perl
use warnings;
use strict;
use Net::GPSD;
use Data::Dumper;
$SIG{'INT'} = 'CLEANUP';
print "[+] Starting gpsd ...";
# my $gpsd = system("gpsd -F /dev/ttyUSB0");
# my $gpsd_proc =  $?;

# if ($gpsd == 0) { 
#       system("kill $gpsd_proc"); 
#       die("FAILED TO START GPSD");
#}
print "done\n";

my $obj=Net::GPSD->new() or die("No device!");
print "Starting loop\n";
        while (1) {
                my $point =  $obj->get();
                if (!$point->fix) { print "Waiting to get fix ...\n"; }
                while (!$point->fix) {
                        $point = $obj->get();
                        sleep(1);
                }
                print "\t".$point->latlon."\n";
                sleep(1);
        }

sub CLEANUP {
        print "[+] Killing gpsd ... ";
        # system("kill $gpsd_proc");
        print "done\n";
        exit(0);
}

Looking at gpsd, I get the following output:

1����6��6�f�v���&�F�v�YS6Vk
Unknown exception: "1����6��6�f�v���&�F�v�YS6Vk"
Lat: 0.000000 Lon: 0.000000 Alt: 0.000000 Sat: 0 Mod: 0 Time: 
$GPGGA,2034xx.00,5136.97xxx,N,00xx5.5xx8,W,1,04,05.0,00169.5,M,0046.4,M,,*4C
Lat: 51.61xxxx Lon: -0.75xxxx Alt: 169.500000 Sat: 4 Mod: 0 Time: 
$GPGSA,A,3,,,,06,14,07,,,,09,,,09.0,05.0,07.4*00

This isn't at all what I was looking for. However, in the debug information the Lat's and longs are correct. (I've obscured the values in the output for privacy reasons).

However, over in the perl script, it reports having no fix. This is odd. Even when I try to output the lats and longs when there is no (supposed) fix, I still get nothing. I have an feeling that perhaps Net::GPSD doesn't work properly on my system.

links

GPSD Hacking

Personal tools