Gps Coordinate conversion help

Hi guys,

A bit of background info: i've made a information display unit for my 4 wheel drive, that displays among other things, Latitude and Longitude in decimal degrees, Eg, -36.76453, 145.74653.. but i if need to convert this info to Degrees, Minutes, Seconds, eg -36° 76' 53, 145° 74' 53. i know i need to do some maths, here's and example i found

DM.m = Degrees, Minutes, Decimal Minutes (eg. 45°22.6333)
D.d = Degrees, Decimal Degrees (eg. 45.3772°)
DMS = Degrees, Minutes, Seconds (eg. 45°22'38")

D.d --> DM.m (45.3772 --> 45°22.6333
Multiply .d by 60 to get M.m (.3772*60=22.6333)

DM.m --> DMS (45°22.6333 --> 45°22'38")
Multiply .m by 60 to get S(.6333*60=38)

and here is my sketch.

// necessary libraries
#include <TinyGPS.h> //GPS
#include <LiquidCrystal.h>
#include <OneWire.h> //for temp sensor
#include <Wire.h>
#include <LSM303DLH.h> //compass
#include <DHT.h> //temp humidity sensor

#define DHTPIN 30 // DHT sensor pin
#define DHTTYPE DHT22 // DHT 22 (AM2302)
DHT dht(DHTPIN, DHTTYPE);

LSM303DLH compass;

const int heading_min = 0; // sensor minimum,
const int heading_max = 359;

// The parameters in the brackets define which digital output pins connect to
// (in order) LCD pins: RS, enable, D4, D5, D6, and D7.
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
LiquidCrystal lcd2(12, 10, 5, 4, 3, 2); //second display

//---------------------------GPS------------------------------------------------------
#define GPSBAUD 9600 // baud rate of our GPS module. Change for your GPS module if different
TinyGPS gps; // Create an instance of the TinyGPS object
void getgps(TinyGPS &gps); // This is where you declare prototypes for the functions that will be
// using the TinyGPS library.

// -------------------------BATTERY VOLTAGE --------------------------------------------

int batteryPin = A0; // analog pin 0
int battery2Pin = A1;

int BattanalogIn = A2;
float BattsensorValue;
float BattoutputValue;

const float referenceVolts = 5; // the default reference on a 5-volt board
const float resistorFactor = 327; // 327 = 1023 x r2 / (r1+r2) r1 = 10000ohm r2 = 4700ohm

// --------------------------Outside temp sensor --------------------------------------------------
int DS18S20_Pin = 22; //DS18S20 Signal pin on digital 22
OneWire ds(DS18S20_Pin); // on digital pin 22

void setup()
{

dht.begin();

Wire.begin();

compass.enableDefault();

// Calibration values. Use the Calibrate example program to get the values for
// your compass.
compass.m_min.x = -1038; compass.m_min.y = -831; compass.m_min.z = -662;
compass.m_max.x = +639; compass.m_max.y = +797; compass.m_max.z = 837;

Serial1.begin(GPSBAUD); // setup sketch for data output speed of GPS module

lcd.begin(20, 4);
lcd2.begin(20, 4);

lcd.clear();
//lcd2.clear();

lcd.setCursor(2,1);
lcd.print("Waiting for lock");

}

void loop()

{

GPS_LOC ( );
Batt_V_I ( );
OutTemp ( );
Compass ( );
TempHumidSensor ( );

}

int GPS_LOC( )

{

while(Serial1.available()) // While there is data on the RX pin...
{
int c = Serial1.read(); // load the data into a variable...
if(gps.encode(c)) // if there is a new valid sentence...

{
getgps(gps); // then grab the data.
}
}
}

void getgps(TinyGPS &gps) // The getgps function will get and print the values we want.

{

float latitude, longitude, fix_age; // Define the variables that will be used

gps.f_get_position(&latitude, &longitude); // You can now print variables latitude and longitude

lcd.clear();

lcd.setCursor(0,0);
lcd.print("Latitude : "); lcd.print(latitude,5);

lcd.setCursor(0,1);
lcd.print("Longitude: "); lcd.print(longitude,5);

lcd.setCursor(0,2);
lcd.print("Altitude : ");
lcd.print(gps.f_altitude());lcd.print("m");

lcd.setCursor(0,3);
lcd.print("Speed: ");
lcd.print(gps.f_speed_kmph(),0); //lcd.print("k");

lcd.setCursor(11,3);
lcd.print("Sats: ");
lcd.print(gps.satellites());

//Serial.print("HDOP: "); Serial.println(gps.hdop());

}

(had to delete some of my sketch to make it fit in this post)

Thanks for helping!

I guess you wanna know how to do that in C (although you actually didn't ask a question).

float long = 45.124783;
int deglong = long;
long -= deglong; // remove the degrees from the calculation
long *= 60; // convert to minutes
int minlong = long;
long -= minlong; // remove the minuts from the calculation
long *= 60; // convert to seconds

This is what you've written in your math section converted to C code.

GPS data convert from DD.DDDDD to DD MM SS.SS

void loop()
{
.
.
.

int DD,MM;
double SS;
DD_DDDDDtoDDMMSS(gps.location.lat() , &DD, &MM, &SS );

Serial.println(DD);
Serial.println(MM);
Serial.println(SS,7);

}




//моя функци перевода из DD_DDDDD  в  DD_MM_SS
void DD_DDDDDtoDDMMSS( double DD_DDDDD , int *DD, int *MM, double *SS )
{    

 *DD=(int)DD_DDDDD;//сделали из 37.45545 это 37 т.е. Градусы
 *MM=(int)((DD_DDDDD - *DD)*60);//получили минуты
 *SS=((DD_DDDDD - *DD)*60-*MM)*60;//получили секунды
}

Just for fun, I converted your sketch to use my NeoGPS library (see below). NeoGPS has built-in support for lat/lon in integer, float and the Degrees/Minutes/Seconds form you are asking about. This displays the lat/lon in DMS instead of a floating-point number:

// necessary libraries
#include "NMEAGPS.h"
#include <LiquidCrystal.h>
#include <OneWire.h> //for temp sensor
#include <Wire.h>
#include <LSM303.h> //compass
#include <DHT.h> //temp humidity sensor


#define DHTPIN 30   // DHT sensor pin
#define DHTTYPE DHT22   // DHT 22  (AM2302)
DHT dht(DHTPIN, DHTTYPE);


LSM303 compass;


const int heading_min = 0;      // sensor minimum, 
const int heading_max = 359;


// The parameters in the brackets define which digital output pins connect to 
// (in order) LCD pins: RS, enable, D4, D5, D6, and D7.
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
LiquidCrystal lcd2(12, 10, 5, 4, 3, 2);  //second display

//---------------------------GPS------------------------------------------------------
#define GPSBAUD 9600 // baud rate of our GPS module. Change for your GPS module if different
NMEAGPS gps;  // Create an instance of the GPS object
void getgps(NMEAGPS &gps);   // This is where you declare prototypes for the functions that will be 
                            // using the GPS library.




// -------------------------BATTERY VOLTAGE --------------------------------------------

int batteryPin = A0; // analog pin 0
int battery2Pin = A1; 

int BattanalogIn = A2;
float BattsensorValue; 
float BattoutputValue; 


const float referenceVolts = 5;   // the default reference on a 5-volt board
const float resistorFactor = 327;  // 327 = 1023 x r2 / (r1+r2)  r1 = 10000ohm   r2 = 4700ohm



// --------------------------Outside temp sensor --------------------------------------------------
int DS18S20_Pin = 22; //DS18S20 Signal pin on digital 22
OneWire ds(DS18S20_Pin);  // on digital pin 22



void setup()
{
 dht.begin();
 
 Wire.begin();
 
 compass.enableDefault();
 
 // Calibration values. Use the Calibrate example program to get the values for
 // your compass.
 compass.m_min.x = -1038; compass.m_min.y = -831; compass.m_min.z = -662;
 compass.m_max.x = +639; compass.m_max.y = +797; compass.m_max.z = 837;

 
 
 
 Serial1.begin(GPSBAUD); // setup sketch for data output speed of GPS module
   
 
 lcd.begin(20, 4);
 lcd2.begin(20, 4);                                                      

 lcd.clear();
 //lcd2.clear();

 lcd.setCursor(2,1);
 lcd.print( F("Waiting for lock") );


}


void loop()

{

 
GPS_LOC ( );
//Batt_V_I ( );
//OutTemp ( );
//Compass ( );
//TempHumidSensor ( );


}

int GPS_LOC( )

{
 if (gps.available( Serial1 )) {
   getgps(gps);  // then grab the data.
 }
}

void getgps( NMEAGPS &gps )   // The getgps function will get and print the values we want.

{
 float latitude, longitude, fix_age;   // Define the variables that will be used
 
 gps_fix fix = gps.read();
 

 lcd.clear();
 
 lcd.setCursor(0,0);
 lcd.print( F("Latitude : ") );
 if (fix.valid.location) {
   //lcd.print( fix.latitude(), 5 );
   
   // Print degrees minutes seconds.123
   lcd << fix.latitudeDMS;
   lcd.print( fix.latitudeDMS.NS() );
 }   
 
 lcd.setCursor(0,1); 
 lcd.print( F("Longitude: ") );
 if (fix.valid.location) {
   //lcd.print( fix.longitude(), 5 ); 

   // Print degrees minutes seconds.123
   lcd << fix.longitudeDMS;
   lcd.print( fix.longitudeDMS.EW() );
 }
 
 lcd.setCursor(0,2);
 lcd.print( F("Altitude : ") );
 if (fix.valid.altitude) {
   lcd.print( fix.altitude() );
   lcd.print('m');
 }
 
 lcd.setCursor(0,3);
 lcd.print( F("Speed: ") );
 if (fix.valid.speed) {
   lcd.print( fix.speed_kph(), 0 );
   //lcd.print( F("kph") );
 }
 
 lcd.setCursor(11,3); 
 lcd.print( F("Sats: ") );
 if (fix.valid.satellites)
   lcd.print( fix.satellites ); 
 
 //Serial.print("HDOP: ");
 //if (fix.valid.hdop)   
   //Serial.println(fix.hdop);

  
}

The two sketch sizes:

**Program ** **RAM **
Original 10484 789
NeoGPS 10960 620

It uses 476 bytes more program space, but 169 fewer bytes of RAM. I think you also find that the LCD doesn't flicker (if it was), and it updates exactly once per second.

Sometimes, adding your other tasks in causes you to start losing GPS data. If that happens (or was happening), this sketch will be more immune to that. If it still happens, you can drop in the NeoHWSerial library and handle the GPS characters in an interrupt. See the Troubleshooting page for more info.

If you'd like to try it, follow the Install instructions, and uncomment these in GPSfix_cfg.h to enable the DMS form:

#define GPS_FIX_LOCATION_DMS
#define GPS_FIX_ALTITUDE
#define GPS_FIX_SPEED
#define GPS_FIX_SATELLITES

Everything should be commented out, unless you want additional pieces.

Also uncomment this in NMEAGPS_cfg.h:

    #define NMEAGPS_PARSING_SCRATCHPAD

It's required for the DMS option.

BTW, you are using the old LSM303DLH, which has been deprecated. You should probably use the newer LSM303 library instead.

Cheers,
/dev

I just noticed a compiler bug, so you may need to download the latest NeoGPS if your Latitude shows as SOUTH when you're actually NORTH.

Cheers,
/dev