├── .gitattributes ├── .gitignore ├── README.md └── serial logger.ino /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # ========================= 18 | # Operating System Files 19 | # ========================= 20 | 21 | # OSX 22 | # ========================= 23 | 24 | .DS_Store 25 | .AppleDouble 26 | .LSOverride 27 | 28 | # Icon must end with two \r 29 | Icon 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Arduino-SD-serial-logger 2 | ======================== 3 | 4 | A small arduino program to log data from the UART port 5 | to an SD card very quickly. Works at 115200 baud. 6 | 7 | Files on the SD card are named LOG00000.TXT, LOG00001.TXT, etc 8 | Each file is always 512,000 bytes, and the parts that have not been written to yet are all 0's 9 | 10 | You can increase the arduino's internal serial buffer at 11 | 12 | ``C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\HardwareSerial.cpp`` 13 | 14 | by changing the line `#define SERIAL_BUFFER_SIZE 64`. (Works great when set to 500, but is close to the memory limit) 15 | 16 | 17 | Adopted from the RawWrite.ino example found [here](https://github.com/greiman/FreeRTOS-Arduino/blob/master/libraries/SdFat/examples/RawWrite/RawWrite.ino) 18 | 19 | Also used code from [OpenLog](https://github.com/sparkfun/OpenLog) 20 | -------------------------------------------------------------------------------- /serial logger.ino: -------------------------------------------------------------------------------- 1 | /* 2 | A small arduino program to log data from the UART port 3 | to an SD card very quickly. Works at 115200 baud. 4 | 5 | 6 | Files on the SD card are named LOG00000.TXT, LOG00001.TXT, etc 7 | Each file is always 512,000 bytes, and the parts that have not been written to yet are all 0's 8 | 9 | You can change the arduino's internal serial buffer at C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\HardwareSerial.cpp 10 | by changing the line "#define SERIAL_BUFFER_SIZE 64" 11 | I had it set to 500 12 | 13 | 14 | Adopted from the RawWrite.ino example found here: 15 | https://github.com/greiman/FreeRTOS-Arduino/blob/master/libraries/SdFat/examples/RawWrite/RawWrite.ino 16 | 17 | Also used code from OpenLog 18 | https://github.com/sparkfun/OpenLog 19 | */ 20 | 21 | #include 22 | #include 23 | 24 | // SD chip select pin 25 | #define chipSelect SS 26 | 27 | // number of blocks in the contiguous file 28 | const uint32_t BLOCK_COUNT = 1000UL; 29 | 30 | //make another file if the one fills up 31 | uint32_t currBlock = 0; 32 | 33 | // file system 34 | SdFat sd; 35 | 36 | // test file 37 | SdFile file; 38 | 39 | // file extent 40 | uint32_t bgnBlock, endBlock; 41 | 42 | // Serial output stream 43 | ArduinoOutStream cout(Serial); 44 | //------------------------------------------------------------------------------ 45 | // store error strings in flash to save RAM 46 | #define error(s) sd.errorHalt_P(PSTR(s)) 47 | //------------------------------------------------------------------------------ 48 | 49 | 50 | #define printn Serial.print 51 | #define printf(...) Serial.print(F(__VA_ARGS__)) 52 | 53 | 54 | unsigned int bufferIndex; 55 | 56 | uint8_t* pCache; 57 | 58 | 59 | void makeFile(void) 60 | { 61 | 62 | //Search for next available log spot 63 | char new_file_name[] = "LOG00000.TXT"; 64 | int new_file_number=0; 65 | while(1) 66 | { 67 | new_file_number++; 68 | 69 | //There is a max of 65534 logs 70 | if(new_file_number > 65533) 71 | { 72 | printf(("!Too many logs:2!")); 73 | return; //Bail! 74 | } 75 | 76 | //Splice the new file number into this file name 77 | sprintf(new_file_name, "LOG%05d.TXT", new_file_number); 78 | 79 | //Try to open file, if fail (file doesn't exist), then break 80 | if (file.open(new_file_name, O_CREAT | O_EXCL | O_WRITE)) break; 81 | } 82 | 83 | //Close the new file that was just opened 84 | file.close(); 85 | 86 | // delete existing file that was just created, so it can be recreated as continuous 87 | sd.remove(new_file_name); 88 | 89 | 90 | // create a contiguous file 91 | if (!file.createContiguous(sd.vwd(), new_file_name, 512UL*BLOCK_COUNT)) { 92 | error("createContiguous failed"); 93 | } 94 | // get the location of the file's blocks 95 | if (!file.contiguousRange(&bgnBlock, &endBlock)) { 96 | error("contiguousRange failed"); 97 | } 98 | //*********************NOTE************************************** 99 | // NO SdFile calls are allowed while cache is used for raw writes 100 | //*************************************************************** 101 | 102 | // clear the cache and use it as a 512 byte buffer 103 | pCache = (uint8_t*)sd.vol()->cacheClear(); 104 | 105 | 106 | // tell card to setup for multiple block write with pre-erase 107 | if (!sd.card()->erase(bgnBlock, endBlock)) error("card.erase failed"); 108 | if (!sd.card()->writeStart(bgnBlock, BLOCK_COUNT)) { 109 | error("writeStart failed"); 110 | } 111 | 112 | printf("begin:"); 113 | printn(bgnBlock); 114 | printf("\n"); 115 | printf("end:"); 116 | printn(endBlock); 117 | printf("\n"); 118 | } 119 | 120 | 121 | void setup(void) { 122 | Serial.begin(115200); 123 | while (!Serial) {} // wait for Leonardo 124 | 125 | 126 | cout << pstr("Free RAM: ") << FreeRam() << endl; 127 | 128 | // initialize the SD card at SPI_FULL_SPEED for best performance. 129 | // try SPI_HALF_SPEED if bus errors occur. 130 | if (!sd.begin(chipSelect, SPI_FULL_SPEED)) sd.initErrorHalt(); 131 | 132 | makeFile(); 133 | 134 | } 135 | 136 | char chr; 137 | 138 | //------------------------------------------------------------------------------ 139 | void loop(void) { 140 | 141 | 142 | // write data 143 | while (Serial.available()) 144 | { 145 | 146 | //read the data and record it in the buffer 147 | chr=Serial.read(); 148 | 149 | pCache[bufferIndex]=chr; 150 | bufferIndex++; 151 | 152 | 153 | //flush whenever the the buffer fills up, or when an 18 is recieved 154 | if (bufferIndex==511 || chr==18) 155 | { 156 | 157 | signed int t=millis(); 158 | 159 | // write a 512 byte block 160 | if (!sd.card()->writeData(pCache)) 161 | { 162 | error("writeData failed"); 163 | } 164 | 165 | 166 | //log some info 167 | printf("flushing took "); 168 | printn((signed)millis()-t); 169 | printf(" ms\n"); 170 | printn((char)18); 171 | if(chr==18){ 172 | printf("chr\n"); 173 | } 174 | if (bufferIndex==511) 175 | { 176 | printf("buf\n"); 177 | } 178 | 179 | //reset the count 180 | bufferIndex=0; 181 | currBlock++; 182 | if(currBlock==BLOCK_COUNT){ 183 | 184 | if (!sd.card()->writeStop()) error("writeStop failed"); 185 | 186 | file.close(); 187 | makeFile(); 188 | 189 | currBlock=0; 190 | 191 | } 192 | } 193 | } 194 | } --------------------------------------------------------------------------------