Go Down

Topic: Arduino GPS Shield by iteadstudio.com (Read 40 times) previous topic - next topic

Frédéric_Plante

As we fight our way northward into the great unknown, only that one thing remains certain...

frankhu01

Yes, below is the code I am using for testing.

Code: [Select]

//Jeremy Blum's Arduino Tutorial Series - Episode 15 - GPS Tracking
//Sample Code 2 - Logging GPS Data to an SD Card
//http://www.jeremyblum.com
//TinyGPS Library and Helper Functions by Mikal Hart http://arduiniana.org/libraries/tinygps/


#include <TinyGPS.h>
#include <SD.h>
#include <stdlib.h>

/* This sample code demonstrates the normal use of a TinyGPS object.
   It uses an Arduino Mega with a GPS attached to Serial1 at 4800 buad.
*/

TinyGPS gps;
static char dtostrfbuffer[20];
int LED = 13;

//Define String
String SD_date_time = "invalid";
String SD_lat = "invalid";
String SD_lon = "invalid";
String dataString ="";

static void gpsdump(TinyGPS &gps);
static bool feedgps();
static void print_float(float val, float invalid, int len, int prec, int SD_val);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);

const int SD1 = 11; //MOSI pin on shield, connect to MOSI pin on board (pin 51)
const int SD2 = 12; //MISO pin on shield, connecto to MISO pin on board (pin 50)
const int SD3 = 13; //SCK pin on shield, connecto to SCK pin on board (pin 52)
int CS = 53; //CS pin on board, connect to D10 on the shield (CS pin for shield)

void setup()
{
  pinMode(SD1,INPUT);
  pinMode(SD2,INPUT);
  pinMode(SD3,INPUT);
  pinMode(CS, OUTPUT);  //Chip Select Pin for the SD Card
  pinMode(LED, OUTPUT);  //LED Indicator
 
  //Serial interfaces
  Serial.begin(38400);
  Serial1.begin(38400);
 
  //Connect to the SD Card
  if(!SD.begin(CS))
  {
    Serial.println("Card Failure");
    return;
  }
 
 
 
  Serial.print("Testing TinyGPS library v. "); Serial.println(TinyGPS::library_version());
  Serial.println("by Mikal Hart");
  Serial.println();
  Serial.print("Sizeof(gpsobject) = "); Serial.println(sizeof(TinyGPS));
  Serial.println();
  Serial.println("Sats HDOP Latitude Longitude Fix  Date       Time       Date Alt     Course Speed Card  Distance Course Card  Chars Sentences Checksum");
  Serial.println("          (deg)    (deg)     Age                        Age  (m)     --- from GPS ----  ---- to London  ----  RX    RX        Fail");
  Serial.println("--------------------------------------------------------------------------------------------------------------------------------------");
}

void loop()
{
  bool newdata = false;
  unsigned long start = millis();
 
  // Every second we print an update
  while (millis() - start < 1000)
  {
    if (feedgps())
      newdata = true;
  }
 
  gpsdump(gps);
 
  //Write the newest information to the SD Card
dataString = SD_date_time + "," + SD_lat + "," + SD_lon;
  if(SD_date_time != "invalid")
    digitalWrite(LED, HIGH);
  else
    digitalWrite(LED, LOW);
   
  //Open the Data CSV File
  File dataFile = SD.open("LOG.csv", FILE_WRITE);
  if (dataFile)
  {
    dataFile.println(dataString);
    Serial.println(dataString);
    dataFile.close();
  }
  else
  {
    Serial.println("\nCouldn't open the log file!");
  }
}

static void gpsdump(TinyGPS &gps)
{
  float flat, flon;
  unsigned long age, date, time, chars = 0;
  unsigned short sentences = 0, failed = 0;
  static const float LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
 
  print_int(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 5);
  print_int(gps.hdop(), TinyGPS::GPS_INVALID_HDOP, 5);
  gps.f_get_position(&flat, &flon, &age);
  print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 9, 5, 1); //LATITUDE
  print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 10, 5, 2); //LONGITUDE
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);

  print_date(gps); //DATE AND TIME

  print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 8, 2, 0);
  print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2, 0);
  print_float(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 6, 2, 0);
  print_str(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(gps.f_course()), 6);
  print_int(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0UL : (unsigned long)TinyGPS::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);
  print_float(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : TinyGPS::course_to(flat, flon, 51.508131, -0.128002), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2, 0);
  print_str(flat == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON)), 6);

  gps.stats(&chars, &sentences, &failed);
  print_int(chars, 0xFFFFFFFF, 6);
  print_int(sentences, 0xFFFFFFFF, 10);
  print_int(failed, 0xFFFFFFFF, 9);
  Serial.println();
}

