So I am trying to make a data-logger for my R/C Car and I have the code mostly working, but I am having issues with it writing to the SD card reliably. Most of the code is copied and pasted from the various sample sketches and then modified to supposedly work with what I am trying to do. My main issues are that it seems to log inconsistently and will often have errors in the log such as corrupted files.
What I want it to do is monitor and log all the sensors to a text file that I can later import into excel and overlay onto a FPV as 'live telemetry'. I would like it to log as often as possible, now I know that the GPS is going to be the limiting factor in the logging speed, but I want all other sensors to log as fast as possible and if I get repeat data for the GPS info in the log file that is fine. If I can get this to work I would like to be able to output the max recorded speed and G-force to the LCD screen, I would also like the ability to use the buttons on the LCD screen to start/stop the logging.
Any help would be greatly appreciated!
Here is what I have for hardware:
Arduino UNO R3
Adafruit Ultimate GPS Logger Shield - Adafruit Ultimate GPS Logger Shield - Includes GPS Module : ID 1272 : $29.95 : Adafruit Industries, Unique & fun DIY electronics and kits
Adafruit RGB LCD Shield Kit w/ 16x2 Character Display - RGB LCD Shield Kit w/ 16x2 Character Display - Only 2 pins used! [NEGATIVE DISPLAY] : ID 714 : $24.95 : Adafruit Industries, Unique & fun DIY electronics and kits
Pololu LSM303DLM 3D Compass and Accelerometer Carrier - Pololu - LSM303DLM 3D Compass and Accelerometer Carrier with Voltage Regulators
Pololu L3G4200D 3-Axis Gyro Carrier - Pololu - L3G4200D 3-Axis Gyro Carrier with Voltage Regulator
LM35 Temp Sensor (2x)
Here is the code I currently have:
//#include <avr/pgmspace.h>
#include <SoftwareSerial.h>
#include <Adafruit_GPS.h>
//#include <Adafruit_MCP23017.h>
//#include <Adafruit_RGBLCDShield.h>
#include <L3G.h>
#include <LSM303.h>
#include <Wire.h>
#include <SD.h>
// Adafruit GPS Shield Start Here
SoftwareSerial mySerial(8, 7);
Adafruit_GPS GPS(&mySerial);
const int chipSelect = 10;
// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences
#define GPSECHO true
// this keeps track of whether we're using the interrupt
// off by default!
boolean usingInterrupt = false;
void useInterrupt(boolean); // Func prototype keeps Arduino 0023 happy
// LSM303DLM 3D Compass and Accelerometer Carrier Start Here
LSM303 compass;
// L3G4200D 3-Axis Gyro Carrier Start Here
L3G gyro;
// Adafruit RGB Character LCD Shield Start Here
/*
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
#define RED 0x1
#define YELLOW 0x3
#define GREEN 0x2
#define TEAL 0x6
#define BLUE 0x4
#define VIOLET 0x5
#define WHITE 0x7
*/
void setup()
{
Serial.begin(115200);
// 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800
GPS.begin(9600);
// uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
// uncomment this line to turn on only the "minimum recommended" data
//GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
// For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since
// the parser doesn't care about other sentences at this time
// Set the update rate
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate
// For the parsing code to work nicely and have time to sort thru the data, and
// print it out we don't suggest using anything higher than 1 Hz
// Request updates on antenna status, comment out to keep quiet
GPS.sendCommand(PGCMD_ANTENNA);
// the nice thing about this code is you can have a timer0 interrupt go off
// every 1 millisecond, and read data from the GPS for you. that makes the
// loop code a heck of a lot easier!
useInterrupt(true);
delay(1000);
// Ask for firmware version
mySerial.println(PMTK_Q_RELEASE);
Wire.begin();
if (!gyro.init())
{
Serial.println(F("Failed to autodetect gyro type!"));
while (1);
}
gyro.enableDefault();
compass.init();
compass.enableDefault();
/*
lcd.begin(16, 2);
lcd.setBacklight(WHITE);
*/
Serial.print(F("Initializing SD card..."));
// make sure that the default chip select pin is set to
// output, even if you don't use it:
pinMode(10, OUTPUT);
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println(F("Card failed, or not present"));
// don't do anything more:
return;
}
Serial.println(F("card initialized."));
File dataFile = SD.open("datalog.txt", FILE_WRITE);
if (dataFile) {
dataFile.println(F(" GPS Time , GPS Fix , GPS Quality , Lat , Lon , GPS Speed , GPS Angle , GPS Altitude , GPS Satellites , AX , AY , AZ , MX , MY , MZ , GX , GY , GZ , ESC Temp , Motor Temp "));
dataFile.close();
}
}
// Interrupt is called once a millisecond, looks for any new GPS data, and stores it
SIGNAL(TIMER0_COMPA_vect) {
char c = GPS.read();
// if you want to debug, this is a good time to do it!
#ifdef UDR0
if (GPSECHO)
if (c) UDR0 = c;
// writing direct to UDR0 is much much faster than Serial.print
// but only one character can be written at a time.
#endif
}
void useInterrupt(boolean v) {
if (v) {
// Timer0 is already used for millis() - we'll just interrupt somewhere
// in the middle and call the "Compare A" function above
OCR0A = 0xAF;
TIMSK0 |= _BV(OCIE0A);
usingInterrupt = true;
} else {
// do not call the interrupt function COMPA anymore
TIMSK0 &= ~_BV(OCIE0A);
usingInterrupt = false;
}
}
uint32_t timer = millis();
void loop()
{
// in case you are not using the interrupt above, you'll
// need to 'hand query' the GPS, not suggested :(
if (! usingInterrupt) {
// read data from the GPS in the 'main loop'
char c = GPS.read();
// if you want to debug, this is a good time to do it!
if (GPSECHO)
if (c) Serial.print(c);
}
// if a sentence is received, we can check the checksum, parse it...
if (GPS.newNMEAreceived()) {
// a tricky thing here is if we print the NMEA sentence, or data
// we end up not listening and catching other sentences!
// so be very wary if using OUTPUT_ALLDATA and trytng to print out data
//Serial.println(GPS.lastNMEA()); // this also sets the newNMEAreceived() flag to false
if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false
return; // we can fail to parse a sentence in which case we should just wait for another
}
// if millis() or timer wraps around, we'll just reset it
if (timer > millis()) timer = millis();
// approximately every 2 seconds or so, print out the current stats
if (millis() - timer > 2000) {
timer = millis(); // reset the timer
}
int gpsspeed = (GPS.speed, DEC * 1.151);
compass.read();
gyro.read();
int temp1 = analogRead(A1);
int temp2 = analogRead(A2);
float esctemp = ((((temp1 * (5.0 / 1023.0)) * 100) * 1.8) + 32.0);
float motortemp = ((((temp2 * (5.0 / 1023.0)) * 100) * 1.8) + 32.0);
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
File dataFile = SD.open("datalog.txt", FILE_WRITE);
// if the file is available, write to it:
if (dataFile) {
dataFile.print(GPS.hour, DEC);
dataFile.print(":");
dataFile.print(GPS.minute, DEC);
dataFile.print(":");
dataFile.print(GPS.seconds, DEC);
dataFile.print(".");
dataFile.print(GPS.milliseconds, DEC);
dataFile.print(" , ");
dataFile.print((int)GPS.fix);
dataFile.print(" , ");
dataFile.print((int)GPS.fixquality);
dataFile.print(" , ");
dataFile.print(GPS.latitude, 4); //dataFile.print(GPS.lat);
dataFile.print(" , ");
dataFile.print(GPS.longitude, 4); //dataFile.print(GPS.lon);
dataFile.print(" , ");
dataFile.print(gpsspeed);
dataFile.print(" , ");
dataFile.print(GPS.angle);
dataFile.print(" , ");
dataFile.print(GPS.altitude);
dataFile.print(" , ");
dataFile.print(GPS.satellites);
dataFile.print(" , ");
dataFile.print((int)compass.a.x);
dataFile.print(" , ");
dataFile.print((int)compass.a.y);
dataFile.print(" , ");
dataFile.print((int)compass.a.z);
dataFile.print(" , ");
dataFile.print((int)compass.m.x);
dataFile.print(" , ");
dataFile.print((int)compass.m.y);
dataFile.print(" , ");
dataFile.print((int)compass.m.z);
dataFile.print(" , ");
dataFile.print((int)gyro.g.x);
dataFile.print(" , ");
dataFile.print((int)gyro.g.y);
dataFile.print(" , ");
dataFile.print((int)gyro.g.z);
dataFile.print(" , ");
dataFile.print(esctemp);
dataFile.print(" , ");
dataFile.println(motortemp);
dataFile.close();
}
// if the file isn't open, pop up an error:
else {
Serial.println("error opening datalog.txt");
}
}
DATALOG.TXT (6.06 KB)