// SD logger used with OBDuino // // - If you use it for something else, note that it's configured as 115200,7,N,1 // so remove the UCSR0C line to have 8 bits of data. // - Optimal buffer size is 512 bytes, it works well on a 328p, if you have a 168 // or use a lot of ram, you may have to reduce the buffer, keep a power of 2. // - Data are read char by char but written only by "block" size to optimize // the writting process. // - When the ASCII character EOT (04) is found, file is closed. // - Some error string and debug output on the serial port, if your application // does not like this, just remove them :) #include #include #include Sd2Card card; SdVolume volume; SdFile root; SdFile file; // best if it's a power of 2 #define BUF_SIZE 512 // store error strings in flash to save RAM #define error(s) error_P(PSTR(s)) void error_P(const char* str) { PgmPrint("error: "); SerialPrintln_P(str); if (card.errorCode()) { PgmPrint("SD error: "); Serial.print(card.errorCode(), HEX); Serial.print(','); Serial.println(card.errorData(), HEX); } while(1); } void setup(void) { Serial.begin(115200); // set to 7,N,1 UCSR0C = _BV(UCSZ01); //N71 // set sleep mode of the AVR, idle set_sleep_mode(SLEEP_MODE_IDLE); } void loop(void) { byte card_inited, EOT, nf; char c, buf[BUF_SIZE]; char str[15]; int r; unsigned int idx; card_inited=EOT=0; // will get out of loop if EndOfTransmission or write fail do { idx=0; for (;;) { // wait for a char while( Serial.available() == 0) { sleep_mode(); } if(!card_inited) { // 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)) error("card.init failed"); // initialize a FAT volume if (!volume.init(&card)) error("volume.init failed"); // open root directory if (!root.openRoot(&volume)) error("openRoot failed"); // open a new trip file nf=1; do { sprintf_P(str, PSTR("TRIP%04d.CSV"), nf++); // open will fail if the file already exists // so we will loop and open a new one Serial.print("try "); Serial.println(str); r=file.open(&root, str, O_CREAT | O_EXCL | O_WRITE); } while(r==0); if (!file.isOpen()) error ("file.create"); card_inited=1; } // get the char c=Serial.read(); // is it a ctrl-d (EOT)? if(c=='\004') { EOT=1; break; // the for } else { // put in buffer buf[idx++] = c; if(idx==BUF_SIZE) break; // the for } } // end of for // write to file r=file.write(buf, idx); // r return number of bytes written (should be the same as idx) } while(!EOT && r>=0); // we are here if EndOfTransmission or write fail // close file file.close(); // close root directory root.close(); // we will return at the top of the function, waiting for a char }