Micro SD Card Sampling Rate

Hi there,

I am using micro SD card shield from Sparkfun and attached to arduino uno. I am acquiring reading from MPU6050. However, I have one serious problem, I cannot set my sampling rate to my desired one.

The following is my code for my project. For the purpose of my project, I need to rewrite the reading into a new file every time i switch off my uno and restart it again. So the code for micro SD card looks something different in my code.

#include <SPI.h>
#include <SD.h>
#include "Wire.h"
#include "I2Cdev.h"
#include "MPU6050.h"

#define FILE_BASE_NAME "Waist"
const uint8_t CS_PIN = 8;

MPU6050 accelgyro  ;

File file;

const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1;
char fileName[] = FILE_BASE_NAME "00.csv";


int axkl, aykl, azkl, gxkl, gykl, gzkl;

unsigned long time;

void setup()
{

  
  #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        Wire.begin();
    #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
        Fastwire::setup(400, true);
    #endif
 
  Serial.begin(115200);
   while (!Serial) {
    ; 
  }
  
   pinMode(CS_PIN, OUTPUT);
    while(!SD.begin(CS_PIN)) {
      ;
    }
  while (SD.exists(fileName)) {
    if (fileName[BASE_NAME_SIZE + 1] != '9') {
      fileName[BASE_NAME_SIZE + 1]++;
    } else if (fileName[BASE_NAME_SIZE] != '9') {
      fileName[BASE_NAME_SIZE + 1] = '0';
      fileName[BASE_NAME_SIZE]++;

    }
  
   accelgyro.initialize();

  


}
}
void loop()
{
  File file = SD.open(fileName, FILE_WRITE);
  if (file) {
 time=millis();
 

     
    accelgyro.getMotion6(&axkl, &aykl, &azkl, &gxkl, &gykl, &gzkl);

        file.print(time);
    file.print(",");
    file.print(axkl); 
    file.print(",");
    file.print(aykl); 
    file.print(",");
    file.print(azkl); 
    file.print(",");
    file.print(gxkl); 
    file.print(",");
    file.print(gykl); 
    file.print(",");
    file.print(gzkl); 
    
 
    Serial.print(time);
    Serial.print(",");
    Serial.print(axkl); 
    Serial.print(",");
    Serial.print(aykl); 
    Serial.print(",");
    Serial.print(azkl); 
    Serial.print(",");
    Serial.print(gxkl); 
    Serial.print(",");
    Serial.print(gykl); 
    Serial.print(",");
    Serial.println(gzkl); 

    file.println(); 
    file.close();
  }

    
delay(10)
  
}

The ‘delay(10)’ should delay the display of my sensors reading to 10 microsecond intervals, but it just does not show this way. Instead it shows this result:

39      -264	32767	-16444	-128	95	61
103	 -224	32767	-16536	-128	102	63
145	-200	32767	-16508	-112	117	63
187	-136	32767	-16560	-131	89	60
228	-172	32767	-16572	-135	83	75
281	-168	32767	-16608	-129	99	61
330	-296	32767	-16500	-135	102	4
371	-188	32767	-16628	-124	115	78
413	-124	32767	-16452	-111	112	30
454	-260	32767	-16536	-128	113	71
496	-220	32767	-16580	-127	95	74
537	-164	32767	-16448	-135	92	29
579	-100	32767	-16460	-141	80	75
620	-144	32767	-16360	-106	89	18
662	-204	32767	-16540	-126	81	81
711	-224	32767	-16476	-111	93	54
753	-244	32767	-16588	-131	114	81
795	-172	32767	-16540	-103	106	21
838	-148	32767	-16544	-138	102	66
880	-308	32767	-16620	-158	99	59
922	-272	32767	-16544	-140	99	49
965	-244	32767	-16512	-124	100	107
1007	-216	32767	-16652	-108	100	36
1049	-240	32767	-16596	-132	115	73
1092	-188	32767	-16504	-125	86	37

Notice the first column is the time interval in millis seconds. The time interval is roughly 30-80ms which is way off from 10ms. So is there anything I can do to modify my code to to get a better sampling rate?

Thanks in advance.

You will never achieve reliable 100 Hz logging with your approach.

See this topic.

You will need a more sophisticated program that avoids the long SD busy periods.

I provided this example with SdFat. This example shows how to log data at high rates without dropping points.

You would need to write a similar program for the MPU6050.

You might find a working MPU6050 program in this forum since many people use this device.

fat16lib: You will never achieve reliable 100 Hz logging with your approach.

See this topic.

You will need a more sophisticated program that avoids the long SD busy periods.

I provided this example with SdFat. This example shows how to log data at high rates without dropping points.

You would need to write a similar program for the MPU6050.

You might find a working MPU6050 program in this forum since many people use this device.

THANKS FOR THE REPLY!!!

I had read your example on LowLatencyLogger.ino. First I will like to apologize for my ignorance because I do not understand your example ( I am considered quite new in this field). Is that mean the example you provided can help to increase the sampling rate (which for me is 100Hz) and reduce the dropping points? I need to use every line of the code in the script and put them into my code?

And when you mentioned about write similar program for MPU6050, do you mean to write a code to increase the i2c sampling rate?

Again please forgive my ignorance.

Thank you.

And is there anywhere I can show the computer Real world time in my reading?

Please help!!!

fat16lib: You will never achieve reliable 100 Hz logging with your approach.

See this topic.

You will need a more sophisticated program that avoids the long SD busy periods.

