SD Card

Probably a simple question, but how do you make the file name a variable when doing a SD.Open

This works
File dataFile = SD.open("Test1.txt", FILE_WRITE);

I want this:
String inputString = "Test1.txt"; // global variable
File dataFile = SD.open(inputString, FILE_WRITE);

What happens. Does it give you an error? What does it say?

Error Compiling

PhotoResistorwithSD_IR.ino: In function 'void loop()':
PhotoResistorwithSD_IR.ino:40:53: error: no matching function for call to 'SDClass::open(String&, int)'
PhotoResistorwithSD_IR.ino:40:53: note: candidate is:
In file included from PhotoResistorwithSD_IR.ino:9:0:
/Applications/Arduino.app/Contents/Java/libraries/SD/src/SD.h:73:8: note: File SDClass::open(const char*, uint8_t)
File open(const char filename, uint8_t mode = FILE_READ);
^
/Applications/Arduino.app/Contents/Java/libraries/SD/src/SD.h:73:8: note: no known conversion for argument 1 from 'String' to 'const char
'
Error compiling.

Open does not take a String, it wants a string (null terminated character array).

So if you get away from the stupid Strings, this would work.

char* inputString = "Test1.txt"; // global variable
File dataFile = SD.open(inputString, FILE_WRITE);

Delta G thank you for the help. It compiles but now I get a error opening datalog.txt message Here’s the whole thing I’m getting a string from the serial port and using a serialEvent, once that happens it opens the SD card and writes data from the photoresistors.
/*

  • SD card attached to SPI bus as follows:
    ** MOSI - pin 11
    ** MISO - pin 12
    ** CLK(SCK) - pin 13
    ** CS - pin 10
    */

#include <SD.h>
#include <SPI.h>
char* inputString = “err”; // a string to hold incoming data
boolean stringComplete = false; // whether the string is complete
const int chipSelect = 10;
const int sensorPin = 0;
int lightLevel, high = 0, low = 1023;
float ti = 0.0;

void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(9600);
Serial.print(“Initializing SD card…”);
pinMode(10, OUTPUT);
digitalWrite(10, HIGH);

if (!SD.begin(chipSelect)) {
Serial.println(“Card failed, or not present”);
return;
}
Serial.println(“card initialized.”);

}

void loop()
{
// print the string when a newline arrives:
if (stringComplete) {
// here
for (int i = 0; i < 2000; i++){
File dataFile = SD.open(inputString, FILE_WRITE);
lightLevel = analogRead(sensorPin);
// if the file is available, write to it:
if (dataFile) {
dataFile.print(ti);
dataFile.print(",");
dataFile.println(lightLevel);
dataFile.close();
ti=ti+.05;
}
// if the file isn’t open, pop up an error:
else {
Serial.println(“error opening datalog.txt”);
}
delay(50);
}
//done

Serial.println(inputString);
// clear the string:
inputString = “”;
stringComplete = false;
}
}

void serialEvent() {
while (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
// if the incoming character is a newline, set a flag
// so the main loop can do something about it:
if (inChar == ‘\n’) {
stringComplete = true;
}

}

}

inputString += inChar;

inputString is a char array now. You can't add to it with the + operator anymore. We've put the baby toys down and picked up the grownup tools. Time to learn to work with char arrays.

Ok for anyone looking at this thread here’s the solution I settled on. I added this code to the beginning of my void loop() program and this allowed me to type in a file name to start the data gathering and use that file name for the file on the SD card. Works! What I did was to convert my string to a char array and add a null terminator to make it like a char* declaration. First the added code then the whole program:

str_len = inputString.length();
inputString[str_len] = ‘\0’;
char char_array[str_len];
inputString.toCharArray(char_array, str_len);

I hope this helps someone…

/*

  • SD card attached to SPI bus as follows:
    ** MOSI - pin 11
    ** MISO - pin 12
    ** CLK(SCK) - pin 13
    ** CS - pin 10
    */

#include <SD.h>
#include <SPI.h>
String inputString = “”; // a string to hold incoming data
char* temp=“File1.txt”;
boolean stringComplete = false; // whether the string is complete
const int chipSelect = 10;
const int sensorPin = 0;
int lightLevel, high = 0, low = 1023;
float ti = 0.0;
int str_len =0;

void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(9600);
Serial.print(“Initializing SD card…”);
pinMode(10, OUTPUT);
digitalWrite(10, HIGH);

if (!SD.begin(chipSelect)) {
Serial.println(“Card failed, or not present”);
return;
}
Serial.println(“card initialized.”);

}

void loop()
{

str_len = inputString.length();
inputString[str_len] = ‘\0’;
char char_array[str_len];
inputString.toCharArray(char_array, str_len);

// temp=char_array;

// print the string when a newline arrives:
if (stringComplete) {
// here we go

for (int i = 0; i < 51; i++){
File dataFile = SD.open(char_array, FILE_WRITE);
lightLevel = analogRead(sensorPin);
// if the file is available, write to it:
if (dataFile) {
dataFile.print(ti);
dataFile.print(",");
dataFile.println(lightLevel);
dataFile.close();
ti=ti+.05;
}
// if the file isn’t open, pop up an error:
else {
Serial.println(“error opening datalog.txt”);
}
delay(50);
}
//done
Serial.println(temp);
Serial.println(char_array);
// clear the string:
inputString = “”;
stringComplete = false;
}
}

void serialEvent() {
while (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:

inputString += inChar;

// if the incoming character is a newline, set a flag
// so the main loop can do something about it:
if (inChar == ‘\n’) {
stringComplete = true;
}

}

}

What I did was to convert my string to a char array and add a null terminator to make it like a char* declaration.

Do you need to add a null terminator or is it already placed in the array by the conversion? Below is some conversion code where no extra null terminator is added. I don’t know who made the code, but saved it as something that might be useful.

char buffer[20];
readString.toCharArray(buffer, 20);
int nRead= atoi(buffer);
long nReadLong= atol(buffer);
unsigned long nReadHex= strtoul(buffer, NULL, 16);

Thanks much, no I added it. That was this: inputString[str_len] = '\0'; that replaced what ever was there with the null character and that did the trick. Everything worked. It's a little more work figuring this out with the Arduinos since you have to write it to the serial port to figure it out. I guess I was being lazy. Maybe it will help someone else, best wishes,

Thanks much, no I added it. That was this: inputString[str_len] = '\0'; that replaced what ever was there with the null character and that did the trick.

I was just curious if in fact the one you added was not actually needed when you used the below conversion line.

 inputString.toCharArray(char_array, str_len);

Yes it's still needed. I thought that line would do it, but the file on the SD card won't open and the only thing I could conclude was it was different. When I put char* filename="Test1.txt";
that works fine like this: File dataFile = SD.open(filename, FILE_WRITE); but when I take the string from the serial input and do: inputString.toCharArray(char_array, str_len);
Then this doesn't work: File dataFile = SD.open(char_array, FILE_WRITE);
I printed out the results from filename and char_array and compared. What I observed was that there was a space after the one that worked. Now I'm not a Computer guy, but I probably could have figured this out by printing out every character hex dec from each string, but like I said I was being lazy. This works and seems pretty easy. Best wishes,