Search code examples
cloopsfopenfclose

Is it the right choice to open/close a text file for writing each 0.01 sec?


I have to collect data through an accelerometer, perform some computations and append the result into a text file (in a MicroSD card connected via SPI). The code is working, but I should increase the speed to a log each 0.01 seconds. Is it healthy for the MicroSD to open/close at this speed?

#include "mbed.h"
#include "SDFileSystem.h"

SDFileSystem sd (SPI_MOSI_SD, SPI_MISO_SD, SPI_SCK_SD, SPI_SS_SD, "sd");

int main (void)
{
  mkdir("/sd/data", 0777);
  while (1)
  {
    // record from accelerometer and perform calculations
    FILE *fp = fopen("/sd/data/parameters.txt", "a");
    if(fp == NULL)
    {
      error("Could not open file for write.\n");
    }
    fprintf(fp, "%.4f\n", parameter);
    fclose(fp);
    wait_ms(100);
  }
}

My problem is that the while loop never ends: I have to write data continuously and decide to interrupt only by switching off the device. In this way fclose(fp) never happens.


Solution

  • In my day SD cards typically wrote their data as full sectors even if you were writing one byte. I'm assuming that's still the case so doing it your way would wear a sector many times over without needing to do so. That's why buffering is important. The data should be buffered at around 512 bytes (typical sector size).Build up the buffer until it reaches 512 bytes then flush by writing to SD card.

    char sd_buffer[512];
    unsigned short buffer_idx = 0;
    :
    void append_buffer ( char *str )
    {
       while ( *str )
       {
           sd_buffer[buffer_idx++] = *str++;
    
           if ( buffer_idx >= 512 )
           {
                FILE *fp = fopen("/sd/data/parameters.txt", "a");
                if ( fp == NULL )
                      return; // error
                // flush buffer
                fwrite(sd_buffer,1,512,fp);
                fclose(fp);
                buffer_idx = 0;
           }
       }
    }
    :
    while (1) 
    {
        char buf[32];
        sprintf(buf,"%.4f\n", parameter);
        append_buffer(sd_buffer,buf);
        wait_ms(100);
    }
    

    This just means it will be writing less to the SD card (at each 512 byte interval)

    Disclaimer: untested

    Ps. The open/close the file is now in append_buffer such that any file system buffers are also flushed.

    If you are having problems with loops. Use a state machine