Skip to content

Instantly share code, notes, and snippets.

@jrleeman
Last active August 29, 2015 14:18
Show Gist options
  • Save jrleeman/5a081752ddb1ff7b8300 to your computer and use it in GitHub Desktop.
Save jrleeman/5a081752ddb1ff7b8300 to your computer and use it in GitHub Desktop.
Logs tilt meter and GPS data from a Jewell D700 tilt meter and Adafruit Ultimate GPS logger shield.
#include <SPI.h>
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#include <SD.h>
#include <avr/sleep.h>
// Make software serial port for GPS and GPS instance
SoftwareSerial mySerial(8, 7);
Adafruit_GPS GPS(&mySerial);
// Variables and defines
#define chipSelect 10
#define REDLED 3
#define GRNLED 4
int current_hour = 99;
boolean usingInterrupt = false;
boolean writeTilt = false;
boolean writeGPS = false;
void useInterrupt(boolean); // Func prototype keeps Arduino 0023 happy
char buffer[80];
char *stringptr;
uint8_t index = 0;
File logfile;
void error(uint8_t errno) {
/*
Blink out error codes based on an integer input.
First making sure that all status LEDS are off.
*/
digitalWrite(REDLED, LOW);
digitalWrite(GRNLED, LOW);
while(1) {
uint8_t i;
for (i=0; i < errno; i++) {
digitalWrite(REDLED, HIGH);
delay(100);
digitalWrite(REDLED, LOW);
delay(100);
}
for (i=errno; i<10; i++) {
delay(200);
}
}
}
void setup() {
/*
Do the setup of the GPS, tilt meter, output pins, SD card, etc.
This is where lots could go wrong if things are not hooked up correctly.
*/
// Setup the LED pins and the CS pin for the SD card as output
pinMode(REDLED, OUTPUT);
pinMode(GRNLED, OUTPUT);
pinMode(10, OUTPUT);
// Turn on the LEDs to show that we are in setup
digitalWrite(REDLED, HIGH);
digitalWrite(GRNLED, HIGH);
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect, 11, 12, 13)) {
error(2);
}
// connect to the GPS at the desired rate
GPS.begin(9600);
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
GPS.sendCommand(PGCMD_NOANTENNA);
useInterrupt(true);
// Start and setup the tilt meter
Serial.begin(9600);
delay(1000);
int bytesSent = Serial.write("*9900XY-SET-BAUDRATE,9600\n"); // Set baudrate on tilt meter
delay(1000);
bytesSent += Serial.write("*9900SO-XDR\n"); // Set to NMEA XDR format
delay(1000);
bytesSent += Serial.write("*9900XYC2\n"); // Set to 1 Hz output
delay(2000);
// DO ERROR CHECKING
// Turn off the LEDs to show that we are done, blink them twice
digitalWrite(REDLED, LOW);
digitalWrite(GRNLED, LOW);
for (int i=0; i < 2; i++) {
delay(1000);
digitalWrite(REDLED, HIGH);
digitalWrite(GRNLED, HIGH);
delay(1000);
digitalWrite(REDLED, LOW);
digitalWrite(GRNLED, LOW);
}
}
// Interrupt is called once a millisecond, looks for any new GPS data, and stores it
SIGNAL(TIMER0_COMPA_vect) {
char c = GPS.read();
}
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;
}
}
void loop() {
// Grab any serial from the GPS and store it
if (GPS.newNMEAreceived()) {
stringptr = GPS.lastNMEA();
writeGPS = true;
}
// Grab any serial from the Tiltmeter and store it
while (Serial.available() > 0) {
if (index < 80) {
char inChar = Serial.read();
buffer[index] = inChar;
index++;
if (inChar == '\n'){
writeTilt = true;
index = 0;
}
}
}
// Process the GPS data if we can
if (writeGPS) {
GPS.parse(stringptr);
// Check and deal with the need for a new logging file
if (GPS.hour != current_hour){
logfile.close();
char name[13];
getLogFileName(name,GPS.day,GPS.month,GPS.year,GPS.hour);
// Prevent over-writing by adding to the sub-sequence set
for (uint8_t i = 0; i < 10; i++) {
name[7] = '0' + i;
if (! SD.exists(name)) {
break;
}
}
// Open the new file and set the current hour to the new hour
logfile = SD.open(name, FILE_WRITE);
if( ! logfile ) {
error(1);
}
current_hour = GPS.hour;
}
digitalWrite(REDLED, HIGH);
uint8_t stringsize = strlen(stringptr);
if (stringsize != logfile.write((uint8_t *)stringptr, stringsize)) //write the string to the SD file
error(4);
if (strstr(stringptr, "RMC") || strstr(stringptr, "GGA"))
logfile.flush();
digitalWrite(REDLED, LOW);
writeGPS = false;
}
// Log the tiltmeter data if we are ready
if (writeTilt){
digitalWrite(GRNLED, HIGH);
//uint8_t stringsize = strlen(buffer);
//if (stringsize != logfile.write((uint8_t *)stringptr, buffer)) //write the string to the SD file
// error(4);
//if (strstr(stringptr, "XDR"))
// logfile.flush();
logfile.write(buffer);
digitalWrite(GRNLED, LOW);
writeTilt = false;
}
}
char getLogFileName(char *filename, int day, int month, int year, int hour) {
/*
Format is DDDYYHHA.DAT
DDD - Day of year
YY - Year
NN - Logger unit number
A - Sub-sequence name, used if more than one file/day
*/
strcpy(filename, "");
strcpy(filename, "00000000.DAT");
// Get day of year and set it
int doy = calculateDayOfYear(day, month, year);
filename[0] = '0' + (doy/100)%100;
filename[1] = '0' + (doy/10)%10;
filename[2] = '0' + doy%10;
// Set the year
filename[3] = '0' + (year/10)%10;
filename[4] = '0' + year%10;
// Set the hour
filename[5] = '0' + (hour/10)%10;
filename[6] = '0' + hour%10;
}
int calculateDayOfYear(int day, int month, int year) {
/*
Given a day, month, and year (2 or 4 digit), returns
the day of year. Errors return 999.
*/
// List of days in a month for a normal year
int daysInMonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
// Check if it is a leap year
if (year%4 == 0)
{
daysInMonth[1] = 29;
}
// Make sure we are on a valid day of the month
if (day < 1)
{
return 999;
} else if (day > daysInMonth[month-1]) {
return 999;
}
int doy = 0;
for (int i = 0; i < month - 1; i++) {
doy += daysInMonth[i];
}
doy += day;
return doy;
}
/* End code */
/*
for( int i = 0; i < sizeof(data); ++i )
data[i] = (char)0;
to clear data
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment