arduino microSD shield lowlatencylogger

时间:2015-07-30 18:55:01

标签: arduino

我从sparkfun购买了microSD卡屏蔽,我希望数据记录能够读取2个MPU6050。我希望有100Hz的采样频率,所以我遇到了Greiman关于lowlatencylogger的一个例子。使用他的示例和SDFat库而不是SD库,我可以获得非常好的采样频率,但是,我无法随意终止数据记录。

我尝试添加一个开关来设置一个条件,如果arduino读取了开关,那么它将开始截断文件。但到目前为止没有结果。所以任何人都可以帮助我吗?

我正在使用的代码

#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();
} 

1 个答案:

答案 0 :(得分:0)

您需要修改以下代码段:

if (Serial.available()) {
  closeFile = true;
}

类似于:

if (Serial.available() || (stopSwitch(haltPIN) == LOW)) {
  closeFile = true;
}

其中stopSwitch通常HIGH连接到haltPIN