Created
May 7, 2013 09:10
-
-
Save anonymous/5531319 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Ladyada's logger modified by Bill Greiman to use the SdFat library | |
// this is a generic logger that does checksum testing so the data written should be always good | |
// Assumes a sirf III chipset logger attached to pin 0 and 1 | |
#include <Ethernet.h> | |
#include <SdFat.h> | |
#include <SdFatUtil.h> | |
//#include <avr/sleep.h> | |
// macros to use PSTR | |
#define putstring(str) SerialPrint_P(PSTR(str)) | |
#define putstring_nl(str) SerialPrintln_P(PSTR(str)) | |
// power saving modes | |
#define SLEEPDELAY 0 | |
#define TURNOFFGPS 0 | |
#define LOG_RMC_FIXONLY 1 | |
Sd2Card card; | |
SdVolume volume; | |
SdFile root; | |
SdFile f; | |
#define led1Pin 4 | |
#define led2Pin 3 | |
#define powerPin 2 | |
#define BUFFSIZE 75 | |
char buffer[BUFFSIZE]; | |
uint8_t bufferidx = 0; | |
uint8_t fix = 0; // current fix data | |
uint8_t i; | |
/* EXAMPLE | |
$PSRF103,<msg>,<mode>,<rate>,<cksumEnable>*CKSUM<CR><LF> | |
<msg> 00=GGA,01=GLL,02=GSA,03=GSV,04=RMC,05=VTG | |
<mode> 00=SetRate,01=Query | |
<rate> Output every <rate>seconds, off=00,max=255 | |
<cksumEnable> 00=disable Checksum,01=Enable checksum for specified message | |
Note: checksum is required | |
Example 1: Query the GGA message with checksum enabled | |
$PSRF103,00,01,00,01*25 | |
Example 2: Enable VTG message for a 1Hz constant output with checksum enabled | |
$PSRF103,05,00,01,01*20 | |
Example 3: Disable VTG message | |
$PSRF103,05,00,00,01*21 | |
*/ | |
#define SERIAL_SET "$PSRF100,01,4800,08,01,00*0E\r\n" | |
// GGA-Global Positioning System Fixed Data, message 103,00 | |
#define LOG_GGA 0 | |
#define GGA_ON "$PSRF103,00,00,01,01*25\r\n" | |
#define GGA_OFF "$PSRF103,00,00,00,01*24\r\n" | |
// GLL-Geographic Position-Latitude/Longitude, message 103,01 | |
#define LOG_GLL 0 | |
#define GLL_ON "$PSRF103,01,00,01,01*26\r\n" | |
#define GLL_OFF "$PSRF103,01,00,00,01*27\r\n" | |
// GSA-GNSS DOP and Active Satellites, message 103,02 | |
#define LOG_GSA 0 | |
#define GSA_ON "$PSRF103,02,00,01,01*27\r\n" | |
#define GSA_OFF "$PSRF103,02,00,00,01*26\r\n" | |
// GSV-GNSS Satellites in View, message 103,03 | |
#define LOG_GSV 0 | |
#define GSV_ON "$PSRF103,03,00,01,01*26\r\n" | |
#define GSV_OFF "$PSRF103,03,00,00,01*27\r\n" | |
// RMC-Recommended Minimum Specific GNSS Data, message 103,04 | |
#define LOG_RMC 1 | |
#define RMC_ON "$PSRF103,04,00,01,01*21\r\n" | |
#define RMC_OFF "$PSRF103,04,00,00,01*20\r\n" | |
// VTG-Course Over Ground and Ground Speed, message 103,05 | |
#define LOG_VTG 0 | |
#define VTG_ON "$PSRF103,05,00,01,01*20\r\n" | |
#define VTG_OFF "$PSRF103,05,00,00,01*21\r\n" | |
// Switch Development Data Messages On/Off, message 105 | |
#define LOG_DDM 1 | |
#define DDM_ON "$PSRF105,01*3E\r\n" | |
#define DDM_OFF "$PSRF105,00*3F\r\n" | |
#define USE_WAAS 0 // useful in US, but slower fix | |
#define WAAS_ON "$PSRF151,01*3F\r\n" // the command for turning on WAAS | |
#define WAAS_OFF "$PSRF151,00*3E\r\n" // the command for turning off WAAS | |
// read a Hex value and return the decimal equivalent | |
uint8_t parseHex(char c) { | |
if (c < '0') | |
return 0; | |
if (c <= '9') | |
return c - '0'; | |
if (c < 'A') | |
return 0; | |
if (c <= 'F') | |
return (c - 'A')+10; | |
} | |
// blink out an error code | |
void error(uint8_t errno) { | |
if (card.errorCode()) { | |
putstring("SD error: "); | |
SerialUSB.print(card.errorCode(), HEX); | |
SerialUSB.print(','); | |
SerialUSB.println(card.errorData(), HEX); | |
} | |
while(1) { | |
for (i=0; i<errno; i++) { | |
digitalWrite(led1Pin, HIGH); | |
digitalWrite(led2Pin, HIGH); | |
delay(100); | |
digitalWrite(led1Pin, LOW); | |
digitalWrite(led2Pin, LOW); | |
delay(100); | |
} | |
for (; i<10; i++) { | |
delay(200); | |
} | |
} | |
} | |
void setup() { | |
//WDTCSR |= (1 << WDCE) | (1 << WDE); | |
//WDTCSR = 0; | |
//Serial3.begin(BPS_4800); | |
Serial3.begin(4800); | |
putstring_nl("\r\nGPSlogger"); | |
pinMode(led1Pin, OUTPUT); | |
pinMode(led2Pin, OUTPUT); | |
pinMode(powerPin, OUTPUT); | |
digitalWrite(powerPin, LOW); | |
// initialize the SD card at SPI_HALF_SPEED to avoid bus errors with | |
// breadboards. use SPI_FULL_SPEED for better performance. | |
if (!card.init(SPI_HALF_SPEED)) { | |
putstring_nl("Card init. failed!"); | |
error(1); | |
} | |
if (!volume.init(&card)) { | |
putstring_nl("No partition!"); | |
error(2); | |
} | |
if(!root.openRoot(&volume)) { | |
putstring_nl("Can't! open root dir"); | |
error(3); | |
} | |
strcpy(buffer, "GPSLOG00.TXT"); | |
for (i = 0; i < 100; i++) { | |
buffer[6] = '0' + i/10; | |
buffer[7] = '0' + i%10; | |
// create if does not exist, do not open existing, write, sync after write | |
if (f.open(&root, buffer, O_CREAT | O_EXCL | O_WRITE | O_SYNC)) break; | |
} | |
if(!f.isOpen()) { | |
putstring("couldnt create "); SerialUSB.println(buffer); | |
error(3); | |
} | |
putstring("writing to "); SerialUSB.println(buffer); | |
putstring_nl("ready!"); | |
putstring(SERIAL_SET); | |
delay(250); | |
if (LOG_DDM){ | |
putstring(DDM_ON);} | |
else | |
{putstring(DDM_OFF);} | |
delay(250); | |
if (LOG_GGA) | |
{putstring(GGA_ON);} | |
else | |
{putstring(GGA_OFF);} | |
delay(250); | |
if (LOG_GLL) | |
{putstring(GLL_ON);} | |
else | |
{putstring(GLL_OFF);} | |
delay(250); | |
if (LOG_GSA) | |
{putstring(GSA_ON);} | |
else | |
{putstring(GSA_OFF);} | |
delay(250); | |
if (LOG_GSV) | |
{putstring(GSV_ON);} | |
else | |
{putstring(GSV_OFF);} | |
delay(250); | |
if (LOG_RMC) | |
{putstring(RMC_ON);} | |
else | |
{putstring(RMC_OFF);} | |
delay(250); | |
if (LOG_VTG) | |
{putstring(VTG_ON);} | |
else | |
{putstring(VTG_OFF);} | |
delay(250); | |
if (USE_WAAS) | |
{putstring(WAAS_ON);} | |
else | |
{putstring(WAAS_OFF);} | |
} | |
void loop() { | |
//Serial.println(Serial.available(), DEC); | |
char c; | |
uint8_t sum; | |
// read one 'line' | |
if (Serial3.available()) { | |
c = Serial3.read(); | |
//Serial.print(c, BYTE); | |
if (bufferidx == 0) { | |
while (c != '$') | |
c = Serial3.read(); // wait till we get a $ | |
} | |
buffer[bufferidx] = c; | |
//Serial.print(c, BYTE); | |
if (c == '\n') { | |
//putstring_nl("EOL"); | |
//Serial.print(buffer); | |
buffer[bufferidx+1] = 0; // terminate it | |
if (buffer[bufferidx-4] != '*') { | |
// no checksum? | |
SerialUSB.print('*', BYTE); | |
bufferidx = 0; | |
return; | |
} | |
// get checksum | |
sum = parseHex(buffer[bufferidx-3]) * 16; | |
sum += parseHex(buffer[bufferidx-2]); | |
// check checksum | |
for (i=1; i < (bufferidx-4); i++) { | |
sum ^= buffer[i]; | |
} | |
if (sum != 0) { | |
//putstring_nl("Cxsum mismatch"); | |
SerialUSB.print('~', BYTE); | |
bufferidx = 0; | |
return; | |
} | |
// got good data! | |
if (strstr(buffer, "GPRMC")) { | |
// find out if we got a fix | |
char *p = buffer; | |
p = strchr(p, ',')+1; | |
p = strchr(p, ',')+1; // skip to 3rd item | |
if (p[0] == 'V') { | |
digitalWrite(led1Pin, LOW); | |
fix = 0; | |
} else { | |
digitalWrite(led1Pin, HIGH); | |
fix = 1; | |
} | |
} | |
if (LOG_RMC_FIXONLY) { | |
if (!fix) { | |
SerialUSB.print('_', BYTE); | |
bufferidx = 0; | |
return; | |
} | |
} | |
// rad. lets log it! | |
SerialUSB.print(buffer); | |
SerialUSB.print('#', BYTE); | |
digitalWrite(led2Pin, HIGH); // sets the digital pin as output | |
// Bill Greiman - need to write bufferidx + 1 bytes to getCR/LF | |
bufferidx++; | |
if(f.write((uint8_t *) buffer, bufferidx) != bufferidx) { | |
putstring_nl("can't write!"); | |
error(4); | |
} | |
digitalWrite(led2Pin, LOW); | |
bufferidx = 0; | |
// turn off GPS module? | |
if (TURNOFFGPS) { | |
digitalWrite(powerPin, HIGH); | |
} | |
//sleep_sec(SLEEPDELAY); | |
digitalWrite(powerPin, LOW); | |
return; | |
} | |
bufferidx++; | |
if (bufferidx == BUFFSIZE-1) { | |
SerialUSB.print('!', BYTE); | |
bufferidx = 0; | |
} | |
} else { | |
} | |
} | |
//void sleep_sec(uint8_t x) { | |
// while (x--) { | |
// // set the WDT to wake us up! | |
// WDTCSR |= (1 << WDCE) | (1 << WDE); // enable watchdog & enable changing it | |
// WDTCSR = (1<< WDE) | (1 <<WDP2) | (1 << WDP1); | |
// WDTCSR |= (1<< WDIE); | |
// set_sleep_mode(SLEEP_MODE_PWR_DOWN); | |
// sleep_enable(); | |
// sleep_mode(); | |
// sleep_disable(); | |
// } | |
//} | |
//SIGNAL(WDT_vect) { | |
// WDTCSR |= (1 << WDCE) | (1 << WDE); | |
// WDTCSR = 0; | |
//} | |
/* End code */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment