Basic of SD card storage

Hi,

I'm trying to store some sensor values on an SD card, which I believe I'm able to do. I'd just like some help on understanding what the stock example code actually means.

Here are my questions:

  1. In the create file section of my code, is it correct to say that I can create a text file "on the fly" with any name?

If so, is there a way I can write this at the top of my code, and then reference it, like a 'const int', but a 'const string', if that makes sense...?

  1. Can I create several text files on the same card?

Here is my code

/*
  SD card datalogger

 The circuit:

*SONAR
 pin 2 - sonar / Trigger 
 pin 3 - sonar / Echo

*SD card attached to SPI bus
 pin 4 - SD card / CS
 pin 11 - MOSI
 pin 12 - MISO
 pin 13 - CLK

 */

#include <SPI.h>
#include <SD.h>
#include <NewPing.h>  // sonar library

const int chipSelect = 4;

int i = 0; // initialize loop counter
int a = 0; // void loop counter, it should run only once
int b = 0; // 1st element of array
int c = 0; // counter for printing array elements

// Sonar set up
#define TRIGGER_PIN  2  // Arduino trigger pin on sonar
#define ECHO_PIN     3  // Arduino echo pin on sonar
#define MAX_DISTANCE 200 /* Maximum distance we want to ping for (in centimeters). 
                            Maximum sensor distance is rated at 400-500cm.
                         */
// SONAR
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

// STRING
  /*  Make a string to log data  */
String dataString = "";

// ARRAY
/*  Make an array to log data  */
const int array_size = 5;
double dataArray[array_size] = {};  // set array to size

void setup() 
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial)
  {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  Serial.print("Initializing SD card...");

  // see 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:
    return;
  }
  
  Serial.println("card initialized.");
}

void loop() 
{
  // run entire loop only once
  for (a; a<1; a++)
  {
    
// read and write sensor values for each conected pin per sensor
  // record 5 readings of the sensors, so that there are 5 string lines
for (i; i<array_size; i++)
{
// read sensor values
  
  // SONAR
  delay(50);    // Wait 50ms between pings (~ 20 pings/sec). 29ms should be min delay between pings
  
   // initially, these types were 'unsigned int', but seemed to be no difference
   int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS)
   double distance = (uS / US_ROUNDTRIP_CM) / 2.54;  // Convert ping time to distance, 0 = outside set distance range
                                                    // units are converted from cm to inches
double sensor_value = distance;

// print to serial monitor
Serial.print("Distance: ");
Serial.print(distance);      // units are in inches
Serial.println("in");

// add sonar values to string
dataString += String(sensor_value);

    if (i < 4) 
        {
          dataString += ",";
        }
 

// add sonar values to array
 if (b<array_size)
  {
    dataArray[b] = sensor_value;
    b++;
  }
}       
 

// OPEN FILE
/* microSD card 
   Note that only one file can be open at a time,
     so you have to close this one before opening another.
     (But if you only have 1 card, no worries.)
*/

// CREATE FILE
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
                       //(file name, function)
                         
// WRITE TO FILE
  // if the file is available, write to it:
  if (dataFile) 
  {

// CLOSE FILE    
    dataFile.println(dataString); //print to microSD card
    dataFile.close();
    
    // print string to serial monitor
    Serial.println("\nString printed to microSD card:");
    Serial.println(dataString);

       // print array to serial monitor
    Serial.println("\nArray printed to microSD card:");
    
    for (c; c < array_size; c++)
    {
      Serial.print(dataArray[c]); // print value at current element position

      // add a comma between elements, but not after last one
      if (c < array_size - 1)
      {
        Serial.print(","); 
      }
    }

      // test: print only 1 element of array to serial monitor
      Serial.println("\n");
      Serial.print("3rd element in array: ");
      Serial.println(dataArray[2]);
    
  }
  
  // if the file isn't open, pop up an error:
  else 
  {
    Serial.println("error opening datalog.txt");
  }
 }

}

Your code look reasonable:
Does it Compile?
Does is preform as expected?

the only questionable statement was:

  File dataFile = SD.open("datalog.txt", FILE_WRITE);

You never specified the subdirectory, or root where to store the file.

  File dataFile = SD.open("/datalog.txt", FILE_WRITE); // create file in root directory

This code is only questionable if the file was not in the 'root' directory of the SDcard.

for each File object you have open, there is an associated sector buffer, since a 512 byte sector is 1/4 of an Arduino's RAM realistically TWO files can be opened as once. If you use a Mega (8k RAM) more files can be concurrently accessed.
You can reuse (open/close) the File object as many times as you wish. But, you are limited by your RAM size the number of concurrently 'open' files.

Chuck.

Essentially, yes to both. You seem to be making things more difficult than they need be. There is a useful example included in the SD section of the IDE examples that should be all you need.

It need be no more than a matter of collecting the data files as you go round the loop, and printing them

myFile.print(var);
myFile print(",");

with a println for the last.
This gives you a comma separated set of data for later analysis.
You can have multiple files but only one open at a time. Open the file, print your stuff, and close the file - each trip round the loop. I think it is the safest, even if you only have one.