Go Down

Topic: [SOLVED] Problem data logging with TinyGPS++ and SdFat (Read 16279 times) previous topic - next topic

tomliggett

Hi, I've had the same issue with the inability of my Mega to both receive GPS data and read/write to an SD card. Could you please post the code that you now have successfully running? I'm not sure how to remove SoftwareSerial from the code, as TinyGPS uses it in Setup() to establish the tx/rx pins. Thanks! (The project is an autonomous boat that requires GPS for navigation and we'd like to have a record of locations)

Sayedurrchowdhury

#31
Jan 13, 2014, 07:32 am Last Edit: Jan 19, 2014, 07:14 am by Sayedurrchowdhury Reason: 1

Hi, I've had the same issue with the inability of my Mega to both receive GPS data and read/write to an SD card. Could you please post the code that you now have successfully running? I'm not sure how to remove SoftwareSerial from the code, as TinyGPS uses it in Setup() to establish the tx/rx pins. Thanks! (The project is an autonomous boat that requires GPS for navigation and we'd like to have a record of locations)


Hi,
When you say 'inability' that doesn't help understand what's going on. I am posting my latest 'best known' code below, but you have to keep two things in mind:
1) My code is for Uno (ATmega328P) not for mega, so you may have to use appropriate pins.
2) TinyGPS and TinyGPS++ are two different libraries from the same author, the later being the successor. If you stick to the non++ library, my code have to be changed (some lines must be removed) accordingly.

As regards use of Software serial, on Mega you do not have to use it at all, because Mega has got several (four, I guess) hardware serial ports. Documentation will tell you which pins.

Code: [Select]

/*
GPS data logger using TinyGPS++ and SoftwareSerial libraries and examples by Mikel Hart
Sketch written by: Sayedur R Chowdhury, Dec 10, 2013

Data to be logged: Date, Time, Lat, Lon, Altitude, DOP, Speed, Bearing

Indicator LED:
  Uses one common anode RGB LED. Connections:
  Anode = pin 6
    Red   = pin 5
Green = pin 7
  Blue = pin 8
 
GPS connections:
  Rx = pin 1
  Tx = pin 0

MicroSD connections:
  CS = pin 10
    MOSI = pin 11
    MISO = pin 12
  SCK = pin 13

*/
//#define SERIALOUT

#include <MemoryFree.h>
#include <TinyGPS++.h>
//#include <SoftwareSerial.h>
#include <SdFat.h>

//definitions fo SoftwareSerial GPS
//static const byte Rx = 3, Tx = 2;  //rx,tx (3,2) on the Arduino side connects to Tx, Rx of GPS respectively
//static const int baudrate = 9600;

//defintion for RGB LED
static const byte commonAnode = 6, R = 5, G = 7, B = 8;

//definitions for SD card and file
SdFat sd;
SdFile datafile;
static const int SD_CS = 10;

bool writeHeader = 1;

//TinyGPS NMEA stream
TinyGPSPlus nmea;
//TinyGPSCustom pdop(nmea, "GPGSA", 15);  //takes up 50 bytes of SRAM

//serial connection to the GPS device
//SoftwareSerial gps(Rx, Tx);


void setup()
{
//#ifdef SERIALOUT
Serial.begin(19200);
//#endif

//set up RGB led pins
pinMode(commonAnode, OUTPUT);
pinMode(R, OUTPUT);
pinMode(G, OUTPUT);
pinMode(B, OUTPUT);
digitalWrite(commonAnode, HIGH);
digitalWrite(R, HIGH);
digitalWrite(G, HIGH);
digitalWrite(B, HIGH);

//gps.begin(baudrate);
pinMode(SD_CS, OUTPUT);

if (sd.begin(SD_CS, SPI_HALF_SPEED)) {
//indicate success by long flashing RB (magenta) led twice
flashLEDbicolor(1000, R, B);
smartDelay(500);
flashLEDbicolor(1000, R, B);
#ifdef SERIALOUT
Serial.println(F("SD Ok"));
#endif
}
else {
//indicate SD init error by long flashing error-led once
flashLED(1000, R);
#ifdef SERIALOUT
Serial.println(F("SD Error"));
#endif
}  //SD.begin ends

#ifdef SERIALOUT
Serial.print("freeMemory()=");
Serial.println(freeMemory());
#endif
}    //setup ends

