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.
/* 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();
}
}
}