// 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 uint8_t sensorCount = 3; //number of analog pins to log #include #include #include #define isdigit(x) ( x >= '0' && x <= '9') //extern uint16_t _end; Sd2Card card; SdVolume volume; SdFile root; SdFile 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 73 // we buffer one NMEA sentence at a time, 83 bytes is longer than the max length char buffer[BUFFSIZE]; // this is the double buffer char buffer2[12]; uint8_t bufferidx = 0; uint32_t tmp; #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_OFF "$PSRF103,4,0,0,1*20\r\n" // the command we send to turn RMC off #define LOG_GGA 0 // 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 0 // satellite 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 0 // 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 #define LOG_RMC_FIXONLY 1 // log only when we get RMC's with fix? uint8_t fix = 0; // current fix data // macros to use PSTR #define putstring(str) SerialPrint_P(PSTR(str)) #define putstring_nl(str) SerialPrintln_P(PSTR(str)) // 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) { if (card.errorCode()) { putstring("SD error: "); Serial.print(card.errorCode(), HEX); Serial.print(','); Serial.println(card.errorData(), HEX); } while(1) { for (i=0; i 6) sensorCount = 6; strncpy_P(buffer, PSTR("time,lat,long,speed,date,sens0,sens1,sens2,sens3,sens4,sens5"), 24 + 6*sensorCount); Serial.println(buffer); // clear print error f.writeError = 0; f.println(buffer); if (f.writeError || !f.sync()) { putstring_nl("can't write header!"); error(5); } 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; } } else { // not GPRMC bufferidx = 0; return; } #if LOG_RMC_FIXONLY if (!fix) { Serial.print('_', BYTE); bufferidx = 0; return; } #endif // rad. lets print it! Serial.print(buffer); // time to clean up the string // find time char *p = buffer; p = strchr(p, ',')+1; buffer[0] = p[0]; buffer[1] = p[1]; buffer[2] = ':'; buffer[3] = p[2]; buffer[4] = p[3]; buffer[5] = ':'; buffer[6] = p[4]; buffer[7] = p[5]; // we ignore milliseconds buffer[8] = ','; p = strchr(buffer+8, ',')+1; // skip past 'active' flag p = strchr(p, ',')+1; // find lat p = strchr(p, ',')+1; buffer[9] = '+'; buffer[10] = p[0]; buffer[11] = p[1]; buffer[12] = ' '; strncpy(buffer+13, p+2, 7); buffer[20] = ','; p = strchr(buffer+21, ',')+1; if (p[0] == 'S') buffer[9] = '-'; // find long p = strchr(p, ',')+1; buffer[21] = '+'; buffer[22] = p[0]; buffer[23] = p[1]; buffer[24] = p[2]; buffer[25] = ' '; strncpy(buffer+26, p+3, 7); buffer[33] = ','; p = strchr(buffer+34, ',')+1; if (p[0] == 'W') buffer[21] = '-'; // find speed p = strchr(p, ',')+1; tmp = 0; if (p[0] != ',') { // ok there is some sort of speed while (p[0] != '.' && p[0] != ',') { tmp *= 10; tmp += p[0] - '0'; p++; } tmp *= 10; if (isdigit(p[1])) tmp += p[1] - '0'; // tenths tmp *= 10; if (isdigit(p[2])) tmp += p[2] - '0'; // hundredths // tmp is knots * 100 // convert to mph (1.15 mph = 1 knot) tmp *= 115; // -OR- convert km/h // tmp *= 185 } tmp /= 100; buffer[34] = (tmp / 10000) + '0'; tmp %= 10000; buffer[35] = (tmp / 1000) + '0'; tmp %= 1000; buffer[36] = (tmp / 100) + '0'; tmp %= 100; buffer[37] = '.'; buffer[38] = (tmp / 10) + '0'; tmp %= 10; buffer[39] = tmp + '0'; buffer[40] = ','; p = strchr(p, ',')+1; // skip past bearing p = strchr(p, ',')+1; //mod for bug when speed,bearing are missing (bill greiman) uint8_t date[6]; for (uint8_t id = 0; id < 6; id++) date[id] = p[id]; // get date into 2001-01-31 style buffer[41] = '2'; buffer[42] = '0'; buffer[43] = date[4]; buffer[44] = date[5]; buffer[45] = '-'; buffer[46] = date[2]; buffer[47] = date[3]; buffer[48] = '-'; buffer[49] = date[0]; buffer[50] = date[1]; buffer[51] = 0; digitalWrite(led2Pin, HIGH); if(f.write((uint8_t *) buffer, 51) != 51) { putstring_nl("can't write fix!"); return; } Serial.print(buffer); // clear print error f.writeError = 0; // add sensor data for (uint8_t ia = 0; ia < sensorCount; ia++) { Serial.print(','); f.print(','); uint16_t data = analogRead(ia); Serial.print(data); f.print(data); } Serial.println(); f.println(); if (f.writeError || !f.sync()) { putstring_nl("can't write data!"); error(4); } digitalWrite(led2Pin, LOW); bufferidx = 0; return; } bufferidx++; if (bufferidx == BUFFSIZE-1) { Serial.print('!', BYTE); bufferidx = 0; } } }