I provided this example with SdFat. This example shows how to log data at high rates without dropping points.

You would need to write a similar program for the MPU6050.

You might find a working MPU6050 program in this forum since many people use this device.

Hi,

I have used your advise and the example LowLatencyLogger.ino in github.

After 1 days survey on this lowlatencylogger example, I tried to modify your example to read MPU6050.

for the UserDataType.h file I only slightly modify the ADC_DIM to 6 (which is guess is the total reading i need to acquire from my sensors):

#ifndef UserDataType_h
#define UserDataType_h
const uint8_t ADC_DIM = 6;
struct data_t {
  unsigned long time;
  unsigned short adc[ADC_DIM];
};
#endif  // UserDataType_h

After I upload the code to my uno and I opened Serial Monitor the shows

c - convert file to csv d - dump data to Serial e - overrun error details r - record data

So I guess my modified code is working. But when I try to read my microSD card in my pc, there is no file inside my card.

What can possibly be the problem in this case?

And regarding my previous post, if I want to show real time pc clock, is it possible by using this example?

thank you.

tanminggui:
Hi,

I have used your advise and the example LowLatencyLogger.ino in github.

After 1 days survey on this lowlatencylogger example, I tried to modify your example to read MPU6050.

for the UserDataType.h file I only slightly modify the ADC_DIM to 6 (which is guess is the total reading i need to acquire from my sensors):

#ifndef UserDataType_h

#define UserDataType_h
const uint8_t ADC_DIM = 6;
struct data_t {
 unsigned long time;
 unsigned short adc[ADC_DIM];
};
#endif  // UserDataType_h




After I upload the code to my uno and I opened Serial Monitor the shows 

c - convert file to csv
d - dump data to Serial
e - overrun error details
r - record data

So I guess my modified code is working. But when I try to read my microSD card in my pc, there is no file inside my card.

What can possibly be the problem in this case?

And regarding my previous post, if I want to show real time pc clock, is it possible by using this example?

thank you.

The modified code in lowlatencylogger I mentioned:

#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h>
#include "Wire.h"
#include "I2Cdev.h"
#include "MPU6050.h"



//------------------------------------------------------------------------------
// User data functions.  Modify these functions for your data items.
#include "UserDataType.h"  // Edit this include file to change data_t.

// define MPU6050 constant
MPU6050 accelgyro; 
int16_t ax, ay, az, gx, gy, gz;

unsigned long time;
// Acquire a data record.
void acquireData(data_t* data) {
  time = micros();
  accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  
  data->time = micros();
    data->adc[1] = ax;
    data->adc[2] = ay;
    data->adc[3] = az;
    data->adc[4] = gx;
    data->adc[5] = gy;
    data->adc[6] = gz;
}


// Print a data record.
void printData(Print* pr, data_t* data) {
  pr->print(data->time);
  for (int i = 0; i < ADC_DIM; i++) {
    pr->write(',');
    pr->print(data->adc[i]);
  }
  pr->println();
}

// Print data header.
void printHeader(Print* pr) {
  pr->print(F("time"));
  for (int i = 0; i < ADC_DIM; i++) {
    pr->print(F(",adc"));
    pr->print(i);
  }
  pr->println();
}
//=============================================================
//------------------------------------------------------------------------------
void setup(void) {
  if (ERROR_LED_PIN >= 0) {
    pinMode(ERROR_LED_PIN, OUTPUT);
  }
  Serial.begin(38400);
  
  
  
  
       #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        Wire.begin();
    #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
        Fastwire::setup(400, true);
    #endif
  accelgyro.initialize();

  Serial.print(F("FreeRam: "));
  Serial.println(FreeRam());
  Serial.print(F("Records/block: "));
  Serial.println(DATA_DIM);
  if (sizeof(block_t) != 512) {
    error("Invalid block size");
  }
  // initialize file system.
  if (!sd.begin(SD_CS_PIN, SPI_FULL_SPEED)) {
    sd.initErrorPrint();
    fatalBlink();
  }
}
//------------------------------------------------------------------------------
void loop(void) {
  // discard any input
  while (Serial.read() >= 0) {}
  Serial.println();
  Serial.println(F("type:"));
  Serial.println(F("c - convert file to csv"));
  Serial.println(F("d - dump data to Serial"));
  Serial.println(F("e - overrun error details"));
  Serial.println(F("r - record data"));

  while(!Serial.available()) {}
  char c = tolower(Serial.read());

  // Discard extra Serial data.
  do {
    delay(10);
  } while (Serial.read() >= 0);

  if (ERROR_LED_PIN >= 0) {
    digitalWrite(ERROR_LED_PIN, LOW);
  }
  if (c == 'c') {
    binaryToCsv();
  } else if (c == 'd') {
    dumpData();
  } else if (c == 'e') {
    checkOverrun();
  } else if (c == 'r') {
    logData();
  } else {
    Serial.println(F("Invalid entry"));
  }
}

tanminggui: The modified code in lowlatencylogger I mentioned:

Hi OP,

I am glad there is someone who is working on similar thing with me. I am also trying to log mpu6050 into microSD card. So far I am able to generate a bin file but not csv file. Have you resolved your problem yet? If you do can you please guide me how to modify this example??

Thank you in advance.

tanminggui: And is there anywhere I can show the computer Real world time in my reading?

Please help!!!

And please correct me if i am wrong. I believe a real time clock module can show the real time pc clock as you wish. There are plenty of clock module available from sparkfun if I am not mistaken.

Cheers.