Go Down

Topic: Increasing the Speed of writing to an SD Card (Read 411 times) previous topic - next topic

goldworkswell

Hi all, I am using an ICM 20601 an arduino due and the AdaFruit data logger shield with rtc. I need the data to be written at least at 4kHz, but right now I am only getting 62Hz. From my understanding this is slow for writing to an SD card normally. Here is my code.
Code: [Select]

 /* Hardware setup:
  MPU9250 Breakout --------- Arduino
  VDD ---------------------- 3.3V
  VDDI --------------------- 3.3V
  SDA ----------------------- A4
  SCL ----------------------- A5
  GND ---------------------- GND
*/
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <string.h>
#include "RTClib.h"

////////////////////////////////////
//TODO:make faster by by holding write
//TODO:make name thing more effieceint
/////////////////////////////////////

// how many milliseconds between grabbing data and logging it. 1000 ms is once a second
#define LOG_INTERVAL  500 // mills between entries (reduce to take more/faster data)

// how many milliseconds before writing the logged data permanently to disk
// set it to the LOG_INTERVAL to write each time (safest)
// set it to 10*LOG_INTERVAL to write all data every 10 datareads, you could lose up to
// the last 10 reads if power is lost but it uses less power and is much faster!
#define SYNC_INTERVAL 5000 // mills between calls to flush() - to write data to the card
uint32_t syncTime = 0; // time of last sync()
RTC_PCF8523 rtc; // define the Real Time Clock object
// for the data logging shield, we use digital pin 10 for the SD cs line
const int chipSelect = 10;
#define ECHO_TO_SERIAL   1 // echo data to serial port
#define WAIT_TO_START 0 // Wait for serial input in setup()
// the logging file
File dataFile;
char fileName[13];


#include "quaternionFilters.h"
#include "MPU9250.h"

#define AHRS true         // Set to false for basic data read   ******if this is true it wont work at least on serial monitor
#define SerialDebug true  // Set to true to get Serial output for debugging

// Pin definitions
int intPin = 12;  // These can be changed, 2 and 3 are the Arduinos ext int pins
uint8_t dayCheck;

MPU9250 myIMU;

void error(char *str)
{
  Serial.print("error: ");
  Serial.println(str);
 
  while(1);
}


void setup() {
    Serial.begin(38400);
  Wire.begin();
  Wire.setClock(400000L);//makes i2c faster
   pinMode(chipSelect,OUTPUT);
      if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }
  if (! rtc.initialized()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
     rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
    Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  if (!SD.begin(chipSelect)) {
    error("Card failed, or not present");
    while(1){
      Serial.print("failed");
      delay(1);
    }
  }
  Serial.println("card initialized.");




  // Read the WHO_AM_I register, this is a good test of communication
  byte c = myIMU.readByte(104, WHO_AM_I_MPU9250);//104 for implementation board 105 for chip
  if(c!=0xAC){//couldn't connect
    Serial.print("Couldn't connect to ICM20601 ");
    Serial.println(c,HEX);
    while(1);
  }
  else{//success
   
// Calibrate gyro and accelerometers, load biases in bias registers
    myIMU.calibrateMPU9250(myIMU.gyroBias, myIMU.accelBias);
//initialize for active mode
    myIMU.initMPU9250();
    // Get magnetometer calibration from AK8963 ROM
    myIMU.initAK8963(myIMU.magCalibration);
      // Read the WHO_AM_I register of the magnetometer, this is a good test of
    // communication
   // byte d = myIMU.readByte(AK8963_ADDRESS, WHO_AM_I_AK8963);
    //Serial.print("AK8963 "); Serial.print("I AM "); Serial.print(d, HEX);
    //Serial.print(" I should be "); Serial.println(0x48, HEX);//uncomment these lines for debuggin purposes
  }
}

