FONA 808 - extract UTC time

Adafruit cellular platform - SMS and IoT over celluar

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
SalviX
 
Posts: 18
Joined: Mon Nov 23, 2015 12:22 pm

FONA 808 - extract UTC time

Post by SalviX »

Hi All,

I am working with FONA808 and Arduino UNO rev 3 (and a number of sensors).
Anybody knows how to extract the UTC time from FONA 808 GPS data (yyymmddHHMMSS --ms not needed) ? This can be used as a timestamp for logging data.

I slightly modified the library (both Adafruit_FONA.h and Adafruit_FONA.cpp) to make this command possible:

Code: Select all

float latitude, longitude, speed_kph, heading, timestamp, altitude;
fona.getGPS(&latitude, &longitude, &speed_kph, &heading, &timestamp, &altitude);
but timestamp variable is always ovf

Any suggestion is most welcomed. Thank you

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: FONA 808 - extract UTC time

Post by adafruit_support_rick »

How are you converting the timestamp to a float? There certainly aren't enough bits in a float for the timestamp, so you'll be losing precision. Your conversion routine is probably overflowing.

User avatar
SalviX
 
Posts: 18
Joined: Mon Nov 23, 2015 12:22 pm

Re: FONA 808 - extract UTC time

Post by SalviX »

I see.
That is what I changed in Adafruit_FONA.cpp

Code: Select all

// grab date & time
    char *ts = strtok(NULL, ",");
    if (! ts) return false;
    *timestamp = atof(ts);
and this is what I modified in Adafruit_FONA.h

Code: Select all

// GPS handling
  boolean enableGPS(boolean onoff);
  int8_t GPSstatus(void);
  uint8_t getGPS(uint8_t arg, char *buffer, uint8_t maxbuff);
  boolean getGPS(float *lat, float *lon, float *speed_kph=0, float *heading=0, float *timestamp=0, float *altitude=0);
  boolean enableGPSNMEA(uint8_t nmea);
Would you suggest that I drop the float and replace it by unsigned long (in my sketch as well) ?

User avatar
SalviX
 
Posts: 18
Joined: Mon Nov 23, 2015 12:22 pm

Re: FONA 808 - extract UTC time

Post by SalviX »

I just tried to change the *timestamp = atof(ts); into *timestamp = atol(ts); in the Adafruit_FONA.cpp. But I have no idea what to modify in the corresponding Adafruit_FONA.h to make it work. Ant suggestion ? Thank you in advance

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: FONA 808 - extract UTC time

Post by adafruit_support_rick »

You're going about this the wrong way. Even a long is not long enough for yyymmddhhmmss. A long is only 10 digits.

What you want to do is
a) get a function that will turn yyyymmddhhmmss into a 32-bit unix time. or
b) store the actual string in your log file.

I think the Time library will do the former, but you'll still have to pull the string apart and format it properly. I would opt for the latter.

User avatar
SalviX
 
Posts: 18
Joined: Mon Nov 23, 2015 12:22 pm

Re: FONA 808 - extract UTC time

Post by SalviX »

Thank you.
Storing the string in the log file is more than enough. Then I can always use any text editor to clean the txt log file.

Please could you explain how to extract UTC time as a string (I'm quite new to all of this and struggling a lot with the .cpp and .h library files...!)

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: FONA 808 - extract UTC time

Post by adafruit_support_rick »

Sure. You're already using strtok, so all you have to do is copy the string pointer from strtok to a string argument to your function.

Code: Select all

#define TS_LENGTH 16

char timestamp[TS_LENGTH] = "";

if (getGPS(&lat, &long, &speed_kph, &heading, timestamp, &altitude))
{
   ... etc ...
}

Code: Select all

  boolean getGPS(float *lat, float *lon, float *speed_kph=0, float *heading=0, char *timestamp="", float *altitude=0)
{
. . . etc. . .

// grab date & time
    char *ts = strtok(NULL, ",");
    if (! ts) return false;
    strncpy(ts, timestamp, TS_LENGTH-1);
. . .etc . . .
}

User avatar
SalviX
 
Posts: 18
Joined: Mon Nov 23, 2015 12:22 pm

Re: FONA 808 - extract UTC time

Post by SalviX »

Thank you so much.
I'll try this later today and will keep you posted

User avatar
MG_123
 
Posts: 6
Joined: Wed Sep 12, 2018 8:00 am

Re: FONA 808 - extract UTC time

Post by MG_123 »

Hello!

I've been working on this problem for a few days and haven't found a solution after much frustration. I'm attempting to modify the library according to @adafruit_support_rick's instructions but I'm having no luck (I've modified the library already to extract all other values but UTC data/time won't cooperate).

Here are code and results from a sketch I modified based on the FONA GPS Test. It displays data from the call to fona.getGPS. I also included modifications I made to the FONA library. All values get returned as expected except UTC Date/Time. What am I doing wrong??

GPStest.ino sketch:

Code: Select all

/*
 * This example is meant to work with the Adafruit
 * FONA 808 or 3G Shield or Breakout
 *
 * Copyright: 2015 Adafruit
 * Author: Todd Treece
 * Licence: MIT
 *
 */
#include "Adafruit_FONA.h"

// standard pins for the shield, adjust as necessary
#define FONA_RX 2
#define FONA_TX 3
#define FONA_RST 4
#define TS_LENGTH 16
char timestamp[TS_LENGTH] = "";
float latitude, longitude, speed_kph, heading, altitude, HDOP, VDOP, used_sats, HPA, VPA;

// We default to using software serial. If you want to use hardware serial
// (because softserial isnt supported) comment out the following three lines 
// and uncomment the HardwareSerial line
#include <SoftwareSerial.h>
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);
SoftwareSerial *fonaSerial = &fonaSS;