static void print_int(unsigned long val, unsigned long invalid, int len)
{
  char sz[32];
  if (val == invalid)
    strcpy(sz, "*******");
  else
    sprintf(sz, "%ld", val);
  sz[len] = 0;
  for (int i=strlen(sz); i<len; ++i)
    sz[i] = ' ';
  if (len > 0)
    sz[len-1] = ' ';
  Serial.print(sz);
  feedgps();
}

static void print_float(float val, float invalid, int len, int prec, int SD_val)
{
  char sz[32];
  if (val == invalid)
  {
    strcpy(sz, "*******");
    sz[len] = 0;
        if (len > 0)
          sz[len-1] = ' ';
    for (int i=7; i<len; ++i)
        sz[i] = ' ';
    Serial.print(sz);
    if(SD_val == 1) SD_lat = sz;
    else if(SD_val == 2) SD_lon = sz;
  }
  else
  {
    Serial.print(val, prec);
    if (SD_val == 1) SD_lat = dtostrf(val,10,5,dtostrfbuffer);
    else if (SD_val == 2) SD_lon = dtostrf(val,10,5,dtostrfbuffer);
    int vi = abs((int)val);
    int flen = prec + (val < 0.0 ? 2 : 1);
    flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
    for (int i=flen; i<len; ++i)
      Serial.print(" ");
  }
  feedgps();
}

static void print_date(TinyGPS &gps)
{
  int year;
  byte month, day, hour, minute, second, hundredths;
  unsigned long age;
  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
  if (age == TinyGPS::GPS_INVALID_AGE)
  {
    Serial.print("*******    *******    ");
    SD_date_time = "invalid";
  }
  else
  {
    char sz[32];
    sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d   ",
        month, day, year, hour, minute, second);
    Serial.print(sz);
    SD_date_time = sz;
  }
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  feedgps();
}

static void print_str(const char *str, int len)
{
  int slen = strlen(str);
  for (int i=0; i<len; ++i)
    Serial.print(i<slen ? str[i] : ' ');
  feedgps();
}

static bool feedgps()
{
  while (Serial1.available())
  {
    if (gps.encode(Serial1.read()))
      return true;
  }
  return false;
}

michinyon

The course information is going to be meaningless unless you are actually moving.

Frédéric_Plante

#183
Aug 05, 2014, 07:04 am Last Edit: Aug 05, 2014, 07:07 am by Frédéric_Plante Reason: 1
Yeah that is for sure since it seem to be the difference between 2 positions. If it is 2x the same Positions. The pointer is null
As we fight our way northward into the great unknown, only that one thing remains certain...

Frédéric_Plante

#184
Aug 05, 2014, 07:10 pm Last Edit: Aug 05, 2014, 08:00 pm by Frédéric_Plante Reason: 1
Hey!

I don't have your particular kind of GPS, how ever, I got the thing to work at speed 38400.  So I got lot of:

Code: [Select]
**** **** *******  *******   **** *******    *******    **** ******* ****** ****
* ***   0        0.00   ***   0     0         0        
                     
invalid,*******  ,*******  
                                                 
**** **** *******  *******   **** *******    *******    **** ******* ****** ****
* ***   0        0.00   ***   0     0         0        
                     
invalid,*******  ,*******  
                                                 
**** **** *******  *******   **** *******    *******    **** ******* ****** ****
* ***   0        0.00   ***   0     0         0        
                     
invalid,*******  ,*******  
                                                 
**** **** *******  *******   **** *******    *******    **** ******* ****** ****
* ***   0        0.00   ***   0     0         0        
                     
invalid,*******  ,*******  
                                                 
**** **** *******  *******   **** *******    *******    **** ******* ****** ****
* ***   0        0.00   ***   0     0         0        
                     
invalid,*******  ,*******  
   


But it does record the data on the SD card. There are lot of bug on you code so I'm just gonna paste the new version:

Code: [Select]

#include <TinyGPS.h>
#include <SD.h>
#include <stdlib.h>
#include <SPI.h>

TinyGPS gps;
static char dtostrfbuffer[20];

int CS = 10;
int LED = 13;

