Write frequency to SD Card
응답
19. 7. 10 오전 2:23

Hi all,

Yes, yet another Accelerometer to SD Card post. I've managed to get a basic code to do so, but the issue I'm having is the rate at which these readings get saved. 

Currently I'm getting about 68 readings per second (calculated using very rudimental methods, ie, stopwatch). I'm testing with the XDK connected through USB and displaying a counter to the console after every write operation. 

The thing is, when I disable (//comment) the SD card writing function after reading the sensor, I suddenly get around 330 readings per second (or at least the counter goes faster). 

I'm using a SDHC 16GB Class 10 card.

Can anybody shed any light on the issue at hand? 

Please find code attached: 

P.S: For testing purposes, a file named "Test.txt" is needed in the SD Card.

Thank you very much!

#include "XdkAppInfo.h"
#undef BCDS_MODULE_ID
#define BCDS_MODULE_ID XDK_APP_MODULE_ID_APP_CONTROLLER
#include <stdio.h>
#include "BCDS_CmdProcessor.h"
#include <FreeRTOS.h>
#include "timers.h"

// SD Card Related Headers

#include "BCDS_SDCard_Driver.h"
#include "ff.h"

// Sensor Related Headers

#include "AppController.h"
#include "XdkSensorHandle.h"

static CmdProcessor_T * AppCmdProcessor;

// SD Card Related Declarations

#define DEFAULT_LOGICAL_DRIVE   ""
#define DRIVE_ZERO              UINT8_C(0)
#define FORCE_MOUNT             UINT8_C(1)
#define FIRST_LOCATION          UINT8_C(0)

static FIL fileObject;

static int counter = 0;
static const char Filename[] = "Test.txt";
static char readings [100];
static int fileSize = 0;


Retcode_T searchForFileOnSdCard(const char* filename, FILINFO* fileData){

  if(FR_OK == f_stat(filename, fileData)){ // @suppress("Symbol is not resolved")
        return RETCODE_OK;
  } else {
    printf("File %s does not exist. \n\r",filename);
    return RETCODE_FAILURE;
  }
}

void writeDataIntoFileOnSdCard(const char* filename, char* dataBuffer){
    FRESULT fileSystemResult;
    char ramBufferWrite[UINT16_C(256)]; // Temporay buffer for write file
    uint16_t fileSize;
    UINT bytesWritten;
    fileSize = (uint16_t) strlen(dataBuffer);

    for(uint32_t index = 0; index < fileSize; index++){
        ramBufferWrite[index] = dataBuffer[index];
    }
    f_open(&fileObject, filename, FA_OPEN_EXISTING | FA_WRITE);
    f_lseek(&fileObject, f_size(&fileObject)); // @suppress("Field cannot be resolved")
    fileSystemResult = f_write(&fileObject, ramBufferWrite, fileSize, &bytesWritten);

    if((fileSystemResult != FR_OK) || (fileSize != bytesWritten)){ // @suppress("Symbol is not resolved")
        printf("Error: Cannot write to file %s \n\r", filename);
    }
    fileSystemResult = f_close(&fileObject);
}

void readwrite()
{
	if(RETCODE_OK == searchForFileOnSdCard(Filename, NULL)){
  for (;;) {

    Retcode_T returnValue = RETCODE_FAILURE;

    Accelerometer_XyzData_T bma280 = {INT16_C(0), INT16_C(0), INT16_C(0)};
    memset(&bma280, 0, sizeof(CalibratedAccel_XyzMps2Data_T));

    returnValue = Accelerometer_readXyzGValue(xdkAccelerometers_BMA280_Handle,&bma280);

    if (RETCODE_OK == returnValue) {
    	    	    	fileSize+= snprintf(readings + fileSize, sizeof(readings) - fileSize,
    	    	    	                "%.2f ,", (float) bma280.xAxisData);
    	    	    	fileSize+= snprintf(readings + fileSize, sizeof(readings) - fileSize,
    	    	    	    	    	"%.2f ,", (float) bma280.yAxisData);
    	    	    	fileSize+= snprintf(readings + fileSize, sizeof(readings) - fileSize,
    	    	    	    	    	"%.2f \n", (float) bma280.zAxisData);
    	    	writeDataIntoFileOnSdCard(Filename, readings);
    	    	printf("%d \n\r",counter);
    		  counter = counter + 1;
    	    }
  }

}
}

void createnewtask(void)
{
  xTaskHandle taskHandle = NULL;

  xTaskCreate(
    readwrite,                 // function that implements the task
    (const char * const) "My Task", // a name for the task
	200,       // depth of the task stack
    NULL,                           // parameters passed to the function
    4,               // task priority
    taskHandle                      // pointer to a task handle for late reference
  );
}

//End of Task Experiment


//SD Card Related Functions

void InitSdCard(void){
  Retcode_T retVal = RETCODE_FAILURE;
  FRESULT FileSystemResult = FR_OK; // @suppress("Symbol is not resolved")
  static FATFS FatFileSystemObject;
  SDCardDriver_Initialize();
  if(SDCARD_INSERTED == SDCardDriver_GetDetectStatus()){
    retVal = SDCardDriver_DiskInitialize(DRIVE_ZERO);
    if(RETCODE_OK == retVal){
      printf("SD Card Disk initialize succeeded \n\r");
      FileSystemResult = f_mount(&FatFileSystemObject, DEFAULT_LOGICAL_DRIVE, FORCE_MOUNT);
      if (FR_OK != FileSystemResult){ // @suppress("Symbol is not resolved")
        printf("Mounting SD card failed \n\r");
      }
    }
  }
}

// Sensor Related Functions


static void initAccelerometer(void)
{
   Retcode_T returnValue = RETCODE_FAILURE;
   Retcode_T returnBandwidthValue = RETCODE_FAILURE;
   Retcode_T returnRangeValue = RETCODE_FAILURE;

 // Initialize accelerometer

   returnValue = Accelerometer_init(xdkAccelerometers_BMA280_Handle);

   if ( RETCODE_OK != returnValue) {
       printf("BMA280 Accelerometer initialization failed\n\r");
   }

   returnBandwidthValue = Accelerometer_setBandwidth(xdkAccelerometers_BMA280_Handle, ACCELEROMETER_BMA280_BANDWIDTH_500HZ);

   if (RETCODE_OK != returnBandwidthValue) {
       printf("Configuring bandwidth failed \n\r");
   }
   returnRangeValue = Accelerometer_setRange(xdkAccelerometers_BMA280_Handle,ACCELEROMETER_BMA280_RANGE_2G);

   if (RETCODE_OK != returnRangeValue) {
       printf("Configuring range failed \n\r");
   }
}

// BOOTING AND SETUP FUNCTIONS

static void AppControllerEnable(void * param1, uint32_t param2)
{
    BCDS_UNUSED(param1);
    BCDS_UNUSED(param2);

    createnewtask();

}

static void AppControllerSetup(void * param1, uint32_t param2)
{
    BCDS_UNUSED(param1);
    BCDS_UNUSED(param2);
    Retcode_T retcode = RETCODE_OK;

// SD Card Code

    InitSdCard();

// Sensor Code

    initAccelerometer();

// Common

    retcode = CmdProcessor_Enqueue(AppCmdProcessor, AppControllerEnable, NULL, UINT32_C(0));
    if (RETCODE_OK != retcode)
    {
        printf("AppControllerSetup : Failed \r\n");
        Retcode_RaiseError(retcode);
        assert(0);
    }
}

void AppController_Init(void * cmdProcessorHandle, uint32_t param2)
{
    BCDS_UNUSED(param2);

    Retcode_T retcode = RETCODE_OK;

    if (cmdProcessorHandle == NULL)
    {
        printf("AppController_Init : Command processor handle is NULL \r\n");
        retcode = RETCODE(RETCODE_SEVERITY_ERROR, RETCODE_NULL_POINTER);
    }
    else
    {
        AppCmdProcessor = (CmdProcessor_T *) cmdProcessorHandle;
        retcode = CmdProcessor_Enqueue(AppCmdProcessor, AppControllerSetup, NULL, UINT32_C(0));
    }

    if (RETCODE_OK != retcode)
    {
        Retcode_RaiseError(retcode);
        assert(0); // To provide LED indication for the user
    }
}

 

0 (0 투표)
RE: Write frequency to SD Card
응답
19. 7. 10 오전 9:29 as a reply to Daniel P..

Hello Daniel,

if i am getting your question right, you were wondering about the performance changes with and without writing data to the SD card.

First your Code:

You are using the function "readwrite()" as a task function with an endless loop in it. So the function get repeatadly executed. Due to the fact you are not using any FreeRTOS delay in the function, the execution time depends on the function calls you do in the endless loop.

Writing data to the SD-card shure takes some time. This delays sums up over time and results in the different perfomance of your programm.

If you now want to increase the performance of your programm and shorten the time which is needed to store data on the SD-card, you can do the following steps:

Hardware:

You could buy an industrial grade micro SD-Card. These are more cost intensive then consumer SD-Cards but the write/read performance is much better.

Software:

1. Step

Most of the time which is needed during the write process of the SD-Card, is the time to open and close a file. So if you want to increase the programm performance you should enlarge your buffer "readings" as much as possible and only write the buffer to the SD-card when it is full.

2. Step

The function "sprintf" is really generic programmed. Due to that fact the execution time of the function is large. An alternative would be to store the data in a raw ASCII format in the buffer write some matlab script which translates the unreadable ASCII file to a normal text file later on.

I hope this was helpfull.

If you have any further questions do not hesitate to ask.

Best regards,

Christian

 

0 (0 투표)