void loop()
{
unsigned int pastCharProcessed = nmea.charsProcessed(), recentCharProcessed=0;
unsigned int flashTimer=0;
unsigned long currentMillis = millis(), previousMillis = 0;
//SdFile datafile;

//smartdelay at the beginning
smartDelay(3000);
//check new nmea.charProcessed because smartDelay has already elapsed some time
recentCharProcessed = nmea.charsProcessed() - pastCharProcessed;

flashTimer = currentMillis - previousMillis;

//verify if GPS data coming in
if (recentCharProcessed < 10) {    //not enough data coming in
//flash errorLed every 3 seconds if no data is coming, diagnose wiring problem
if (flashTimer > 3000) {
previousMillis = currentMillis;
flashLED(10, R);
flashTimer = 0; //reset timer
#ifdef SERIALOUT
Serial.println(F("No data"));
#endif
}
}
else { //expected amount of data is coming
//verify if a fix is obtained
if (!nmea.location.isValid()) {  //no fix yet
//flash fixLed every 10 seconds if data is coming but no fix yet
if (flashTimer > 10000) {
previousMillis = currentMillis;
flashLED(10, B);
flashTimer = 0; //reset timer
#ifdef SERIALOUT
Serial.println(F("Data Ok, no fix"));
#endif
}
}
else {  //fix obtained
//GPS units generally have fix indicators, an indicator is not needed; comment out flashLed codes below
/*
if (flashTimer > 30000) {
previousMillis = currentMillis;
flashLED(10, G);
flashTimer = 0; //reset timer
}
*/
#ifdef SERIALOUT
Serial.println(F("Fix obtained"));
#endif

//Debug: the following closing brace moved here from below to initiate loggin even before a fix
//in the final sketch logging will start only when a fix is obtained
} //!nmea.location.isValid()

//now that a fix is obtained,  proceed onto logging data to SD card file

if (datafile.open("GPSDATA.CSV", O_WRITE | O_CREAT | O_APPEND)) {
//indicate write/logging success by flashing OkLed once every minute
if (flashTimer > 60000) {
previousMillis = currentMillis;
flashLED(10, G);
flashTimer = 0; //reset timer
#ifdef SERIALOUT
Serial.println(F("GPSDATA.CSV opened"));
#endif
}

//write CSV header only once at the beginning of the loop
if (writeHeader == 1) {
datafile.println();
datafile.print(F("GPS data logging starts at "));
datafile.print(millis());
datafile.println(F(" mSecs"));
datafile.println(F("date,time,lat,lon,altitude,HDOP,speed,course"));
writeHeader = 0;
}

//Date, Time
if (nmea.date.isUpdated()) {
datafile.print(nmea.date.year());
datafile.print("/");
datafile.print(nmea.date.month());
datafile.print("/");
datafile.print(nmea.date.day());
}
datafile.print(",");
if (nmea.time.isUpdated()) {
datafile.print(nmea.time.hour());
datafile.print(":");
datafile.print(nmea.time.minute());
datafile.print(":");
datafile.print(nmea.time.second());
datafile.print(".");
datafile.print(nmea.time.centisecond());
}
datafile.print(",");

//Lat, Lon
datafile.print(nmea.location.lat(),6);
datafile.print(",");
datafile.print(nmea.location.lng(),6);
datafile.print(",");

//Altitude
datafile.print(nmea.altitude.meters(),5);
datafile.print(",");

//DOP
datafile.print(nmea.hdop.value(),5);
datafile.print(",");

//speed
datafile.print(nmea.speed.kmph());
datafile.print(",");

//bearing
datafile.print(nmea.course.deg());

datafile.print(",");
datafile.print(freeMemory());

//last field saved, start a new line
datafile.println();

#ifdef SERIALOUT
Serial.println(F("Data written."));
#endif

//close datafile
datafile.close();
} //if datafile succeeds
else {  //datafile error
//flash error LED
flashLED(400, R);
#ifdef SERIALOUT
Serial.println(F("Write error"));
#endif
}  //datafile
//} //!nmea.location.isValid() ends
} //recentCharProcessed < 10

#ifdef SERIALOUT
Serial.print("freeMemory()=");
Serial.println(freeMemory());
#endif
}

// This custom version of delay() ensures that the nmea object is being "fed".
static void smartDelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (Serial.available())
nmea.encode(Serial.read());
} while (millis() - start < ms);
}

//red LED indicator of Errors
static void flashLED(int duration, byte color)
{
digitalWrite(color, LOW);
smartDelay(duration);
digitalWrite(color, HIGH);
}

static void flashLEDbicolor(int duration, byte color1, byte color2)
{
digitalWrite(color1, LOW);
digitalWrite(color2, LOW);
smartDelay(duration);
digitalWrite(color1, HIGH);
digitalWrite(color2, HIGH);
}


nihaoma

#32
Jan 17, 2014, 11:14 pm Last Edit: Jan 17, 2014, 11:24 pm by nihaoma Reason: 1
Hi Sayedurrchowdhury,

Thanks for sharing your sucessful code. A couple of questions I couldn't answer from the post:

(1) Is this last piece of code still sucessfully working with both the uBlox Neo-6 from eBay, and Adafruit Ultimate GPS as you stated in #2 of your first post?

(2) Also, with respect to the uBlox Neo: would you mind sharing a picture or schematic of how are you connecting it to the UNO? I'm concerned about the UNO pins at 5V and the uBlox RX and TX pins at 3.3V.

I'm talking specifically about this uBlox Neo:
http://www.ebay.com/itm/200911914297

Best,

Sayedurrchowdhury


(1) Is this last piece of code still sucessfully working with both the uBlox Neo-6 from eBay, and Adafruit Ultimate GPS as you stated in #2 of your first post?


Hi nihaoma,

I am not quite sure which part of the code you are referring to, but that wouldn't affect the way I answer your query. This code runs for both the GPSs I use. This is because the code is not hardware dependent as long as you connect your GPS module via Tx/Rx pins and receive valid NMEA sentences from the GPS. As such, this code will work for any NMEA enabled GPS module.

Quote

(2) Also, with respect to the uBlox Neo: would you mind sharing a picture or schematic of how are you connecting it to the UNO? I'm concerned about the UNO pins at 5V and the uBlox RX and TX pins at 3.3V.


I don't have a schematic ready to show you here, but it's pretty simple; connect the GPS's Rx to Arduino 1 and Tx to Arduino 0. VCC and GND as usual. However, please be informed that, I am not using an off-the-shelf Arduino Uno, instead I have made my own, which uses 3.3V on all its pins, and an optional 5V source if I need sometime. You can see complete details of my homemade Arduino here: http://www.instructables.com/id/Dual-voltage-Generic-Data-Logger-Arduino/

And yes, I have the same (or at least looks the same) Ublox on eBay.

Cheers!

nihaoma

Thanks for the quick reply.

Btw, your dual voltage logger documentation is pretty neat and easy to follow. I will most likely build a similar configuration. The discovery of the ATMega chip outputting 3.3V when powered by 3.3V is important.

Best,

Go Up