500 sampes per second SD writting

Hello,

I´m about to start a project with arduino, don´t have any experience with it; however, I understand is less complex than using a PIC. My project is a 24 hour holter monitor and I´m going to use the heart signal to be recorded into an SD card. I´m wondering if is possible to write the SD card at sampling rate of 500 samples per second, is this possible with Arduino ? any help would be great.

I´m wondering if is possible to write the SD card at sampling rate of 500 samples per second

How much data would be associated with each sample?

Here is a program that can log data at 500 Hz.

LowLatencyLogger

This example uses analogRead() but you can modify these functions to log from other sensors.

Data record type in UserDataType.h:

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

Functions to read sensors and format data as text in LowLatencyLogger.ino.

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

// Acquire a data record.
void acquireData(data_t* data) {
  data->time = micros();
  for (int i = 0; i < ADC_DIM; i++) {
    data->adc[i] = analogRead(i);
  }
}

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

fat16lib and PaulS thanks for replying !

Since I have very basic knowledge in programming, I´m having a hard time understanding the suggested codes, specially LowLatencyLogger.

What I pretend to do is receive the heart signal through 3 analog pins (A0-A2), then use the ADC and save them to the SD card as text file to plot the signal after it.

I wonder if you can help me with my code... It´s pretty basic, this is what I have so far:

uint32_t lastTime;

void setup()
{
  Serial.begin(115200);
  lastTime = millis();
  Serial.println("Miliseg,Valor1,Valor2,Valor3");
}

void loop()
{
  while ((millis() - lastTime)  < 2);  // wait for 2 ms passed
  lastTime = millis();
  int x = analogRead(A0);
  int y = analogRead(A1);
  int z = analogRead(A2);  // make a read
  Serial.print(millis());
  Serial.print(",");
  Serial.print(x);
  Serial.print(",");
  Serial.print(y);
  Serial.print(",");
  Serial.println(z);// send it
}

This is a code I found to sample 500 samples for sec.

Then I modified it to trying log it into the SD card with this:

#include <SD.h>
uint32_t lastTime;
const int chipSelect = 10;

void setup()
{
  Serial.begin(9600);
  lastTime = millis();
  Serial.print("Initializing SD card...");
  
  pinMode(10, OUTPUT);
  pinMode(4, OUTPUT);
  
  
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
  Serial.println("Miliseg,Valor1,Valor2,Valor3");
 }

void loop()
{
  while ((millis() - lastTime)  < 2);  // wait for 2 ms passed
  lastTime = millis();
  int x = analogRead(A0);
  int y = analogRead(A1);
  int z = analogRead(A2);  
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  if (dataFile) {
    dataFile.print(millis());
    dataFile.print(",");
    dataFile.print(x);
    dataFile.print(",");
    dataFile.print(y);
    dataFile.print(",");
    dataFile.println(z);
    dataFile.close();
  Serial.print(millis());
  Serial.print(",");
  Serial.print(x);
  Serial.print(",");
  Serial.print(y);
  Serial.print(",");
  Serial.println(z);// send it
}
else {
    Serial.println("error opening datalog.txt");
  }
 }

This code only log around 50 samples for second.

I appreciate if you guys could help me to understand what can be modified to get what I need.

This code only log around 50 samples for second.

I appreciate if you guys could help me to understand what can be modified to get what I need.

Your code will never work with simple mods. SD cards can have very long write latencies. That's why I added the LowLatencyLogger example to Sdfat.

Since I have very basic knowledge in programming, I´m having a hard time understanding the suggested codes, specially LowLatencyLogger.

Better learn since 500 Hz is impossible without sophisticated buffering.

Hi AndChor,

I stumbled across exactly the same problem to reach 500 samples per second for an ECG device.

I realized, when you open and close the SD file only once, you get a huge improvement of the data rate.

For me it was an improvement from 62 samples per second to 434 samples per second.

Regards,
CCommander

CCommander,

For me it was an improvement from 62 samples per second to 434 samples per second.

A simple logger that writes to an SD card will have occasional write latencies of from 10 to 250 milliseconds.

Do you care if there are random time gaps in your data?

You must buffer data and isolate sample acquisition from writing the SD if you want a uniform interval between samples.

A time series with jitter in the interval is worthless in applications where you want to some types of analysis like frequency analysis with an FFT.

A standard test for a high speed logger is to record a pure sine wave, do an FFT and see if the logger introduces harmonics.

I am developing a million sample per second logger using a Nucleo-F411RE board, cost about $13. I am using the ChibiOS RTOS, not the Arduino IDE.

I have attached a plot that shows there is little jitter in the one microsecond sample interval.