// Hardware serial is also possible!
//  HardwareSerial *fonaSerial = &Serial1;

Adafruit_FONA fona = Adafruit_FONA(FONA_RST);

// Have a FONA 3G? use this object type instead
//Adafruit_FONA_3G fona = Adafruit_FONA_3G(FONA_RST);


void setup() {

  while (! Serial);

  Serial.begin(115200);
  Serial.println(F("Adafruit FONA 808 & 3G GPS demo"));
  Serial.println(F("Initializing FONA... (May take a few seconds)"));

  fonaSerial->begin(4800);
  if (! fona.begin(*fonaSerial)) {
    Serial.println(F("Couldn't find FONA"));
    while(1);
  }
  Serial.println(F("FONA is OK"));  

  Serial.println(F("Enabling GPS..."));
  fona.enableGPS(true);
}

void loop() {
  delay(2000);

   bool gps_succes = fona.getGPS(&latitude, &longitude, &speed_kph, &heading, &altitude, &HDOP, &VDOP, &used_sats, &HPA, &VPA, timestamp);

    Serial.print("GPS lat:");
    Serial.println(latitude, 6);
    Serial.print("GPS long:");
    Serial.println(longitude, 6);
    Serial.print("GPS speed KPH:");
    Serial.println(speed_kph);
    Serial.print("GPS heading:");
    Serial.println(heading);
    Serial.print("GPS altitude:");
    Serial.println(altitude);
    Serial.print("HDOP:");
    Serial.println(HDOP);
    Serial.print("VDOP:");
    Serial.println(VDOP);
    Serial.print("Used Sats:");
    Serial.println(used_sats,0);
    Serial.print("UTC Date/time:");
    Serial.println(timestamp);
    Serial.print("HPA:");
    Serial.println(HPA);
    Serial.print("VPA:");
    Serial.println(VPA);
}


Adafruit_FONA.h:

Code: Select all

boolean getGPS(float *lat, float *lon, float *speed_kph=0, float *heading=0, float *altitude=0, float *HDOP=0, float *VDOP=0, float *used_sats=0, float *HPA=0, float *VPA=0, char *timestamp="");
Adafruit_FONA.cpp:

Code: Select all