String SD_date_time = "invalid";
String SD_lat = "invalid";
String SD_lon = "invalid";
String dataString ="";

static void gpsdump(TinyGPS &gps);

static bool feedgps();
static void print_float(float val, float invalid, int len, int prec, int SD_val);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);


void setup(){

 pinMode(CS, OUTPUT);  
 pinMode(LED, OUTPUT);  
 
 Serial.begin(57600);
 Serial1.begin(38400);
 
 if(!SD.begin(CS)) {

   Serial.println("Card Failure");
   return;

 }
 
 Serial.print(F("Testing TinyGPS library v. "));
 Serial.println(TinyGPS::library_version());
 Serial.println(F("by Mikal Hart"));
 Serial.println();
 Serial.print(F("Sizeof(gpsobject) = "));
 Serial.println(sizeof(TinyGPS));
 Serial.println();
 Serial.println(F("Sats HDOP Latitude Longitude Fix  Date       Time       Date Alt     Course Speed Card  Distance Course Card  Chars Sentences Checksum"));
 Serial.println(F("          (deg)    (deg)     Age                        Age  (m)     --- from GPS ----  ---- to London  ----  RX    RX        Fail"));  
Serial.println(F("--------------------------------------------------------------------------------------------------------------------------------------"));

}

void loop(){

 bool newdata = false;
 unsigned long start = millis();
 
 while (millis() - start < 1000) {

   if (feedgps()) newdata = true;

 }
 
 gpsdump(gps);
 dataString = SD_date_time + "," + SD_lat + "," + SD_lon;

 if(SD_date_time != "invalid") digitalWrite(LED, HIGH);
 else digitalWrite(LED, LOW);

 File dataFile = SD.open("LOG.csv", FILE_WRITE);

 if (dataFile) {

   dataFile.println(dataString);
   Serial.println(dataString);
   dataFile.close();

 }

 else  Serial.println("\nCouldn't open the log file!");

}

static void gpsdump(TinyGPS &gps){

 float flat, flon;
 unsigned long age, date, time, chars = 0;
 unsigned short sentences = 0, failed = 0;
 static const float LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
 
 print_int(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 5);
 print_int(gps.hdop(), TinyGPS::GPS_INVALID_HDOP, 5);

 gps.f_get_position(&flat, &flon, &age);

 print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 9, 5, 1); //LATITUDE
 print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 10, 5, 2); //LONGITUDE
 print_int(age, TinyGPS::GPS_INVALID_AGE, 5);

 print_date(gps); //DATE AND TIME

 print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 8, 2, 0);
 print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2, 0);
 print_float(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 6, 2, 0);
 print_str(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(gps.f_course()), 6);
 print_int(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0UL : (unsigned long)TinyGPS::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);
 print_float(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : TinyGPS::course_to(flat, flon, 51.508131, -0.128002), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2, 0);
 print_str(flat == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON)), 6);

 gps.stats(&chars, &sentences, &failed);

 print_int(chars, 0xFFFFFFFF, 6);
 print_int(sentences, 0xFFFFFFFF, 10);
 print_int(failed, 0xFFFFFFFF, 9);

 Serial.println();

}

static void print_int(unsigned long val, unsigned long invalid, int len){

 char sz[32];

 if (val == invalid)  strcpy(sz, "*******");
 else sprintf(sz, "%ld", val);

 sz[len] = 0;

 for (int i=strlen(sz); i<len; ++i)  sz[i] = ' ';

 if (len > 0) sz[len-1] = ' ';

 Serial.print(sz);

 feedgps();

}

static void print_float(float val, float invalid, int len, int prec, int SD_val){

 char sz[32];

 if (val == invalid)  {

   strcpy(sz, "*******");
   sz[len] = 0;
   
   if (len > 0)  sz[len-1] = ' ';

   for (int i=7; i<len; ++i)  sz[i] = ' ';

   Serial.print(sz);

   if(SD_val == 1) SD_lat = sz;
   else if(SD_val == 2) SD_lon = sz;

 }
 
 else  {

   Serial.print(val, prec);

   if (SD_val == 1) SD_lat = dtostrf(val,10,5,dtostrfbuffer);
   else if (SD_val == 2) SD_lon = dtostrf(val,10,5,dtostrfbuffer);

   int vi = abs((int)val);
   int flen = prec + (val < 0.0 ? 2 : 1);

   flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
   
   for (int i=flen; i<len; ++i) Serial.print(F(" "));

 }

 feedgps();

}

