Logging Analog data into SDcard using Arduino Uno

Hi guys!

I want to log sampled raw data of a low frequency sine wave of 40Hz into a SDcard via the Arduino Uno. The code below is what I came out with so far. It is simple and should take less than a minute to look at it. Basically my issue right now is that, when i feed the raw data to Audacity, I obtain a weird ‘spike’ whenever the write function is called to write the 512 data block into the Sdcard. Below is my code and attached is the results.

Would be much appreciated, if someone can point out my errors or help to provide suggestion that can fix the code.

Thank youuuu.

/*
The circuit:
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4
 */
#include <SPI.h>
#include <SD.h>
//assign pin
const int analogPin = 0;
//Sample rate in samples per second
 const float SAMPLE_RATE = 8000;  
//Sample Interval
 const float SAMPLE_INTERVAL = 1.0/SAMPLE_RATE;
//SD chip select pin
const int chipSelect = 4;
// 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;
//buffer definitions
#define BUFFSIZE 512
char buffer[BUFFSIZE];
int testArray[2000];
char c;
int buffIndex=0, sensor=0;
int head =0, tail = 0;
//unsigned long start_times[105];
//unsigned long stop_times[105];

//-----------------------------------------------------------------------------------
 boolean logData() {
  boolean result = false;
  Serial.print("Initializing SD card...");
  pinMode(10, OUTPUT);

  // check if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    result = false;
  } 
  
  else {
    Serial.println("card initialized.");
    File dataFile = SD.open("f13.bin", FILE_WRITE);
    
    for(int i=0; i<1500; i++)
      {
     // start_times[i] = micros();
      sensor = analogRead(analogPin);  
      buffer[buffIndex++] = sensor; 
      if (buffIndex >= BUFFSIZE-1)
          {
            //buffer[buffIndex] = 0; // terminate it with null at current index
            dataFile.write((uint8_t *) buffer, (buffIndex + 1)); 
            buffIndex = 0;     // reset buffer pointer
          }    
   //   stop_times[i] = micros();    
      }
    Serial.print("Complete"); 
    dataFile.close();

    result = true;
  return result;
  }
}  
//=======================================================================================


//========================================================================================

void setup() {
  Serial.begin(9600);

}

void loop()
{     
  while (Serial.read() >= 0) {}
  Serial.println();
  Serial.println(F("type:"));
  Serial.println(F("l - log data ")); 
  //Serial.println(F("d - dump data to Serial"));  
  
   while(!Serial.available()) {}
  char c = tolower(Serial.read());
  if (ERROR_LED_PIN >= 0) {
    digitalWrite(ERROR_LED_PIN, LOW);
  }
  //check SDcard
  if (c == 'l') {
    logData();
  }
  else {
    Serial.println(F("Invalid entry"));
  }  
   
}

dataFile.write () will take a considerable time, which is delaying your analog read loop.

What is this supposed to do BTW:

  while (Serial.read() >= 0) {}

because is looks like you meant to call available(). Calling read() before checking
available() gives undefined result.

Hi Mark!

Thank you so much for the reply and help. I actually tried that but the same error persist. I think i would need some sort of multi threading since this seems like a producer-consumer problem. I need to be able to buffer data WHILE writing buffered data into the SDcard, since I have continuous incoming data.

I am thinking of implementing the NilRTOS as discussed in this page:

Do you think that would be a solution to my problem?

I see several issues with your code but the one causing that "spike" looks to be due to a classic one-off error. Specifically, you are filling the first 511 bytes of your buffer and then writing 512 bytes, so that last one is undefined or maybe is always zero due to what the bootloader does.