I am trying to pull gps data from my adafruit ultimate gps sheild and datalog it to an sd card using my UNO rev3. I am having an issue where in the serial monitor it shows "Initializing SD card...card initialized." repeating over and over until I disconnect the Arduino. I started with a new sketch, and added small chunks of my code until I found the parts doing it. As soon as I add "File dataFile = SD.open("datalog.csv",FILE_WRITE);" it will throw 4-5 lines of the card initialized, but then when I add else statement at the bottom, thats when it starts doing an endless loop of displaying the card initialized line. Any pointers would be excellent. Im fairly new to this, but have been comparing what I have to other sketches, and I am not seeing where things are going wrong.
The SD card is an 8gig card formated as fat32. I have run the sketches in the SD library, and it will pull the SD card data, so at this point I dont think its the card. I do have a few others on their way to mess with though.
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#include <SPI.h>
#include <SD.h>
SoftwareSerial mySerial(8, 7);
Adafruit_GPS GPS(&mySerial);
#define GPSECHO true
#define chipSelect 10
File datafile;
void setup() {
Serial.begin(115200);
pinMode(10, OUTPUT);
pinMode(10, HIGH);
Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// don't do anything more:
while (1);
}
Serial.println("card initialized.");
GPS.begin(9600);
//GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_10HZ);
delay(250);
}
uint32_t timer = millis();
void loop() {
char c = GPS.read();
if (c)
//Serial.write(c);
if (GPS.newNMEAreceived()) {
if (!GPS.parse(GPS.lastNMEA()))
return;
}
if (timer > millis()) timer = millis();
if (millis() - timer > 250) {
timer = millis();
}
float mph;
mph = (GPS.speed) * 1.15;
String timestamp = String(GPS.hour, DEC) + (":") + String(GPS.minute, DEC) + (":") + String(GPS.seconds, DEC);
String date = String(GPS.month, DEC) + ("/") + String(GPS.day, DEC) + ("/20") + String(GPS.year, DEC);
File dataFile = SD.open("datalog.csv",FILE_WRITE);
if (datafile) {
if (GPS.fix == 1) {
Serial.print("Date: ");
//Serial.print(date);
Serial.print(", ");
//Serial.print(timestamp);
Serial.print(", ");
Serial.print(GPS.latitudeDegrees, 8);
Serial.print(", ");
Serial.print(GPS.longitudeDegrees, 8);
Serial.print(", ");
Serial.print("Speed: ");
Serial.println(mph);
datafile.print(GPS.latitudeDegrees, 8);
datafile.print(", ");
datafile.println(GPS.longitudeDegrees, 8);
datafile.close();
}
// if the file isn't open, pop up an error:
else {
Serial.println("error opening datalog.csv");
}
}
}
You should not open the file, write a bit of data and close it again, as that vastly increases the error rate and the current draw (an entire sector buffer has be read and written each open/close).
Open the file once in setup(), write a bunch of data, and when you are done collecting, close the file. You should occasionally execute datafile.flush(); (e.g. every hour or day) to keep the file pointers updated.
That may not be not the cause of the .begin() problem, though. Perhaps the Arduino is resetting/rebooting due to an inadequate power supply. Post the details of the setup.
for this project a push button wouldnt be possible. maybe for testing it could, but in the end it needs to start and stop recording based on vehicle speed. I havent got that point of the project though. I just wanted to validate that things could be written to the SD card at this point.
the File dataFile = SD.open was a typo, that should have been
File datafile = SD.open
So in the code now, I have removed the File datafile; and now I have the below. When I compile it, I get an error "Compilation error: 'dataFile' was not declared in this scope". In the IDE it has this highlighted for the error.
if (datafile) {
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#include <SPI.h>
#include <SD.h>
SoftwareSerial mySerial(8, 7);
Adafruit_GPS GPS(&mySerial);
#define GPSECHO true
#define chipSelect 10
void setup() {
Serial.begin(115200);
pinMode(10, OUTPUT);
pinMode(10, HIGH);
Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// don't do anything more:
while (1);
}
Serial.println("card initialized.");
File datafile = SD.open("datalog.csv",FILE_WRITE);
GPS.begin(9600);
//GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_10HZ);
delay(250);
}
uint32_t timer = millis();
void loop() {
char c = GPS.read();
if (c)
//Serial.write(c);
if (GPS.newNMEAreceived()) {
if (!GPS.parse(GPS.lastNMEA()))
return;
}
if (timer > millis()) timer = millis();
if (millis() - timer > 250) {
timer = millis();
}
float mph;
mph = (GPS.speed) * 1.15;
String timestamp = String(GPS.hour, DEC) + (":") + String(GPS.minute, DEC) + (":") + String(GPS.seconds, DEC);
String date = String(GPS.month, DEC) + ("/") + String(GPS.day, DEC) + ("/20") + String(GPS.year, DEC);
if (datafile) {
if (GPS.fix == 1) {
Serial.print("Date: ");
//Serial.print(date);
Serial.print(", ");
//Serial.print(timestamp);
Serial.print(", ");
Serial.print(GPS.latitudeDegrees, 8);
Serial.print(", ");
Serial.print(GPS.longitudeDegrees, 8);
Serial.print(", ");
Serial.print("Speed: ");
Serial.println(mph);
datafile.print(GPS.latitudeDegrees, 8);
datafile.print(", ");
datafile.println(GPS.longitudeDegrees, 8);
datafile.close();
}
// if the file isn't open, pop up an error:
else {
Serial.println("error opening datalog.csv");
}
}
}
Put this above setup() to declare a global variable, and remove the "File" keyword from the open statement.
You are strongly advised to avoid using Strings. They are never necessary, and on AVR-based Arduinos, they lead to memory corruption and program crashes.
Looks like the Arduino is rebooting. That is typically a power supply problem.
SD cards are power hungry, and a write operation can draw a hundred mA or more. You may be overloading the 3.3V regulator, if that is where the SD card power is coming from.
Tha'ts because datafile is a local variable declared in setup(). Declare it as a global
File datafile;
Then use it anywhere in the sketch but do not precede its name with File as this will create a second variable with the same name but a different scope
looking at the data sheet, it appears to be 3.3v, so is the SD card something that just isnt going to work with the UNO then do you know? Is there another route that you would suggest that would work for this?
The SD card is strictly 3.3V and cannot be directly connected to a 5V Arduino without logic level shifters. However the card module may have shifters on board.
Please post links to the modules, a wiring diagram and a photo of the setup.
char c = GPS.read();
You should be checking whether characters are available before reading. There appear to be quite a number of problems with the code,