static void print_date(TinyGPS &gps){

 int year;
 byte month, day, hour, minute, second, hundredths;
 unsigned long age;

 gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);

 if (age == TinyGPS::GPS_INVALID_AGE) {

   Serial.print(F("*******    *******    "));
   SD_date_time = "invalid";

 }

 else {

   char sz[32];

   sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d   ",  month, day, year, hour, minute, second);

   Serial.print(sz);

   SD_date_time = sz;

 }

 print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
 
 feedgps();

}

static void print_str(const char *str, int len){

 int slen = strlen(str);

 for (int i=0; i<len; ++i) Serial.print(i<slen ? str[i] : ' ');

 feedgps();

}

static bool feedgps(){

 while (Serial1.available()) {

   if (gps.encode(Serial1.read()))  return true;

 }

 return false;

}


But here is a few clue.

1. you need to declare the SPI.h library.
2. you should not use pin 53 for CC I got it hooked on 10. You can put what ever pin that you prefer actually 10 is the default for SPI.
3. you should not assign  the pin for the spi port your self, the SPI library does it by it self.
4. the SPI port on mega256 is at pin 50 pin 51 and pin 52.
5. the MOSI pin and CLK pin are  OUTPUT, I just say but don't mess with them as I said the library does it for you

So try this and give me new about it. :)
As we fight our way northward into the great unknown, only that one thing remains certain...

Frédéric_Plante

Oh one last thing, the IDE serial port monitor does not seem to support the speed 38400bps, I don't know why since it's a the product of 9600bps x 4, but any way. I't could be a good thing to set your Serial port 0 speed to a speed that is compatible with the IDE serial port monitor, while leaving the Serial1 at speed 38400. I would suggest to put it a 57600 to make sure you don't get a buffer over run problem.
As we fight our way northward into the great unknown, only that one thing remains certain...

frankhu01

Hello,

The code you gave me logs the data when its warming up, like when the result is ******. But when the GPS fixes and valid data comes through, the serial monitor prints that it can't open log file.

The results I get:
Quote

**** **** *******  *******   **** *******    *******    **** ******* ****** ***** ***   0        0.00   ***   25873 0         3       
invalid,*******  ,*******   
**** **** *******  *******   **** *******    *******    **** ******* ****** ***** ***   0        0.00   ***   26206 0         3       
invalid,*******  ,*******   
**** **** *******  *******   **** *******    *******    **** ******* ****** ***** ***   0        0.00   ***   26539 0         3       
invalid,*******  ,*******   
5    164  37.87208 -122.28707126  08/06/2014 05:57:34   131  33.60   0.00   2.46  N     8603     32.68  NNE   26982 2         3       

Couldn't open the log file!
5    164  37.87208 -122.28707234  08/06/2014 05:57:35   239  33.90   0.00   0.63  N     8603     32.68  NNE   27399 4         3       

Couldn't open the log file!
5    164  37.87207 -122.28707259  08/06/2014 05:57:36   264  34.10   0.00   0.41  N     8603     32.68  NNE   27842 6         3       

Couldn't open the log file!
5    164  37.87207 -122.28707285  08/06/2014 05:57:37   290  34.70   0.00   0.30  N     8603     32.68  NNE   28293 8         3       

Couldn't open the log file!

michinyon

I don't know why you defined those functions to be "static",  as that will have no meaningful effect.

michinyon

You can use pin 53 for the chip select signal to the sd card reader,  there is no reason why you cannot.

What is the point of your "newdata" variable ?   You set this if new data has come from the gps,  but then you don't use it.

Your sd card may have had its formatting damaged.   try to read the information which is already there.   try deleting any existing log.txt file.   Try reformatting the sd card.


michinyon

Quote
The code you gave me logs the data when its warming up, like when the result is ******. But when the GPS fixes and valid data comes through, the serial monitor prints that it can't open log file.


So,  you are saying here,   it works when you start it up,   and it writes invalid data into the sd card file,    and then when the gps actuallly starts working,   then it cannot write to the sd file any more ????

The only way this could be happening,   is that when all those complicated print functions get run for invalid data,   then they work,   but when they run for good data,    and execute different parts of the code in those print functions,    then you are running out of memory or getting data corruption somehow.

To be clear,  I don't think it is a bug with any of the code actually related to the sd card open/write/close operation.

