SparkFun Forums 

Where electronics enthusiasts find answers.

Tips and questions relating to the GPS modules from SFE
By mg
#15110
I've just received this datalogger and found that the co-ordinates it generates for Google Earth (KML mode) are not correct.

I'm located in London, UK. I did a walking/bus round trip for about 2-3 miles. Removed the 0,0,0 entries from the resulting output file and wrapped them up in a KML header/footer:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.0">
<Placemark>
<name>Name</name>
<description>Description</description>
<Style>
<LineStyle>
<width>4</width>
</LineStyle>
</Style>
<LineString>
<tessellate>1</tessellate>
<coordinates>
...
0.1974166631699,51.5142326354980,23
0.1974233388901,51.5142364501953,23
0.1974299997091,51.5142364501953,23
0.1974366605282,51.5142364501953,22
0.1974416673183,51.5142402648926,22
...
</coordinates>
</LineString>
</Placemark>
</kml>

It turns out that the sign of the longitude is incorrect. Those numbers should be -0.19. When I change this in a text editor, the resulting path is correct. Otherwise, the path is mirror imaged across longitude 0.

Can anyone else confirm this behaviour?

M
User avatar
By ohararp
#15114
Sounds like the code is assuming that the data logger is destined for north america and is ignoring the N,S and E,W values in the nmea sentence. I cannot confirm this (being that I live in the us) but imagine that this is the problem. Global economy nowadays isn't it.
Last edited by ohararp on Thu Jun 29, 2006 3:51 am, edited 1 time in total.
By mg
#15119
I'll try NMEA and do the conversion with an external tool.

I'd pay a small fee for anyone who can take the existing firmware and solve this problem and enhance the power-saving features.
By matthev
#15256
mg wrote:I've just received this datalogger and found that the co-ordinates it generates for Google Earth (KML mode) are not correct.

I'm located in London, UK. I did a walking/bus round trip for about 2-3 miles. Removed the 0,0,0 entries from the resulting output file and wrapped them up in a KML header/footer:

<KML STUFF>

It turns out that the sign of the longitude is incorrect. Those numbers should be -0.19. When I change this in a text editor, the resulting path is correct. Otherwise, the path is mirror imaged across longitude 0.

Can anyone else confirm this behaviour?

M

I just analyzed the code. You've discovered a bug specific to your longitude (this would also affect negative equatorial regions).

Here's the code from the logger firmware that does the KML conversion for latitude (same thing applies to longitude):


//latitude
for (x = 0; x < 7; x++)
{
temp2[x] = lat[mark1 - 2 + x];
lat[mark1 - 2 + x] = 0;
}

q = atof(temp2)/60; //minutes
r = atof(lat); //degrees

if (r < 0) r -= q; //check for negative degrees is invalid from
//0 to -1 (anything between the two).
//This is because "-0" is not < 0.
else r += q;
//r=latitude



The easiest firmware fix would be to store the flag for N/S and E/W, then apply it at the end:
r += q;
if(NS_Flag == -1) r=0-r;

SFE Guys, can you fix your bug?

-Matt

PS: No fix fee required. And Sparkfun did pay attention to the N/S E/W flags, they just didn't do enough boundary checking!
By matthev
#15345
I don't see a way to add a file to the post, so I've just copied and pasted the updated code for the affected function from the firmware file. This should replace the function by the same name in the SFE firmware. The whole project will need to be recompiled and loaded into the GPS logger.

I also added comments so others could understand the code a bit better.

-Matt
Code: Select all
void get_GPS_KML(void)
{
    float q = 0, r = 0, s = 0;
    int x, y, z;
    char temp;
    char temp2[7];
    char north = 0, west = 0;
    char lat[10], lon[11], alt[5];
    char mark1 = 0, mark2 = 0;

    for (x = 0; x < 160; x++)    //zero the arrays
    {
        GPS_short[x] = 0;
        
        if (x < 11) 	lon[x] = 0;
        if (x < 10) 	lat[x] = 0;
        if (x < 5) 		alt[x] = 0;
    }
    
    U1FCR = 0x02;

    while(1)
    {
        temp = getc2();

//this is the GPS message that's being converted:
//$GPGGA,hhmmss.ss,ddmm.mmmmm,s,dddmm.mmmmm,s,n,qq,pp.p,±aaaaa.aa,M,±xxxx.xx,M,sss,aaaa *cc<CR><LF>
//sync   UTC	   Latitude     Longitude   			Altitude
//							  N/S			E/W

        if (temp == '$')
        {
            temp = getc2(); //'G'
            temp = getc2(); //'P'
            temp = getc2(); //'G'

            if (temp == 'G')
            {
                temp = getc2(); //'G'
                temp = getc2(); //'A'
                temp = getc2(); //','
                temp = getc2(); //start of UTC

                if (temp != ',') //if there's real data (if there's a GPS lock?)
                {
                    stat0_on();
                    temp = 0;

                    y = 0;
                    x = 0;

                    while (x < 9)
                    {
                        temp = getc2();

                        if (temp == ',') //"Clear out data" Mode (scrolls past UTC data etc.)
                        {
                            x++;
                            y = 0;
                            temp = getc2();
                        }
                        
                        
                        if (x == 1) //Latitude Mode
                        {
                            lat[y] = temp;
                            if (temp == '.') mark1 = y;
                            y++;

                        }
                        
                        
                        if (x == 2) //North/South Mode
                        {
                            north = temp; //setting the North/South flag
                            y++;
                        }

                        if (x == 3)  //Longitude Mode
                        {
                            lon[y] = temp;
                            if (temp == '.') mark2 = y;
                            y++;
                        }
                        
                        
                        if (x == 4)  //East/West Mode
                        {
							west = temp;  //setting the East/West flag
                            y++;
                        }
                        
                        
                        if (x == 8)   //Altitude mode
                        {
                            alt[y] = temp;
                            y++;
                        }
                        

                    }

                    break;
                }
            }
        }
    }
    
    for (x = 0; x < 8; x++)   //convert latitude to two strings (degrees and minutes)
    {
        temp2[x] = lat[mark1 - 2 + x]; //move minutes data to new string
        lat[mark1 - 2 + x] = 0; //clear minutes data out of degrees string
    }
    
    //change strings to floats
    q = atof(temp2)/60; //minutes
    r = atof(lat);           //degrees

    r += q; //combined latitude (all degrees with decimal)
    
    if(north == 'S'){ 
    	r = 0 - r; //if south, make latitude negative
    }

    for (x = 0; x < 8; x++)   //convert longitude to two strings (degrees and minutes)
    {
        temp2[x] = lon[mark2 - 2 + x]; //move minutes data to new string
        lon[mark2 - 2 + x] = 0; //clear minutes data out of degrees string
    }

	//change strings to floats
    q = atof(temp2)/60; //minutes
    s = atof(lon);   //degrees

	s += q;
	
	if(west == 'W'){    
		s = 0-s; //if west, make longitude negative
	}
		
	//convert altitude string to integer
    x = atoi(alt);

    sprintf(GPS_short,"%3.13f,%3.13f,%d \r\n",s,r,x);
}
By Pete-O
#15416
Nice catch, dude! Hey, I never claimed to be a "good" programmer...I'll be looking it over more closely in the next 24 hours and I'll make sure that the next batch of loggers go out with the fix.

Thanks for pulling my bacon out of the fire!

Pete