GPSLoggerSketch
// 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 "AF_SDLog.h" #include "util.h" #include <avr/pgmspace.h> #include <avr/sleep.h> // power saving modes #define SLEEPDELAY 0 // how long to sleep before reading another NMEA sentence #define TURNOFFGPS 0 // probably only want to do this if the sleep delay > 60 or so #define LOG_RMC_FIXONLY 1 // log only when we get RMC's with fix? AF_SDLog card; File f; #define led1Pin 4 // LED1 connected to digital pin 4 #define led2Pin 3 // LED2 connected to digital pin 3 #define powerPin 2 // GPS power control // set the RX_BUFFER_SIZE to 32! #define BUFFSIZE 75 // we buffer one NMEA sentense at a time, 83 bytes is longer than the max length char buffer[BUFFSIZE]; // this is the double buffer uint8_t bufferidx = 0; #define LOG_RMC 1 // essential location data #define RMC_ON "$PSRF103,4,0,1,1*21\r\n" // the command we send to turn RMC on (1 hz rate) //#define RMC_ON "$PSRF103,4,0,10,1*11\r\n" // 1/30 hz #define RMC_OFF "$PSRF103,4,0,0,1*20\r\n" // the command we send to turn RMC off #define LOG_GGA 1 // contains fix, hdop & vdop data #define GGA_ON "$PSRF103,0,0,1,1*25\r\n" // the command we send to turn GGA on (1 hz rate) #define GGA_OFF "$PSRF103,0,0,0,1*24\r\n" // the command we send to turn GGA off #define LOG_GSA 1 // satelite data #define GSA_ON "$PSRF103,2,0,1,1*27\r\n" // the command we send to turn GSA on (1 hz rate) #define GSA_OFF "$PSRF103,2,0,0,1*26\r\n" // the command we send to turn GSA off #define LOG_GSV 1 // detailed satellite data #define GSV_ON "$PSRF103,3,0,1,1*26\r\n" // the command we send to turn GSV on (1 hz rate) #define GSV_OFF "$PSRF103,3,0,0,1*27\r\n" // the command we send to turn GSV off #define LOG_GLL 0 // Loran-compatibility data // this isnt output by default #define USE_WAAS 1 // useful in US, but slower fix #define WAAS_ON "$PSRF151,1*3F\r\n" // the command for turning on WAAS #define WAAS_OFF "$PSRF151,0*3E\r\n" // the command for turning off WAAS uint8_t fix = 0; // current fix data // 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; } uint8_t i; // blink out an error code void error(uint8_t errno) { 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() // run once, when the sketch starts { WDTCSR |= (1 << WDCE) | (1 << WDE); WDTCSR = 0; Serial.begin(4800); putstring_nl("GPSlogger"); pinMode(led1Pin, OUTPUT); // sets the digital pin as output pinMode(led2Pin, OUTPUT); // sets the digital pin as output pinMode(powerPin, OUTPUT); digitalWrite(powerPin, LOW); if (!card.init_card()) { putstring_nl("Card init. failed!"); error(1); } if (!card.open_partition()) { putstring_nl("No partition!"); error(2); } if (!card.open_filesys()) { putstring_nl("Can't open filesys"); error(3); } if (!card.open_dir("/")) { putstring_nl("Can't open /"); error(4); } strcpy(buffer, "GPSLOG00.TXT"); for (buffer[6] = '0'; buffer[6] <= '9'; buffer[6]++) { for (buffer[7] = '0'; buffer[7] <= '9'; buffer[7]++) { //putstring("\n\rtrying to open ");Serial.println(buffer); f = card.open_file(buffer); if (!f) break; // found a file! card.close_file(f); } if (!f) break; } if(!card.create_file(buffer)) { putstring("couldnt create "); Serial.println(buffer); error(5); } f = card.open_file(buffer); if (!f) { putstring("error opening "); Serial.println(buffer); card.close_file(f); error(6); } putstring("writing to "); Serial.println(buffer); putstring_nl("ready!"); delay(1000); putstring("\r\n"); #if USE_WAAS == 1 putstring(WAAS_ON); // turn on WAAS #else putstring(WAAS_OFF; // turn on WAAS #endif #if LOG_RMC == 1 putstring(RMC_ON); // turn on RMC #else putstring(RMC_OFF); // turn off RMC #endif #if LOG_GSV == 1 putstring(GSV_ON); // turn on GSV #else putstring(GSV_OFF); // turn off GSV #endif #if LOG_GSA == 1 putstring(GSA_ON); // turn on GSA #else putstring(GSA_OFF); // turn off GSA #endif #if LOG_GGA == 1 putstring(GGA_ON); // turn on GGA #else putstring(GGA_OFF); // turn off GGA #endif } void loop() // run over and over again { //Serial.println(Serial.available(), DEC); char c; uint8_t sum; // read one 'line' if (Serial.available()) { c = Serial.read(); //Serial.print(c, BYTE); if (bufferidx == 0) { while (c != '$') c = Serial.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? Serial.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"); Serial.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) { Serial.print('_', BYTE); bufferidx = 0; return; } #endif // rad. lets log it! //Serial.print(buffer); Serial.print('#', BYTE); digitalWrite(led2Pin, HIGH); // sets the digital pin as output if(card.write_file(f, (uint8_t *) buffer, bufferidx) != bufferidx) { putstring_nl("can't write!"); return; } 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) { Serial.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(SIG_WATCHDOG_TIMEOUT) { WDTCSR |= (1 << WDCE) | (1 << WDE); WDTCSR = 0; }
page revision: 0, last edited: 08 Feb 2009 00:29