Hello all,
I made a GPS datalogger for some research I am doing based off this. I wanted to show you all, so that, if interested, you could critique my code and offer suggestions/improvements.
Hardware:
Arduino Uno
uSD shield
GPS shield
EM-506 receiver
Murata 5V regulator
What it does: saves gps data to uSD as text files with the date as the name. I put these in trucks and equipment as they operate for up to several days at a time.
Possible improvements that I have thought of:
LED on A0 does not stop blinking if uSD is ejected while powered on
Code does not save a new file at midnight for the next day
Saves a datapoint every second, this could be reduced to every 5 seconds
The possible improvements are things that aren’t necessary but could really improve the operation of my datalogger. These improvements aren’t really things I know how to add in the code yet; if you have suggestions, feel free to let me know. If there are any critical changes I would need to make to the code, feel free to offer them. Thanks all!
// Include libraries
#include <SoftwareSerial.h>
#include <TinyGPS.h>
#include <SD.h>
#include <SPI.h>
// Define variables that will be used
float latitude, longitude, gpsaltitude, gpscourse, gpsspeed;
int year;
byte month, day, hour, minute, second, hundredths;
// Character used to name file on uSD card
char Name[17];
// And counter variables (flags)
int GPS_count=1;
int file_init=0;
// LED pin
int led=A0;
// Chip Select (CS) pin on SD shield is pin 8
const int chipSelect=8;
// The GPS TX and RX pins are 2 and 3, respectively. However,
// these pins are needed elsewhere. Therefore, they will be
// ported to Arduino DI 9 and 10.
#define RXPIN 9
#define TXPIN 10
//EM-506 default baud rate is 4800
#define GPSBAUD 4800
// Create an instance of the TinyGPS object
TinyGPS gps;
// Initialize the SoftwareSerial library to the pins you defined above.
// This tells the Arduino which pins to read serial.
SoftwareSerial uart_gps(RXPIN, TXPIN);
// This is where you declare prototypes for the functions that will be
// using the TinyGPS library.
void getgps(TinyGPS &gps);
// In the setup function, you need to initialize two serial ports; the
// standard hardware serial port (Serial()) to communicate with your
// terminal program an another serial port (NewSoftSerial()) for your
// GPS.
void setup()
{
// This is the serial rate for your terminal program. It must be this
// fast because we need to print everything before a new sentence
// comes in. If you slow it down, the messages might not be valid and
// you will likely get checksum errors.
Serial.begin(115200);
// Sets baud rate of your GPS
uart_gps.begin(GPSBAUD);
// Set chipSelect pin to output (pin 8)
pinMode(chipSelect, OUTPUT);
// LED pin to output (pin A0)
pinMode(led, OUTPUT);
Serial.println("");
Serial.println(" GPS Shield and SD Shield Datalogger ");
Serial.println(" ...INITIALIZING SD CARD... ");
Serial.println();
// Check presence of uSD card, and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println(" **Card failed, or not present** ");
Serial.println();
Serial.println();
}
else {
Serial.println(" **CARD INITIALIZED!** ");
Serial.println();
Serial.println(" ...waiting for GPS lock... ");
Serial.println();
Serial.println();
}
}
// This is the main loop of the code. All it does is check for data on
// the RX pin of the ardiuno, makes sure the data is valid NMEA sentences,
// then jumps to the getgps() function.
void loop()
{
while(uart_gps.available()) // While there is data on the RX pin...
{
int c = uart_gps.read(); // load the data into a variable...
if(gps.encode(c)) // if there is a new valid sentence...
{
getgps(gps); // then grab the data.
write_SD(); // write it to uSD card.
}
}
}
// The getgps function will get and print the values we want.
void getgps(TinyGPS &gps)
{
// To get all of the data into variables that you can use in your code,
// all you need to do is define variables and query the object for the
// data. To see the complete list of functions see keywords.txt file in
// the TinyGPS and NewSoftSerial libs.
// Assign variables
gpsaltitude=gps.f_altitude();
gpscourse=gps.f_course();
gpsspeed=gps.f_speed_kmph();
// Print GPS counter
Serial.print("Point #: ");
Serial.println(GPS_count);
// Function for latitude and longitude
gps.f_get_position(&latitude, &longitude);
Serial.print("Lat/Long: ");
Serial.print(latitude,5);
Serial.print(", ");
Serial.println(longitude,5);
// Date and time
gps.crack_datetime(&year,&month,&day,&hour,&minute,&second,&hundredths);
Serial.print("Date: ");
Serial.print(month, DEC); Serial.print("/");
Serial.print(day, DEC); Serial.print("/");
Serial.println(year);
Serial.print("Time: ");
Serial.print(hour, DEC); Serial.print(":");
Serial.print(minute, DEC); Serial.print(":");
Serial.print(second, DEC); Serial.print(".");
Serial.println(hundredths, DEC);
// Elevation, course and speed
Serial.print("Altitude (m): "); Serial.println(gpsaltitude);
Serial.print("Course (deg): "); Serial.println(gpscourse);
Serial.print("Speed (kmph): "); Serial.println(gpsspeed);
Serial.println();
// Counter increases once per loop iteration.
GPS_count++;
}
// Write_SD takes care of saving data to uSD card.
void write_SD()
{
// Change global variables to local, used for naming uSD card
int lmonth=month;
int lday=day;
// If year is valid and file has not been saved yet, save a file
if (year >= 2015 && file_init==0)
{
//Build a file name string from local variables
sprintf(Name, "%02d%02d.txt", lmonth, lday);
Serial.println(Name); // Print serial name to check
// Counter increases so that filename is only changed once
file_init++;
}
// If filesave is valid, write to it:
if (file_init > 0)
{
// Write to uSD card
File dataFile = SD.open(Name, FILE_WRITE);
// Error
if (!dataFile)
{
Serial.println("Error opening datalog.txt");
return;
}
// GPS counter
dataFile.print(GPS_count); dataFile.print(",");
// Date
dataFile.print(year); dataFile.print(",");
dataFile.print(month, DEC); dataFile.print(",");
dataFile.print(day, DEC); dataFile.print(",");
//Time
dataFile.print(hour, DEC); dataFile.print(",");
dataFile.print(minute, DEC); dataFile.print(",");
dataFile.print(second, DEC); dataFile.print(",");
//Location
dataFile.print(latitude, DEC); dataFile.print(",");
dataFile.print(longitude, DEC); dataFile.print(",");
//Altitude, speed, heading
dataFile.print(gpsaltitude, DEC); dataFile.print(",");
dataFile.print(gpscourse, DEC); dataFile.print(",");
dataFile.print(gpsspeed, DEC);
dataFile.println();
dataFile.close(); //close file
// Blink an LED to indicate
digitalWrite(led, HIGH); // turn the LED on
delay(500); // wait for a second
digitalWrite(led, LOW); // turn the LED off
}
}