Advertisement
3Domse3

SD Card Data Logger with Buffered Writing

Aug 27th, 2024
30
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Arduino 5.52 KB | Source Code | 0 0
  1. /*
  2.  * SD Card Data Logger with Buffered Writing
  3.  *
  4.  * Developed by: 3Domse3
  5.  * Date: 2024-08-27
  6.  * Version: 2.1
  7.  *
  8.  * Description:
  9.  * This Arduino sketch logs the runtime of the microcontroller in microseconds
  10.  * to an SD card. The data is buffered in memory and written to the SD card in
  11.  * larger chunks to improve efficiency. The filename is generated incrementally
  12.  * to avoid overwriting existing files on the SD card.
  13.  *
  14.  * Hardware:
  15.  * - Arduino board (e.g., UNO, Mega)
  16.  * - SD card module connected via SPI
  17.  * - SD card formatted with FAT16/FAT32
  18.  * - Built-in LED used for error indication
  19.  *
  20.  * Pin Connections:
  21.  * - MOSI (pin 11)
  22.  * - MISO (pin 12)
  23.  * - SCK (pin 13)
  24.  * - CS (pin 4)
  25.  * - Built-in LED (pin 13)
  26.  */
  27.  
  28. /************************** Section 1: Libraries and Constants **************************/
  29.  
  30. #include <SPI.h>
  31. #include <SD.h>
  32.  
  33. // Constants for SD card and LED
  34. const int chipSelect = 4;            // SD card chip select pin
  35. const int ledPin = LED_BUILTIN;       // Built-in LED pin
  36.  
  37. // Constants for buffering data
  38. const int BUFFER_SIZE = 512;          // Buffer size in bytes
  39.  
  40. /************************** Section 2: Global Variables **************************/
  41.  
  42. uint32_t lastMicros = 0;              // Last microsecond value read
  43. uint32_t overflowCount = 0;           // Overflow counter for micros()
  44. uint64_t totalMicros = 0;             // Total elapsed time in microseconds
  45.  
  46. char dataString[20];                  // Buffer for the formatted runtime string
  47. char fileName[13];                    // Buffer for the file name (8.3 format)
  48. char buffer[BUFFER_SIZE];             // Buffer for storing multiple data strings before writing to SD
  49. int bufferIndex = 0;                  // Index to keep track of the current position in the buffer
  50.  
  51. File dataFile;                        // SD file object
  52.  
  53. /************************** Section 3: Setup Function **************************/
  54.  
  55. void setup() {
  56.   pinMode(ledPin, OUTPUT);            // Set the LED pin as output
  57.  
  58.   Serial.begin(115200);
  59.   while (!Serial) {
  60.     ; // Wait for serial port to connect. Needed for native USB port only
  61.   }
  62.  
  63.   // Initialize the SD card
  64.   if (!SD.begin(chipSelect)) {
  65.     Serial.println("Card failed, or not present");
  66.     errorBlink();                     // Blink LED to indicate error
  67.   }
  68.  
  69.   // Generate and print the filename
  70.   getIncrementalFilename(fileName);
  71.   Serial.print("File name: ");
  72.   Serial.println(fileName);
  73.  
  74.   // Open the file for writing
  75.   dataFile = SD.open(fileName, FILE_WRITE);
  76.   if (!dataFile) {
  77.     Serial.println("Failed to open file for writing");
  78.     errorBlink();                     // Blink LED to indicate error
  79.   }
  80.  
  81.   delay(1000);                        // Optional delay before starting logging
  82. }
  83.  
  84. /************************** Section 4: Loop Function **************************/
  85.  
  86. void loop() {
  87.   // Update the runtime buffer with the current runtime
  88.   getRuntime(dataString);
  89.  
  90.   // Add the data to the buffer
  91.   bufferIndex += snprintf(buffer + bufferIndex, BUFFER_SIZE - bufferIndex, "%s\n", dataString);
  92.  
  93.   // If the buffer is full, write it to the SD card
  94.   if (bufferIndex >= BUFFER_SIZE - 20) {  // Leave space for one more line
  95.     writeBufferToSD();
  96.   }
  97.  
  98.   // Optional: Output to serial for debugging
  99.   Serial.println(dataString);
  100. }
  101.  
  102. /************************** Section 5: Runtime Calculation **************************/
  103.  
  104. void getRuntime(char* buffer) {
  105.   uint32_t currentMicros = micros();
  106.  
  107.   // Check for overflow
  108.   if (currentMicros < lastMicros) {
  109.     overflowCount++;
  110.   }
  111.   lastMicros = currentMicros;
  112.  
  113.   // Calculate total elapsed time in microseconds
  114.   totalMicros = ((uint64_t)overflowCount << 32) | (uint64_t)currentMicros;
  115.  
  116.   // Convert the totalMicros to a string and store it in the buffer
  117.   sprintf(buffer, "%01lu", totalMicros);
  118. }
  119.  
  120. /************************** Section 6: Buffer Management **************************/
  121.  
  122. void writeBufferToSD() {
  123.   if (dataFile) {
  124.     dataFile.write(buffer, bufferIndex);  // Write the buffer to the SD card
  125.     dataFile.flush();                     // Ensure data is written to the card
  126.     bufferIndex = 0;                      // Reset buffer index after writing
  127.   } else {
  128.     Serial.println("Error: File not open");
  129.     errorBlink();                         // Blink LED to indicate error
  130.   }
  131. }
  132.  
  133. void flushBufferOnExit() {
  134.   // Ensure any remaining data in the buffer is written to the SD card
  135.   if (bufferIndex > 0) {
  136.     writeBufferToSD();
  137.   }
  138.   dataFile.close();                       // Close the file after writing
  139. }
  140.  
  141. /************************** Section 7: Error Handling **************************/
  142.  
  143. void errorBlink() {
  144.   while (true) {
  145.     digitalWrite(ledPin, HIGH);           // Turn the LED on
  146.     delay(250);                           // Wait for 250 ms
  147.     digitalWrite(ledPin, LOW);            // Turn the LED off
  148.     delay(250);                           // Wait for 250 ms
  149.   }
  150. }
  151.  
  152. /************************** Section 8: Filename Generation **************************/
  153.  
  154. // Generate the next available incremental filename (e.g., "BUF0001.TXT")
  155. void getIncrementalFilename(char* buffer) {
  156.   int number = 1;  // Start with 1 instead of 0 for better readability
  157.  
  158.   do {
  159.     sprintf(buffer, "BUF%04d.TXT", number);
  160.     number++;
  161.   } while (SD.exists(buffer));
  162. }
  163.  
  164. /************************** Section 9: Cleanup on Exit **************************/
  165.  
  166. // Ensure the buffer is flushed before the program exits
  167. void __attribute__((destructor)) cleanup() {
  168.   flushBufferOnExit();
  169. }
  170.  
Tags: C++ Arduino
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement