1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-08-01 03:47:23 +03:00

Combining MemoryCard and SdFat libraries into SD library.

Defaulting to CS pin 4 (for Arduino Ethernet Shield).  Holding the SS pin high (for disabling W5100 on the Ethernet Shield).
This commit is contained in:
David A. Mellis
2010-11-13 14:01:37 -05:00
parent 676ca6aebc
commit 6e449d7f5b
35 changed files with 43 additions and 65 deletions

View File

@ -0,0 +1,387 @@
// 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 <SdFat.h>
#include <SdFatUtil.h>
#include <avr/pgmspace.h>
#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<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
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);
// 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.CSV");
for (i = 0; i < 100; i++) {
buffer[6] = '0' + i/10;
buffer[7] = '0' + i%10;
if (f.open(&root, buffer, O_CREAT | O_EXCL | O_WRITE)) break;
}
if(!f.isOpen()) {
putstring("couldnt create "); Serial.println(buffer);
error(3);
}
putstring("writing to "); Serial.println(buffer);
putstring_nl("ready!");
// write header
if (sensorCount > 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;
}
}
}