void loop() {
  DateTime now=rtc.now();
  dayCheck=now.day();
  //the following is to make a name for the file
   if(now.month()>9){
      strcat(fileName,"1");
      sprintf(fileName+strlen(fileName),"%c",(now.month()%10)+'0');
  }
  else{
      sprintf(fileName,"0%c", now.month()+'0');
  }
  if(now.day()>9){
      uint8_t tensPlace=(now.day()-now.day()%10)/10;
      //sprintf(fileName+strlen(fileName),"%c",tensPlace+'0');
      if(tensPlace==1){
        sprintf(fileName + strlen(fileName),"%c",((now.day()-now.day()%10)-9)+'0');
      }
      if(tensPlace==2){
        sprintf(fileName + strlen(fileName),"%c",((now.day()-now.day()%10)-18)+'0');
      }if(tensPlace==3){
        sprintf(fileName + strlen(fileName),"%c",((now.day()-now.day()%10)-27)+'0');
      }
     
      sprintf(fileName + strlen(fileName),"%c", now.day()%10+'0');
  }
  else{
      sprintf(fileName + strlen(fileName),"0%c", now.day()+'0');
  }
  strcat(fileName + strlen(fileName), "20");
 
  uint8_t yearDecade=(now.year()%100-now.year()%10)/10;
  if(yearDecade==1){
      sprintf(fileName+strlen(fileName),"1%c", char(now.year()%10+'0'));
  }
    else if(yearDecade==2){
      sprintf(fileName+strlen(fileName),"2%c", ((now.year()%10)-1)+'0');
  }
    else if(yearDecade==3){
      sprintf(fileName+strlen(fileName),"3%c", now.year()%10+'0');
  }
 else if(yearDecade==4){
      sprintf(fileName+strlen(fileName),"4%c", now.year()%10+'0');
  }
   else if(yearDecade==5){
      sprintf(fileName+strlen(fileName),"5%c", now.year()%10+'0');
  }
   else if(yearDecade==6){
      sprintf(fileName+strlen(fileName),"6%c", now.year()%10+'0');
  }
   else if(yearDecade==7){
      sprintf(fileName+strlen(fileName),"7%c", now.year()%10+'0');
  }
   else if(yearDecade==8){
      sprintf(fileName+strlen(fileName),"8%c", now.year()%10+'0');
  }
     else if(yearDecade==9){
      sprintf(fileName+strlen(fileName),"9%c", now.year()%10+'0');
  }
  else{sprintf(fileName + strlen(fileName),"0%c",now.year()%10+'0');}
  strcat(fileName + strlen(fileName), ".txt");
  // delay for the amount of time we want between readings
  delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL));
//File dataFile = SD.open(fileName, FILE_WRITE);
  while(dayCheck==now.day()){
      DateTime now=rtc.now();

      File dataFile = SD.open(fileName, O_CREAT | O_APPEND | O_WRITE);
if(dataFile){//if you could open file

    //get acceleration data
     if (myIMU.readByte(MPU9250_ADDRESS, INT_STATUS) & 0x01){//if there is new data to read
      myIMU.readAccelData(myIMU.accelCount);//reads the x/y/z adc values
      myIMU.getAres();//gets the acceleration resolution
      // Now we'll calculate the accleration value into actual g's
      // This depends on scale being set
      myIMU.ax = (float)myIMU.accelCount[0] * myIMU.aRes; // - accelBias[0];
      myIMU.ay = (float)myIMU.accelCount[1] * myIMU.aRes; // - accelBias[1];
      myIMU.az = (float)myIMU.accelCount[2] * myIMU.aRes; // - accelBias[2];
      myIMU.readGyroData(myIMU.gyroCount);  // Read the x/y/z adc values
      myIMU.getGres();
      // Calculate the gyro value into actual degrees per second
      // This depends on scale being set
      myIMU.gx = (float)myIMU.gyroCount[0] * myIMU.gRes;
      myIMU.gy = (float)myIMU.gyroCount[1] * myIMU.gRes;
      myIMU.gz = (float)myIMU.gyroCount[2] * myIMU.gRes;
     }//if(myIMU.readByte(MPU9250_ADDRESS, INT_STATUS) & 0x01)
     // Must be called before updating quaternions!
     myIMU.updateTime();
        // Print acceleration values in milligs!
        dataFile.print(now.hour(), DEC);
        dataFile.print(":");
        dataFile.print(now.minute(), DEC);
        dataFile.print(":");
        dataFile.print(now.second(), DEC);
        dataFile.print(" X-acceleration:"); dataFile.print(1000 * myIMU.ax);
        dataFile.print(" Y-acceleration: "); dataFile.print(1000 * myIMU.ay);
        dataFile.print(" Z-acceleration: "); dataFile.print(1000 * myIMU.az);
        dataFile.print("mg");
        dataFile.println();
        dataFile.print("gx = ");dataFile.print(myIMU.gx, 2);
        dataFile.print(" gy = "); dataFile.print( myIMU.gy, 2);
        dataFile.print(" gz = "); dataFile.print( myIMU.gz, 2);
        dataFile.println(" deg/s");
        dataFile.flush();
        dataFile.close();
        }
  }
}



wvmarle

With that delay() call you limit yourself to 2 Hz.
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

goldworkswell

The speed didn't change after commenting out that line.

MarkT

Closing and reopening a file on SDcard is very expensive in time.  You should only close and open
when the filename changes.  You could also elect to flush less often too, that would help.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

Go Up