Hardware: Arduino Nano, MicroSD card module (SPI), Neo 7m GPS module
When I run the Example "SD - ReadWrite", everything works fine. I have tried multiple SD cards and reformatted them several times. I have tested the setup over USB of course, but also standalone with battery power (both 3.3v and 5v) and still don't get a pattern. The Neo NMEA data from the GPS has always been consistent. So I am confident in the circuit setup.
When I run my sketch, the card consistently initializes fine. However, randomly the Nano writes the GPS data to the SD card as expected, and sometimes it writes garbage characters. Everything in the Serial Monitor displays correctly every time.
I believe it is some kind of memory allocation or memory read/write speed issue but I can't pin the problem down. I've spent about four days reading forum posts here, in Stack Overflow, and web search engines with no concrete answers. Please help if you are familiar with this - it seems to be a very common setup.
Full sketch code and output file attached below.
Thank you.
#include <TinyGPSPlus.h>
#include <SoftwareSerial.h>
#include <SPI.h>
#include <SD.h>
// set up variables and constants
Sd2Card card;
SdVolume volume;
File myFile;
String day, month, year, minute, second, Date, Time, speed, Data;
int hour = 0;
double Latitude, Longitude, Altitude, Dire;
static const int RXPin = 3, TXPin = 4;
static const int chipSelect = 10;
#define MOSI 11
#define MISO 12
#define SCLK 13
// Initialize objects
TinyGPSPlus gps;
SoftwareSerial SerialGPS(RXPin, TXPin);
void setup()
{
Serial.begin(9600);
Serial.print("Initializing SD card...");
if (!SD.begin(chipSelect)) {
Serial.println("initialization failed!");
while (1);
}
Serial.println("initialization done.");
Serial.print("Creating GPS_data.txt...");
myFile = SD.open("GPS_data.txt", FILE_WRITE);
if (myFile) {
myFile.println(F("Latitude, Longitude, Altitude, Date, Time, Speed, Course"));
myFile.close();
Serial.println("done.");
}
else {
Serial.println("error opening GPS_data.txt");
}
SerialGPS.begin(9600);
}
void loop()
{
// This section displays information every time a new NMEA sentence is correctly encoded.
while (SerialGPS.available() > 0)
if (gps.encode(SerialGPS.read()))
displayInfo();
if (millis() > 5000 && gps.charsProcessed() < 10)
{
Serial.println("No GPS detected: check wiring.");
while(true);
}
}
void displayInfo()
{
if (gps.location.isValid()) {
Latitude = gps.location.lat();
Longitude = gps.location.lng();
}
else
{
Serial.println("INVALID GPS Location");
}
if (gps.date.isValid()) {
month = gps.date.month();
day = gps.date.day();
year = gps.date.year();
Date = month + "/" + day + "/" + year;
}
else
{
Serial.println("INVALID GPS Date");
}
if (gps.time.isValid()) {
hour = (gps.time.hour() - 4);
minute = gps.time.minute();
second = gps.time.second();
if ((gps.time.minute() < 10) && (gps.time.second() < 10)) {
Time = ":0" + minute + ":0" + second; }
else if (gps.time.second() < 10) {
Time = ":" + minute + ":0" + second; }
else if (gps.time.minute() < 10) {
Time = ":0" + minute + ":" + second; }
else {
Time = ":" + minute + ":" + second; }
}
else
{
Serial.println("INVALID GPS Time");
}
if (gps.altitude.isValid()) {
Altitude = gps.altitude.feet();
}
else
{
Serial.println("INVALID GPS Altitude");
}
if (gps.speed.isValid()) {
speed = gps.speed.mph();
}
else
{
Serial.println("INVALID GPS Speed");
}
if (gps.course.isValid()) {
Dire = gps.course.deg();
}
else
{
Serial.println("INVALID GPS Course");
}
Data = Date + ", " + hour + Time + ", " + speed + "mph, ";
Serial.print(Latitude, 4);
Serial.print(",");
Serial.print(Longitude, 4);
Serial.print(", ");
Serial.print(Altitude, 0);
Serial.print("ft, ");
Serial.print(Data);
Serial.print(Dire, 0);
Serial.println("deg");
myFile = SD.open("GPS_Data.txt", FILE_WRITE);
if (myFile) {
Serial.print(F("Logging information to GPS_data.txt..."));
myFile.print(Latitude, 4);
myFile.print(",");
myFile.print(Longitude, 4);
myFile.print(", ");
myFile.print(Altitude, 0);
myFile.print("ft, ");
myFile.print(Data);
myFile.print(Dire, 0);
myFile.println("deg");
Serial.println(F("done."));
myFile.close();
}
else {
Serial.println("error writing information to GPS_data.txt");
}
smartDelay(10000);
}
static void smartDelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (SerialGPS.available())
gps.encode(SerialGPS.read());
} while (millis() - start < ms);
}
GPS_DATA.TXT (681 Bytes)