I have a marine autopilot project I am converting to Teensy 3.6. Part of it is a GPS NMEA parser. I have what appears to be Teensy math error that I do not understand. Code and result are shown below. The subcode here converts Lat or Lon from a NMEA string to a floating point number. The sample given is String Lat_Lon_in = "10617.5254".
If you do this manually you get:
Degrees 106
Minutes 17
Decimal Minutes .5254
The floating point degrees should be 106 + 17/60.0 + .5254/60 =106.2920900, the code gives 106.29209137
I can't understand this result.
The code gives the following Printed result :
Lat_Lon String 10617.5254
Decimal 0.525400
minutes 17.000
Degrees 106.00000000
Decimal_Minutes 0.29209000
Lat_Lon_Deg 106.29209137
Answer should be 106.2920900
The code parses the pieces correctly but when it adds Degrees (106.0000) + Decimal_Minutes(.2920900) it gets 106.29209137 instead of 106.2920900.
If you do this manually you get:
Degrees 106
Minutes 17
Decimal Minutes .5254
The floating point degrees should be 106 + 17/60.0 + .5254/60 =106.2920900, the code gives 106.29209137
I can't understand this result.
The code gives the following Printed result :
Lat_Lon String 10617.5254
Decimal 0.525400
minutes 17.000
Degrees 106.00000000
Decimal_Minutes 0.29209000
Lat_Lon_Deg 106.29209137
Answer should be 106.2920900
The code parses the pieces correctly but when it adds Degrees (106.0000) + Decimal_Minutes(.2920900) it gets 106.29209137 instead of 106.2920900.
Code:
String Lat_Lon_in = "10617.5254";
String Lat_Lon;
String string1;
float float1;
char char_buf[16];
float Lat_Lon_Deg;
unsigned long long1;
char *brkb, *pEnd;
void setup() {
Serial.begin(57600);
Serial.println("Setup ");
}
void loop() {
To_Degrees(Lat_Lon_in);
delay(10000);
}
void To_Degrees(String Lat_Lon)
{
// NOTE ASSUMES NORTH LATITUDE AND WEST LOGITUDE ARE POSITIVE NEED TO ADD HANDLING FOR SOUTH LATITUDE AND EAST LOGITUDE (treat them as negative
float Degrees;
float Minutes;
float Decimal;
float Decimal_Minutes;
int N1;
// if LatLon_decimals is 0 in user input this will auto detect number of decimals or manually set the number of decimals in user input
//if(LatLon_decimals == 0 && Detect_LatLon_decimals == 0){
N1 = Lat_Lon.length() - Lat_Lon.indexOf('.') -1;
// N1 = 4;
//Detect_LatLon_decimals = 1; This is used to only detect number of decimals once to save time
//}
//else N1 = LatLon_decimals; //
//Serial.print("number of decimals = "); Serial.println(N1);
//int N1 = 4; // number of characters after decimal (precision of lat lon sentence
int N2 = N1+1; // length - n2 is position after ending position for minutes counting the first position as 0 = N1 + 1
int N3 = N1+3; // lenghth - n3 is starting position for minutes = N1 + 3
int N4 = pow(10,N1); // divisor for decimal part of minutes to convert interger to decimal = 10^N1
// Lat/Lon have form dddmm.pppp(p, ddd is degrees (1 to 3 characters, mm is min, and ppp(p) is decimal minutes 3 o 4 characters
//for (int i=0;i<16;i++) char_buf[i]=' ';
Serial.print("Lat_Lon String "); Serial.println(Lat_Lon);
string1 = Lat_Lon.substring(Lat_Lon.length() - N1);// decimal part of Lat Lonchar_buf[] = "";
string1.toCharArray(char_buf,16);
long1 = strtol(char_buf,&pEnd,10);
Decimal = float(long1)/N4; // convert integer to decimal
Serial.print("Decimal "); Serial.println(Decimal,6);
string1 = Lat_Lon.substring(Lat_Lon.length()-N3, Lat_Lon.length()-N2); // gets minutes Note start is inclusive, stop is exclusive (position it stops before) see arduino substring
string1.toCharArray(char_buf,16);
long1 = strtol(char_buf,&pEnd,10);
Minutes = float(long1);
Serial.print("minutes "); Serial.println(Minutes,3);
string1 = Lat_Lon.substring(0, Lat_Lon.length()-N3); // gets degrees
string1.toCharArray(char_buf,16);
long1 = strtol(char_buf,&pEnd,10);
Degrees = float(long1);
Serial.print("Degrees "); Serial.println(Degrees,8);
Decimal_Minutes = Minutes/60.0 + Decimal/60.0;
Serial.print("Decimal_Minutes ");Serial.println(Decimal_Minutes,8);
//Lat_Lon_Deg = Degrees + Minutes/60.0 + Decimal/60.0;
Lat_Lon_Deg = 0.0;
Lat_Lon_Deg = Degrees + Decimal_Minutes;
Serial.print("Lat_Lon_Deg "); Serial.println(Lat_Lon_Deg,8);
Serial.println("Answer should be 106.2920900");
Serial.println();
} // end To_Degrees