I had purchased a microSD card shield from sparkfun and I wish to do data logging to read 2 MPU6050. I wished to have sampling frequency of 100Hz, so I came across one example from Greiman about lowlatencylogger. Using his example and SDFat library instead of SD library, I do can get very good sampling frequency, however, I cannot terminate the data logging at will.
I tried to add a switch to set a condition where if the arduino read the switch, then it will start truncating the file. But so far no result. So can anyone help me??
the code that I am using
- CODE: SELECT_ALL_CODE
#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.
MPU6050 mpu;
MPU6050 mpu_69 (0x69);
int switchPin = 6;
void setupData() {
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
// set I2C 400 kHz
TWBR = (F_CPU/400000 - 16)/2;
Serial.println(F("Using Wire"));
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
Serial.println(F("Using Fastwire"));
#endif
mpu.initialize();
mpu_69.initialize();
pinMode(switchPin,INPUT_PULLUP);
}
// Acquire a data record.
void acquireData(data_t* data) {
data->time = micros();
data->hs = analogRead(0);
data->to = analogRead(1);
mpu.getMotion6(&data->axr, &data->ayr, &data->azr,
&data->gxr, &data->gyr, &data->gzr);
mpu_69.getMotion6(&data->axl, &data->ayl, &data->azl,
&data->gxl, &data->gyl, &data->gzl);
}
// Print a data record.
void printData(Print* pr, data_t* data) {
pr->print(data->time);
pr->write(',');
pr->print(data->hs);
pr->write(',');
pr->print(data->to);
pr->write(',');
pr->print(data->axr);
pr->write(',');
pr->print(data->ayr);
pr->write(',');
pr->print(data->azr);
pr->write(',');
pr->print(data->gxr);
pr->write(',');
pr->print(data->gyr);
pr->write(',');
pr->print(data->gzr);
pr->write(',');
pr->print(data->axl);
pr->write(',');
pr->print(data->ayl);
pr->write(',');
pr->print(data->azl);
pr->write(',');
pr->print(data->gxl);
pr->write(',');
pr->print(data->gyl);
pr->write(',');
pr->println(data->gzl);
}
// Print data header.
void printHeader(Print* pr) {
pr->println(F("micros,heels,toeo,axshank,ayshank,azshank,gxshank,gyshank,gzshank,axankle,ayankle,azankle,gxankle,gyankle,gzankle"));
}
//==============================================================================
// Start of configuration constants.
//==============================================================================
//Interval between data records in microseconds.
const uint32_t LOG_INTERVAL_USEC = 10000;
//------------------------------------------------------------------------------
// Pin definitions.
//
// SD chip select pin.
const uint8_t SD_CS_PIN = 8;
//
// Digital pin to indicate an error, set to -1 if not used.
// The led blinks for fatal errors. The led goes on solid for SD write
// overrun errors and logging continues.
const int8_t ERROR_LED_PIN = -1;
//------------------------------------------------------------------------------
// File definitions.
//
// Maxrimum file size in blocks.
// The program creates a contiguous file with FILE_BLOCK_COUNT 512 byte blocks.
// This file is flash erased using special SD commands. The file will be
// truncated if logging is stopped early.
const uint32_t FILE_BLOCK_COUNT = 256000;
////////////////////////////
uint32_t const ERASE_SIZE = 262144L;
void logData() {
unsigned long timeout =0;
bool truncate=false;
uint32_t bgnBlock, endBlock;
// Allocate extra buffer space.
block_t block[BUFFER_BLOCK_COUNT];
block_t* curBlock = 0;
Serial.println();
// Find unused file name.
if (BASE_NAME_SIZE > 6) {
error("FILE_BASE_NAME too long");
}
while (sd.exists(binName)) {
if (binName[BASE_NAME_SIZE + 1] != '9') {
binName[BASE_NAME_SIZE + 1]++;
} else {
binName[BASE_NAME_SIZE + 1] = '0';
if (binName[BASE_NAME_SIZE] == '9') {
error("Can't create file name");
}
binName[BASE_NAME_SIZE]++;
}
}
// Delete old tmp file.
if (sd.exists(TMP_FILE_NAME)) {
Serial.println(F("Deleting tmp file"));
if (!sd.remove(TMP_FILE_NAME)) {
error("Can't remove tmp file");
}
}
// Create new file.
Serial.println(F("Creating new file"));
binFile.close();
if (!binFile.createContiguous(sd.vwd(),
TMP_FILE_NAME, 512 * FILE_BLOCK_COUNT)) {
error("createContiguous failed");
}
// Get the address of the file on the SD.
if (!binFile.contiguousRange(&bgnBlock, &endBlock)) {
error("contiguousRange failed");
}
// Use SdFat's internal buffer.
uint8_t* cache = (uint8_t*)sd.vol()->cacheClear();
if (cache == 0) {
error("cacheClear failed");
}
// Flash erase all data in the file.
Serial.println(F("Erasing all data"));
uint32_t bgnErase = bgnBlock;
uint32_t endErase;
while (bgnErase < endBlock) {
endErase = bgnErase + ERASE_SIZE;
if (endErase > endBlock) {
endErase = endBlock;
}
if (!sd.card()->erase(bgnErase, endErase)) {
error("erase failed");
}
bgnErase = endErase + 1;
}
// Start a multiple block write.
if (!sd.card()->writeStart(bgnBlock, FILE_BLOCK_COUNT)) {
error("writeBegin failed");
}
// Initialize queues.
emptyHead = emptyTail = 0;
fullHead = fullTail = 0;
// Use SdFat buffer for one block.
emptyQueue[emptyHead] = (block_t*)cache;
emptyHead = queueNext(emptyHead);
// Put rest of buffers in the empty queue.
for (uint8_t i = 0; i < BUFFER_BLOCK_COUNT; i++) {
emptyQueue[emptyHead] = &block[i];
emptyHead = queueNext(emptyHead);
}
// Wait for Serial Idle.
Serial.flush();
delay(10);
uint32_t bn = 0;
uint32_t t0 = millis();
uint32_t t1 = t0;
uint32_t overrun = 0;
uint32_t overrunTotal = 0;
uint32_t count = 0;
uint32_t maxlatency = 0;
int32_t diff;
// Start at a multiple of interval.
uint32_t logTime = micros()/LOG_INTERVAL_USEC + 1;
logTime *= LOG_INTERVAL_USEC;
bool closeFile = false;
while (1) {
// Time for next data record.
logTime += LOG_INTERVAL_USEC;
if (Serial.available()) {
closeFile = true;
}
if (closeFile) {
if (curBlock != 0 && curBlock->count >= 0) {
// Put buffer in full queue.
fullQueue[fullHead] = curBlock;
fullHead = queueNext(fullHead);
curBlock = 0;
}
} else {
if (curBlock == 0 && emptyTail != emptyHead) {
curBlock = emptyQueue[emptyTail];
emptyTail = queueNext(emptyTail);
curBlock->count = 0;
curBlock->overrun = overrun;
overrun = 0;
}
do {
diff = logTime - micros();
} while(diff > 0);
if (diff < -10) {
error("LOG_INTERVAL_USEC too small");
}
if (curBlock == 0) {
overrun++;
} else {
acquireData(&curBlock->data[curBlock->count++]);
if (curBlock->count == DATA_DIM) {
fullQueue[fullHead] = curBlock;
fullHead = queueNext(fullHead);
curBlock = 0;
}
}
}
if (fullHead == fullTail) {
// Exit loop if done.
if (closeFile) {
break;
}
} else if (!sd.card()->isBusy()) {
// Get address of block to write.
block_t* pBlock = fullQueue[fullTail];
fullTail = queueNext(fullTail);
// Write block to SD.
uint32_t usec = micros();
if (!sd.card()->writeData((uint8_t*)pBlock)) {
error("write data failed");
}
usec = micros() - usec;
t1 = millis();
if (usec > maxlatency) {
maxlatency = usec;
}
count += pBlock->count;
// Add overruns and possibly light LED.
if (pBlock->overrun) {
overrunTotal += pBlock->overrun;
if (ERROR_LED_PIN >= 0) {
digitalWrite(ERROR_LED_PIN, HIGH);
}
}
// Move block to empty queue.
emptyQueue[emptyHead] = pBlock;
emptyHead = queueNext(emptyHead);
bn++;
if (bn == FILE_BLOCK_COUNT) {
// File full so stop
break;
}
}
}
if (!sd.card()->writeStop()) {
error("writeStop failed");
}
do{
if(digitalRead(switchPin)==LOW){
if(millis()>timeout){ // switchPin is low and has been low for 100ms
truncate = true; // close the file,
// truncate at current record number,
// rename to 'binname'
}
}
else { // switchPin High, not pressed
timeout = millis() + 100; // time that switch has to be pressed to be valid
}
}while(truncate=false);
if(truncate == true){
// Truncate file if recording stopped early.
if (bn != FILE_BLOCK_COUNT) {
//Serial.println(F("Truncating file"));
if (!binFile.truncate(512L * bn)) {
error("Can't truncate file");
}
}
}
binFile.close();
if (!binFile.rename(sd.vwd(), binName)) {
error("Can't rename file");
}
}
//------------------------------------------------------------------------------
void setup(void) {
if (ERROR_LED_PIN >= 0) {
pinMode(ERROR_LED_PIN, OUTPUT);
}
Serial.begin(38400);
sd.begin(38400);
while (!Serial) {}
pinMode(switchPin,INPUT_PULLUP);
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");
}
setupData();
// initialize file system.
if (!sd.begin(SD_CS_PIN, SPI_FULL_SPEED)) {
sd.initErrorPrint();
fatalBlink();
}
}
//------------------------------------------------------------------------------
void loop(void) {
logData();
binaryToCsv();
}