10 years, 3 months ago.

Get timestamp via GPS

Is it possible to get the timestamp via GPS for the C27-G35-0?

I've tried it with another library like MODGPS, but it seems not to be fit for the C027. https://mbed.org/cookbook/MODGPS

Thank you for your help in advance.

Question relating to:

support library for C027 helper functions for Buffer Pipes, Buffered Serial Port (rtos capable) and GPS parsing. It includes modem APIs for USSD, SMS and Sockets. C027, u-blox

1 Answer

10 years, 3 months ago.

Fairly easy. Turn on the GPS and parse the Serial data you are getting.

Look for a line starting with "$GPRMC," and then pull out the time and date fields.

The format is (not actually code but tagged as code used to keep the spaces and new lines):

$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A

Where:
     RMC          Recommended Minimum sentence C
     123519       Fix taken at 12:35:19 UTC
     A            Status A=active or V=Void.
     4807.038,N   Latitude 48 deg 07.038' N
     01131.000,E  Longitude 11 deg 31.000' E
     022.4        Speed over the ground in knots
     084.4        Track angle in degrees True
     230394       Date - 23rd of March 1994
     003.1,W      Magnetic Variation

See http://www.gpsinformation.org/dale/nmea.htm#nmea for more detail.

If you set an update rate faster than 1Hz then the time will have some decimal places for the fraction of the second e.g. 123519.100

Some fields may be blank or different lengths so count the commas to keep track of where you are in the line.

If you need more accurate time stamping then you need to use the PPS signal from the GPS. By first syncing to the GPS time and then increasing the PPS rate to 1kHz and counting pulses you can timestamp to the ms.

Accepted Answer

I've worked out this problem in two ways. See the second one under the comment "Alternative". However, you need a function that converts the timedate into a unix timestamp.

unsigned long unixTimestamp(int year, int month, int day,
              int hour, int min, int sec)
{
  const short days_since_beginning_of_year[12] = {0,31,59,90,120,151,181,212,243,273,304,334};
 
  int leap_years = ((year-1)-1968)/4
                  - ((year-1)-1900)/100
                  + ((year-1)-1600)/400;
 
  long days_since_1970 = (year-1970)*365 + leap_years
                      + days_since_beginning_of_year[month-1] + day-1;
 
  if ( (month>2) && (year%4==0 && (year%100!=0 || year%400==0)) )
    days_since_1970 += 1; /* +leap day, if year is a leap year */
 
  return sec + 60 * ( min + 60 * (hour + 24*days_since_1970) );
}

int main(void)
{
...
    while ((ret = gps.getMessage(buf, sizeof(buf))) > 0)
    {           
        int len = LENGTH(ret);

        //GET TIME & DATE
        if(strstr(buf,"$GPRMC"))
        {
            //GET TIME;
            char cGETtime[7];
            char cGETdate[7];
            memcpy( cGETtime, &buf[7], 6 );
            cGETtime[6] = '\0';

            int end = len;
            int pos = 14;
            int countcomma=1;
                        
            // GET DATE
            while ( pos < end )
            {                              
				if( buf[pos] == ','  )
					countcomma++;   

				if( countcomma == 9 )
				{
					pos++;
					memcpy( cGETdate, &buf[pos], 6 );
					cGETdate[6] = '\0';
					break;
				}
				pos++;
            }
            struct tm settm;

            settm.tm_hour = 10 * (cGETtime[0] - '0') + cGETtime[1] - '0'; // '0' = 30; '1' = 31 => e.g. cGETtime[0]= '1' => '1'-'0' = 31-30 = 1
            settm.tm_min  = 10 * (cGETtime[2] - '0') + cGETtime[3] - '0';
            settm.tm_sec  = 10 * (cGETtime[4] - '0') + cGETtime[5] - '0';

            settm.tm_mday  = 10 * (cGETdate[0] - '0') + cGETdate[1] - '0';
            settm.tm_mon   = 10 * (cGETdate[2] - '0') + cGETdate[3] - '0' -1; //0-11
            settm.tm_year  = 10 * (cGETdate[4] - '0') + cGETdate[5] - '0';
            settm.tm_isdst = -1;

            printf("Date: %02d:%02d:%02d %02d.%02d.%02d \r\n", settm.tm_hour, settm.tm_min,settm.tm_sec, settm.tm_mday, settm.tm_mon + 1, settm.tm_year);

            //----Alternative: GET TIME&DATE via getNmeaItem
            double dgetdate, dgettime;
            gps.getNmeaItem(9,buf,len,dgetdate);
            gps.getNmeaItem(1,buf,len,dgettime);
            printf("\r\n %f  %f \r\n",dgetdate,dgettime);
            //----

            //convert datetime to unix timestamp
            unsigned long ltime = unixTimestamp(settm.tm_year+2000,settm.tm_mon+1 ,settm.tm_mday, settm.tm_hour, settm.tm_min,settm.tm_sec);
            printf("timestamp: %u \r\n",ltime);
            }
	}	
...
posted by Abdurrahim Sevay 19 Sep 2014