Try getting rid of all that printing,   by not calling gpsdump( )  at all,   and see what happens.    You might need to write a short alternative function which justs gets the time and lattitude and longitude from the gps class object,   but doesn't do anything else.



michinyon

Code: [Select]

    if(SD_val == 1) SD_lat = sz;
    else if(SD_val == 2) SD_lon = sz;


This bit of code in your printfloat( ) function is dubious.

It only sets a value into the strings SD_lat and SD_long in the case where the data is invalid.    which would seem to be the wrong thing to do.

The char array sz is not null-terminated.

You are relying on some kind of unknown assignment from a char array to a string.    There may be a suitable default assignment overload,  but I would not do it that way.


Frédéric_Plante

#191
Aug 06, 2014, 04:46 pm Last Edit: Aug 06, 2014, 05:18 pm by Frédéric_Plante Reason: 1
Personally, I would not use the tinygps, cause it's far from tiny.

By the way you are right muchinyon, there is no problem using the pin 53, I was cross remembering 2 info that don't belong together, my mistake. Just any pin will do just fine.

I must admit there was lot of crap in the code, I changed it just enough to make it work on my system. But really, you know that all your NMEA data are split by "," so do a routine that will extract just the part you need, and drop the rest.

Your problem is not when you fetch data from you serial port, and it's not when you send stuff to your SD card, so it as to be in between. The running out of memory hypotheses is the bet. Tinygps does so much useless stuff with the data it get, although it does it well I checked in the library, that running out of memory is more then probable.

Tinygps, is a demo program meant to see if you gps is working. Well that is the way I see it any way.
As we fight our way northward into the great unknown, only that one thing remains certain...

Frédéric_Plante

It's really strange cause with this exact code, excepte at a gps communication speed of 4800 bps I get this in my log file:

Code: [Select]
invalid,*******  ,*******   
invalid,*******  ,*******   
invalid,*******  ,*******   
invalid,*******  ,*******   
invalid,*******  ,*******   
invalid,*******  ,*******   
08/06/2014 17:58:39   ,  45.78860, -74.00496
08/06/2014 17:58:40   ,  45.78860, -74.00496
08/06/2014 17:58:43   ,  45.78860, -74.00496
08/06/2014 17:58:44   ,  45.78860, -74.00496
08/06/2014 17:58:45   ,  45.78860, -74.00496
08/06/2014 17:58:46   ,  45.78860, -74.00496
08/06/2014 17:58:47   ,  45.78860, -74.00496
08/06/2014 17:58:48   ,  45.78860, -74.00496
08/06/2014 17:58:49   ,  45.78860, -74.00496
08/06/2014 17:58:50   ,  45.78860, -74.00496
08/06/2014 17:58:51   ,  45.78860, -74.00496
08/06/2014 17:58:53   ,  45.78860, -74.00496
08/06/2014 17:58:54   ,  45.78860, -74.00496
08/06/2014 17:58:55   ,  45.78860, -74.00496
08/06/2014 17:58:56   ,  45.78861, -74.00496
08/06/2014 17:58:57   ,  45.78861, -74.00496
08/06/2014 17:58:58   ,  45.78861, -74.00496
08/06/2014 17:58:59   ,  45.78861, -74.00497
08/06/2014 17:59:00   ,  45.78861, -74.00497
08/06/2014 17:59:01   ,  45.78861, -74.00497
08/06/2014 17:59:02   ,  45.78812, -74.00490
08/06/2014 17:59:03   ,  45.78803, -74.00488
08/06/2014 17:59:04   ,  45.78803, -74.00488
08/06/2014 17:59:05   ,  45.78802, -74.00488


Well the time is no good, but I can expect that since i'm located at -5 gmt.

So we are really back at is there  some sort of a system incompatibility when the serial port is set at 38400bps with the SPI bus.

Can you try to set your Internal GPS speed to some thing else?
As we fight our way northward into the great unknown, only that one thing remains certain...

frankhu01

Okay, I will try deleting TinyGPS print functions to clear up memory and try it again.
I will also try filtering out the data I need instead of using tinygps and see if that works.

My question would be how do I reset the internal speed of the GPS to 4800?

Thanks for the insight guys!

Frédéric_Plante

You can do that for now,  will get you to be able to start you project right away.

but this is bugging me, what could lead to this particular problem. This is no good, I'm getting on the case of this incompatibilité
As we fight our way northward into the great unknown, only that one thing remains certain...

Go Up