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.

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-)

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.

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.