Let's Make Robots!

GPS and trying to move a decimal point

I have a GPS and am using the library NewSoftSerial. Using the example code, it prints the latitude and longitude in degrees, minutes and seconds but i want just degrees out to the normal 6 decimal places for the GPS. So i just printed the latitude to see what it comes out as. I get  281848348. But i need it to equal 28.184348 which would be the correct degrees. So i thought i would try and just multiply by E^-7 to move the decimal point. But that gives me 28.18 and gets rid of the rest. I am just trying to get the correct degrees out to the 6 decimal places. But i do not know how to shift this decimal place correctly it seems. Here is the code:

 

#include <NewSoftSerial.h>

 

NewSoftSerial mySerial =  NewSoftSerial(0, 1);

#define powerpin 4

 

#define GPSRATE 4800

//#define GPSRATE 38400

 

 

// GPS parser for 406a

#define BUFFSIZ 90 // plenty big

char buffer[BUFFSIZ];

char *parseptr;

char buffidx;

uint8_t hour, minute, second, year, month, date;

uint32_t latitude, longitude;

uint8_t groundspeed, trackangle;

char latdir, longdir;

char status;

 

void setup() 

  if (powerpin) {

    pinMode(powerpin, OUTPUT);

  }

  pinMode(13, OUTPUT);

  Serial.begin(GPSRATE);

  mySerial.begin(GPSRATE);

 

  // prints title with ending line break 

  Serial.println("GPS parser"); 

 

   digitalWrite(powerpin, LOW);         // pull low to turn on!

 

 

void loop() 

  uint32_t tmp;

 

  Serial.print("\n\rread: ");

  readline();

 

  // check if $GPRMC (global positioning fixed data)

  if (strncmp(buffer, "$GPRMC",6) == 0) {

 

    // hhmmss time data

    parseptr = buffer+7;

    tmp = parsedecimal(parseptr); 

    hour = tmp / 10000;

    minute = (tmp / 100) % 100;

    second = tmp % 100;

 

    parseptr = strchr(parseptr, ',') + 1;

    status = parseptr[0];

    parseptr += 2;

 

    // grab latitude & long data

    // latitude

    latitude = parsedecimal(parseptr);

 

    if (latitude != 0) {

      latitude *= 10000;

      parseptr = strchr(parseptr, '.')+1;

      latitude += parsedecimal(parseptr);

    }

    parseptr = strchr(parseptr, ',') + 1;

    // read latitude N/S data

    if (parseptr[0] != ',') {

      latdir = parseptr[0];

    }

 

    //Serial.println(latdir);

 

    // longitude

    parseptr = strchr(parseptr, ',')+1;

    longitude = parsedecimal(parseptr);

    if (longitude != 0) {

      longitude *= 10000;

      parseptr = strchr(parseptr, '.')+1;

      longitude += parsedecimal(parseptr);

    }

    parseptr = strchr(parseptr, ',')+1;

    // read longitude E/W data

    if (parseptr[0] != ',') {

      longdir = parseptr[0];

    }

 

 

    // groundspeed

    parseptr = strchr(parseptr, ',')+1;

    groundspeed = parsedecimal(parseptr);

 

    // track angle

    parseptr = strchr(parseptr, ',')+1;

    trackangle = parsedecimal(parseptr);

 

 

    // date

    parseptr = strchr(parseptr, ',')+1;

    tmp = parsedecimal(parseptr); 

    date = tmp / 10000;

    month = (tmp / 100) % 100;

    year = tmp % 100;

 

    Serial.print("\nTime: ");

    Serial.print(hour, DEC); Serial.print(':');

    Serial.print(minute, DEC); Serial.print(':');

    Serial.println(second, DEC);

    Serial.print("Date: ");

    Serial.print(month, DEC); Serial.print('/');

    Serial.print(date, DEC); Serial.print('/');

    Serial.println(year, DEC);

 

    Serial.print("Lat: "); 

    if (latdir == 'N')

       Serial.print('+');

    else if (latdir == 'S')

       Serial.print('-');

 

    Serial.print(latitude/10000000, DEC); Serial.print('\°', BYTE); Serial.print(' ');

    Serial.print((latitude/10000)%100, DEC); Serial.print('\''); Serial.print(' ');  

    Serial.print((latitude%10000)*6/1000, DEC); Serial.print('.');

    Serial.print(((latitude%10000)*6/10)%100, DEC); Serial.println('"');

 

  float latv= latitude*10E-7;  // here is where i move the decimal place but get 28.18

  Serial.println(latv);

  delay(500);

  Serial.print("Long: ");

    if (longdir == 'E')

       Serial.print('+');

    else if (longdir == 'W')

       Serial.print('-');

    Serial.print(longitude/10000000, DEC); Serial.print('\°', BYTE); Serial.print(' ');

    Serial.print((longitude/10000)%100, DEC); Serial.print('\''); Serial.print(' ');

    Serial.print((longitude%10000)*6/1000, DEC); Serial.print('.');

    Serial.print(((longitude%10000)*6/10)%100, DEC); Serial.println('"');

 

  }

  //Serial.println(buffer);

}

 

uint32_t parsedecimal(char *str) {

  uint32_t d = 0;

 

  while (str[0] != 0) {

   if ((str[0] > '9') || (str[0] < '0'))

     return d;

   d *= 10;

   d += str[0] - '0';

   str++;

  }

  return d;

}

 

void readline(void) {

  char c;

 

  buffidx = 0; // start at begninning

  while (1) {

      c=mySerial.read();

      if (c == -1)

        continue;

      Serial.print(c);

      if (c == '\n')

        continue;

      if ((buffidx == BUFFSIZ-1) || (c == '\r')) {

        buffer[buffidx] = 0;

        return;

      }

      buffer[buffidx++]= c;

  }

}

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Hi

Have you had a look at TinyGPS (a GPS/NMEA Parser) ?

http://arduiniana.org/libraries/TinyGPS/

 

yeah that is older. He created the newer NewSoftSerial. 

" Use NewSoftSerial for greater reliability"
I might make one of those reverse geocache boxes. 
According to the print reference, "Floats are similarly printed as ASCII digits, defaulting to two decimal places.".  You can specify the number of post-decimal point digits you want by adding an integer 2nd parameter.  So, for six decimal places, you'd use Serial.print(latv, 6);
yes just found that out last night....Now to find out why it is getting the wrong distance if since the GPS point is correct.

Your latitude is of type uint32_t, your latv is of type float.

I don't actually speak "Italian", but I'm guessing the float type does not allow for more significant numbers in your value than four: 18.28, that's four positions.

Maybe you should get yourself a bigger float-type.

Or stick with uint32_t (long 32 bit integers). Find the whole part of the number after the decimal point: 281848348 and take the 1848348 to mean "millionths of a degree" in the rest of your program.

For any value of latitude.

how do i get a bigger float type?

Anyone who does? Help the fella out here.

As I said, I don't speak the lingo. I'd have to read the manual. You'd better do that yourself. And then, say a year from now, you can teach me, when pass over into the dark side.

I don't even know if there is such a thing as "a bigger float".

8-)