boolean Adafruit_FONA::getGPS(float *lat, float *lon, float *speed_kph, float *heading, float *altitude, float *HDOP, float *VDOP, float *used_sats, float *HPA, float *VPA, char *timestamp) {

...

    // only grab date if needed
   if (timestamp != NULL) {
      // grab date
      char *ts = strtok(NULL, ",");
      if (! ts) return false;

      strncpy(ts,timestamp,15);   //#define TS_LENGTH 16 not passed from .ino sketch to this routine
           
    }

Output from Serial Monitor:

Code: Select all

	---> AT+CGNSINF
	<--- +CGNSINF: 1,1,20180912114751.000,-2.489895,28.857263,1464.200,12.41,103.2,1,,3.3,3.5,1.0,,13,3,,,21,,
GPS lat:-2.489895
GPS long:28.857261
GPS speed KPH:12.41
GPS heading:103.20
GPS altitude:1464.20
HDOP:3.30
VDOP:1.00
Used Sats:3
UTC Date/time:
HPA:21.00
VPA:0.00
I've tried passing the UTC Date/Time string as char, uint8_t, uint16_t, float and double but nothing seems to work. The closest I get to something useful is by assigning the string to a float in the .cpp file using "atof()". However this overflows unless I do Serial.print(timestamp*0.0001) in my sketch and isn't useful because "timestamp" is truncated.

Another thread discusses using network time instead of GPS time however my project will be used in areas outside of cell reception so I need date/time from the satellites.

Thanks SO much for your help! Keep up the good work.

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: FONA 808 - extract UTC time

Post by adafruit_support_mike »

You're probably calling strtok() in the wrong place.

strtok() is what's known as a 'modal' function.. its behavior depends on how and when you talk to it. You call it the first time with a data string and a delimiter string, and it returns the first part of the data string up to the delimiter. Then every time you call strotok(NULL,delim) it returns the next chunk of the data string up to the next delimiter.

Generally speaking, modal functions are a pain to deal with.

If you're using this as the data string:

Code: Select all

   <--- +CGNSINF: 1,1,20180912114751.000,-2.489895,28.857263,1464.200,12.41,103.2,1,,3.3,3.5,1.0,,13,3,,,21,,
the timestamp is the third item in the comma-delimited list. You have to pull the pointer to that substring as the third call to strtok().

User avatar
MG_123
 
Posts: 6
Joined: Wed Sep 12, 2018 8:00 am

Re: FONA 808 - extract UTC time

Post by MG_123 »

OK so I did some digging and found a solution! It's a bit clunky but it gets the UTC timestamp into my Arduino sketch where I can display it in the format I want. I suspect I'm using more memory than necessary and I still don't understand why it's so difficult to work with this value but for those still looking for a solution, here is what I have:

I had the strtok() set up correctly in the .cpp file but I had to borrow the parsing code from the CCID section where the char array is converted to a string. I was unable to return the UTC time in any other data type unfortunately. I'm unsure why making the last bit of the string a 0 and calling readline() (eat OK?) works but the output is what I want. The Adafruit_FONA.cpp for my FONA V2 now contains:

Code: Select all

boolean Adafruit_FONA::getGPS(char *timestamp, float *lat, float *lon, float *speed_kph, float *heading, float *altitude, float *HDOP, float *VDOP, float *used_sats, float *HPA, float *VPA) {
.
.
.
} else if (_type == FONA808_V2) {
    // Parse 808 V2 response.  See table 2-3 from here for format:
    // "mode,fixstatus,utctime(yyyymmddHHMMSS),latitude,longitude,... etc..."

    // skip GPS mode  (first strtok iteration)
    char *tok = strtok(gpsbuffer, ",");
    if (! tok) return false;

    // skip fix status  (second strtok iteration)
    tok = strtok(NULL, ",");
    if (! tok) return false;

    // grab UTC date/time (third strtok iteration)
    char *timestring = strtok(NULL, ",");
    if (! timestring) return false;    

       strncpy(timestamp, timestring, 14);

         timestamp[14] = 0;

  readline(); // eat 'OK'
.
.
.

}

Now in my Arduino sketch, I get the GPS data as follows:

Code: Select all

    bool gpsFix = fona.getGPS(&timestamp, &latitude, &longitude, &speed_kph, &heading, &altitude, &HDOP, &VDOP, &used_sats, &HPA, &VPA);


char *UTCstring = &timestamp;  //yyyymmddHHMMSS assign timestamp address to UTCstring variable?

And I can display the UTCstring using Serial.print(UTCstring). I'm now working to separate this string into UTC date and UTC time. The following works:

Code: Select all

 

char *UTCstring = &timestamp;  //yyyymmddHHMMSS

Serial.print(UTCstring[0]);
    Serial.print(UTCstring[1]);
    Serial.print(UTCstring[2]);
    Serial.print(UTCstring[3]);
    Serial.print(UTCstring[4]);
    Serial.print(UTCstring[5]);
    Serial.print(UTCstring[6]);
    Serial.print(UTCstring[7]);
But the following does not:

Code: Select all

char *UTCstring = &timestamp;  //yyyymmddHHMMSS

    char UTCdate[8];
    char UTCtime[6];
   
    for (int i=0; i<8; i++){
        UTCdate[i] = UTCstring[i];
    }

    for (int i=9; i<14; i++){
        UTCtime[i] = UTCstring[i];
    }

Serial.print(UTCdate);
Serial.println(UTCtime);
@adafruit_support_mike (or others), I have two remaining questions:

1. Do you have any recommendations on how to handle this parsing more efficiently? Is there a better way to assign the pointer values to variables so this string can be worked more easily in the Arduino sketch? Is appears that &timestamp holds the address of the UTC string, but how best to assign it to a variable?

2. Why can't this data be passed from the .ccp as another data type except string? Every other data type results in trouble. This string is simply a 14-digit number with fixed length and no special characters. According to Arduino, float can have a value up to 3.4028235E+38 and the UTC date/time is nowhere near that maximum. I'm a little confused - why is it not possible? Working with strings is a pain!

Thanks again for the help!

MG

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: FONA 808 - extract UTC time

Post by adafruit_support_mike »

Check to see if sscanf() is supported on the board you’re uising. It’s the opposite of sprintf(), extracting values from a formatted string and putting them into variables.

You probably won’t have an integer type that can hold enough digits for the whole timestamp. The largest possible 32-bit integer only has 10 digits.

Locked
Please be positive and constructive with your questions and comments.

Return to “FONA”