I'm getting a lattitude from tinyGPS in this format: 4114474
How would I split it into something like this:
41
14
47
4
What kind of variable is the 4114474 in ?
Seeing your code would help a lot.
There are simple c-string and String parsing methods that can get the first two characters, second two characters, ect., and then convert the parsed characters into numbers for use if needed.
zoomkat:
There are simple c-string and String parsing methods that can get the first two characters, second two characters, ect., and then convert the parsed characters into numbers for use if needed.
Hey that's a good idea! I'll try it!
UKHeliBob:
What kind of variable is the 4114474 in ?
Seeing your code would help a lot.
It's "long" type.
long lat, lon; // Latitude, longitude for sattelite
char msgbuffer[40]="No GPS Data";
gps.get_position(&lat, &lon, &age);
printCoordinates();
void printCoordinates () {
long coord=lat;
char dr[2]; // East or West, North or Sounth
if (lat<0) dr[0]='S'; else dr[0]='N';
// if (lon<0) dr[0]='W'; else dr[0]='E';
if (coord<0) coord=abs(coord);
Serial.print (coord / 100000); Serial.print(dr[0]);Serial.print (" ");
Serial.print ( (coord / 1000) % 100); Serial.print ("' ");
Serial.print ( (coord/100)%10 );
Serial.print ( (coord/10)%10 );
Serial.print(".");
Serial.print ( (coord/1)%10 );
Serial.println ("\"");
snprintf(msgbuffer,sizeof(msgbuffer),"Longitude:%dN %d%d' %d%d.%d",lat / 100000,(lat/10000)%10,(lat/1000)%10,(lat/100)%10,(lat/10)%10,(lat/1)%10);
for (int i=0;i<sizeof(msgbuffer);i++) Serial.print (msgbuffer[i]);
}
Initial Serial.print statments seem to split it correctly, however I think that functions just ignores floating numbers, etc. becuase when I do snprintf it returns weird gibberish...
snprintf(msgbuffer,sizeof(msgbuffer),"Longitude:%dN %d%d' %d%d.%d",lat / 100000,(lat/10000)%10,(lat/1000)%10,(lat/100)%10,(lat/10)%10,(lat/1)%10);
for (int i=0;i<sizeof(msgbuffer);i++) Serial.print (msgbuffer[i]);
snprintf() has, if possible, populated a NULL-terminated array of chars (also known as a string). Why not print the string, rather than one character at a time?
You do not want to be printing the entire buffer, as you are now doing. You want to be printing only the portion that snprintf() actually wrote to. strlen() will tell you that.
bratan:
I'm getting a lattitude from tinyGPS in this format: 4114474
How would I split it into something like this:
41
14
47
4
What GPS module are you using?
Are you sure it's giving you Degrees-Minutes-Seconds (DMS)?
Mine spits out Degrees & Decimal Minutes (MinDec). It's just degrees and minutes in the following format: Latitude: DDMM.MMMM (The first two characters are the degrees.) Longitude: DDDMM.MMMM (The first three characters are the degrees.)
bratan:
I'm getting a lattitude from tinyGPS in this format: 4114474
How would I split it into something like this:
41
14
47
4
4114474 / 100000 = 41
4114474 % 100000 = 14474
14474 / 1000 = 14
14474 % 1000 = 474
474 / 10 = 47
474 % 10 = 4
Ahhh the wonders of integer match and the modulus operator.
PaulS:
snprintf(msgbuffer,sizeof(msgbuffer),"Longitude:%dN %d%d' %d%d.%d",lat / 100000,(lat/10000)%10,(lat/1000)%10,(lat/100)%10,(lat/10)%10,(lat/1)%10);
for (int i=0;i<sizeof(msgbuffer);i++) Serial.print (msgbuffer[i]);
snprintf() has, if possible, populated a NULL-terminated array of chars (also known as a string). Why not print the string, rather than one character at a time? You do not want to be printing the entire buffer, as you are now doing. You want to be printing only the portion that snprintf() actually wrote to. strlen() will tell you that.
There used to be a bug within Arduino when using strings, so I tried to avoid them as plague, but yeah I guess it's same thing Thanks for pointing it out!
1ChicagoDave:
What GPS module are you using?Are you sure it's giving you Degrees-Minutes-Seconds (DMS)?
Mine spits out Degrees & Decimal Minutes (MinDec). It's just degrees and minutes in the following format: Latitude: DDMM.MMMM (The first two characters are the degrees.) Longitude: DDDMM.MMMM (The first three characters are the degrees.)
Ok now you have me scratching my head I'm using Adafruit's ultimate GPS. But shouldn't all GPS spit out standard NMEA data? tinyGPS library is weird tho, it doesn't seem to output 100th decimal number which is crucial to exact position. I plugged numbers into to Google Maps and I think format is legict, but it found location which is about 25 miles away from my home...
For example gps.get_position(&lat, &lon, &age); will get lon=-7413240 which looks like -74°13'24.0" and indeed close to my location...
Arrch:
4114474 / 100000 = 41
4114474 % 100000 = 14474
14474 / 1000 = 14
14474 % 1000 = 474
474 / 10 = 47
474 % 10 = 4
Ahhh the wonders of integer match and the modulus operator.
Thanks man!
Adafruit Ultimate GPS is same one I have/use. The quote I posted was from learn.adafruit.com tutorial on how to use it.
Should check it out.
Shield-
Overview | Adafruit Ultimate GPS Logger Shield | Adafruit Learning System
Breakout -
Overview | Adafruit Ultimate GPS | Adafruit Learning System
They have library and sample sketches to parse GPS data, use built-in "LOCUS" data logger, etc...etc....
That is standard NMEA sentence structure --
Where a numeric latitude or longitude is given, the two digits immediately to the left of the decimal point are whole minutes, to the right are decimals of minutes, and the remaining digits to the left of the whole minutes are whole degrees.
eg. 4533.35 is 45 degrees and 33.35 minutes. ".35" of a minute is exactly 21 seconds.
eg. 16708.033 is 167 degrees and 8.033 minutes. ".033" of a minute is about 2 seconds.
another sample -
$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
Where:
GGA Global Positioning System Fix Data
123519 Fix taken at 12:35:19 UTC
4807.038,N Latitude 48 deg 07.038' N
01131.000,E Longitude 11 deg 31.000' E
1 Fix quality: 0 = invalid
1 = GPS fix (SPS)
2 = DGPS fix
3 = PPS fix
4 = Real Time Kinematic
5 = Float RTK
6 = estimated (dead reckoning) (2.3 feature)
7 = Manual input mode
8 = Simulation mode
08 Number of satellites being tracked
0.9 Horizontal dilution of position
545.4,M Altitude, Meters, above mean sea level
46.9,M Height of geoid (mean sea level) above WGS84
ellipsoid
(empty field) time in seconds since last DGPS update
(empty field) DGPS station ID number
*47 the checksum data, always begins with *
Good Luck!
It's a pretty impressive little nugget of technology! Have you read through the datasheet and PMTK command lists yet?
Right now I'm playing with the built-in logging, sleep mode timer, and PPS signal on fix to interact with sleeping Arduino & create a super low power GPS logger/tracker.
There used to be a bug within Arduino when using strings, so I tried to avoid them as plague, but yeah I guess it's same thing
No. The problem was with Strings - not the same thing as a string, by a long shot.
1ChicagoDave:
Adafruit Ultimate GPS is same one I have/use. The quote I posted was from learn.adafruit.com tutorial on how to use it.
Should check it out.
Shield-
Overview | Adafruit Ultimate GPS Logger Shield | Adafruit Learning System
Breakout -
Overview | Adafruit Ultimate GPS | Adafruit Learning SystemThey have library and sample sketches to parse GPS data, use built-in "LOCUS" data logger, etc...etc....
Hmm ok I see it now. You right NMEA format is different from what library is spitting out. You are using Adafruit's library, I'm using tinyGPS (because it was easier to get it working to set my clock with it and uses less RAM) so both have their own output format it seems.
Values returned by the core TinyGPS methods are integral. Angular latitude and longitude measurements, for example, are provided in units of 10-5 degrees, so instead of 90°30’00?, get_position() returns a longitude value of 9050000, or 90.5 degrees.
And I figured out what the problem was with snprint. I was splitting number correctly (not as elegantly as Arrch's method) but var values were getting lots when I called that function. Adding pointer "&" to the var name solved this
snprintf(msgbuffer,sizeof(msgbuffer),"Longitude:%dN %d%d' %d%d.%d",&lat / 100000,(lat/10000)%10,(&lat/1000)%10,(&lat/100)%10,(&lat/10)%10,(&lat/1)%10);
Adding pointer "&" to the var name solved this
No, it changed the output to garbage.
The correct format specifier for longs is not %d.
Values returned by the core TinyGPS methods are integral. Angular latitude and longitude measurements, for example, are provided in units of 10-5 degrees, so instead of 90°30’00?, get_position() returns a longitude value of 9050000, or 90.5 degrees.
Oh, okay. So it's giving you straight-up decimal degrees, then.
If you've got it figured out, sweet! I'm still gonna post the following to open up for critique &/or confirmation. ....and maybe help someone else?
To go from decimal degrees to Degrees Minutes Seconds given a decimal longitudinal coordinate such as -87.728055 the method is as follows:
First, subtract the whole number portion of the coordinate, leaving the fractional part.
The whole number is the number of degrees.
87.728055 = 87 degrees.
Then, multiply the remaining fractional part by 60.
This will produce a number of minutes in the whole number portion.
0.728055 x 60 = 43.6833 = 43 minutes.
Multiply the fractional part of the number of minutes by 60, producing a number of seconds.
0.6833 x 60 = 40.998 = 41 seconds.
(It is possible to just count this as 40 seconds by truncating the decimal, round it to 41, or keep the entire number.)
Depending on whether the source number was a latitudinal or longitudinal coordinate, and the sign of the number, add the N/S/E/W specifier.
The following shows the possibilities:
Type Dir. Sign Test
Lat. N + > 0
Lat. S - < 0
Long. E + > 0
Long. W - < 0
A latitude of 0°0?0? (The Equator) is neither North nor South. Similarly, a longitude of 0°0?0? (Prime Meridian) is neither East nor West. These are referred to as zero latitude and zero longitude, respectively.
A longitude of 180°0?0? (180th meridian) is neither East nor West. This is the basis for the International Date Line when referring to the Earth.
The final result is: W 87°43?41?.
Code might look something like this....?
(Pseudocode)
function deg_to_dms ( degfloat )
Input must be non-negative:
if degfloat < 0
error
end if
Compute degrees, minutes and seconds:
deg ? integerpart ( degfloat )
minfloat ? 60 * ( degfloat - deg )
min ? integerpart ( minfloat )
secfloat ? 60 * ( minfloat - min )
Round seconds to desired accuracy:
secfloat ? round( secfloat, digits )
After rounding, the seconds might become 60. These two
if-tests are not necessary if no rounding is done.
if secfloat = 60
min ? min + 1
secfloat ? 0
end if
if min = 60
deg ? deg + 1
min ? 0
end if
Return output:
return ( deg, min, secfloat )
end function