Created Mon, 24 Feb 2014 14:38:40 +0000 by kaaasap
Mon, 24 Feb 2014 14:38:40 +0000
I am working with uC32 and mpide. I am trying to write a file. example: file.csv
if the file exists, I need to append to the file name (1) or (2) and so forth example: test(1).csv
I am using the SD ReadWrite example to start the process and I understand how it works. I understand how to check if the file exists, I just can't seem to get my head around how to append the (1) to the end of the file name.
I am thinking along the lines of:
myFile = SD.open(test.csv);
if (test.csv == true)
{
for (i = 0; i < 99; i++)
myFile = SD.open(test(1).csv, FILE_WRITE);
}
but of course I know its not that simple.
Any help would be greatly appreciated. Thank you!
Mon, 24 Feb 2014 15:42:22 +0000
You should look at the sprintf function.
Something along the lines of:
char filename[12];
int i = 0;
sprintf(filename, "test.csv");
while (fileExists(filename)) {
i++;
sprintf(filename, "test(%d).csv", i);
}
Note: fileExists() is just a placeholder function to whatever you need to check if the file exists (maybe write a little fileExists(char *filename) function to check the file existance for you).
Mon, 24 Feb 2014 18:14:31 +0000
deleted comment as it was an idiot responding
Mon, 24 Feb 2014 20:04:37 +0000
thank you majenko, you are the best!
if I could, I would buy you a round
Tue, 25 Feb 2014 14:53:32 +0000
why does it limit me to 8 characters for the file name?
char filename[100]; char timekeeper[12]; char datekeeper[12]; char testing[12]; sprintf(timekeeper, "%i:%i", hour, minute); sprintf(datekeeper, "%i_%i_%i", dayOfMonth, month, year); sprintf(testing, "delete_me"); int i = 0; sprintf(filename, "012345678.csv"); //// <--------here is where it limits me delay(5);
/while (SD.exists(filename)) { i++; sprintf(filename, "test(%i).csv", i); }/
int totalTests = 1234; char testsBuffer[50];
sprintf(testsBuffer, "Total Tests %i", totalTests);
// open the file. note that only one file can be open at a time, // so you have to close this one before opening another. myFile = SD.open(filename,FILE_WRITE); delay(200);
//if the file opened okay, write to it:
if (myFile) {
Serial.print("Writing to .csv...");
myFile.print(testsBuffer);
myFile.println(" ");
myFile.println(" ");
myFile.println(" ");
myFile.println(" ");
myFile.println(" ");
//close the file:
myFile.close();
Serial.println("done.");
}
else {
//if the file didn't open, print an error:
Serial.println("error opening");
}
//re-open the file for reading:
myFile = SD.open(filename);
if (myFile) {
Serial.println(filename);
//read from the file until there's nothing else in it:
while (myFile.available()) {
Serial.write(myFile.read());
}
//close the file:
myFile.close();
}
else {
//if the file didn't open, print an error:
Serial.println("error opening.csv");
}
} void loop() { // nothing happens after setup }
Tue, 25 Feb 2014 15:58:02 +0000
They are what are called "8.3" filenames, and have been the standard filename format since CP/M and right up to Windows 95, and even then under the hood the files are actually stored as "munged" 8.3 filenames.
[url]http://en.wikipedia.org/wiki/8.3_filename[/url]
It's basically due to the fact that the filesystem only has enough room in each directory entry to store 8 characters of filename and 3 letters of extension. That is why so many files have a 3-letter extension (.txt, .doc, .exe, .com, .bat, .vbs, .xls, etc).
Tue, 25 Feb 2014 16:02:08 +0000
awesome lol
so I will have to convert from long to short then add ~1, ~2, etc. to the end
again, thank you majenko
Fri, 28 Feb 2014 19:11:21 +0000
I have been trying to find info on how to capture the file created/last modified date and time.
example: file name created last modified myfile.txt 2/28/2014 2/28/2014
Does anyone have a sample or know of a tutorial for this?
Fri, 28 Feb 2014 19:44:41 +0000
File->Examples->SD->Card Info
Fri, 28 Feb 2014 19:50:11 +0000
You want to use the dirEntry() function of the SdFile object.
Something along the lines of:
dir_t dent;
if (myFile.dirEntry(&dent)) {
Serial.println(dent.lastWriteDate);
Serial.println(dent.lastWriteTime);
}
Comments in the FatStructs.h file say:
* Date Format. A FAT directory entry date stamp is a 16-bit field that is
* basically a date relative to the MS-DOS epoch of 01/01/1980. Here is the
* format (bit 0 is the LSB of the 16-bit word, bit 15 is the MSB of the
* 16-bit word):
*
* Bits 9-15: Count of years from 1980, valid value range 0-127
* inclusive (1980-2107).
*
* Bits 5-8: Month of year, 1 = January, valid value range 1-12 inclusive.
*
* Bits 0-4: Day of month, valid value range 1-31 inclusive.
*
* Time Format. A FAT directory entry time stamp is a 16-bit field that has
* a granularity of 2 seconds. Here is the format (bit 0 is the LSB of the
* 16-bit word, bit 15 is the MSB of the 16-bit word).
*
* Bits 11-15: Hours, valid value range 0-23 inclusive.
*
* Bits 5-10: Minutes, valid value range 0-59 inclusive.
*
* Bits 0-4: 2-second count, valid value range 0-29 inclusive (0 - 58 seconds).
*
* The valid time range is from Midnight 00:00:00 to 23:59:58.
Fri, 28 Feb 2014 21:25:06 +0000
Thank you majenko and Jacob
Naturally, the one place I didn't look. Such a fool. I guess that is why the authors took the time to write those notes.......
Sat, 01 Mar 2014 16:12:49 +0000
You should look at the sprintf function. Something along the lines of:
char filename[12];
sprintf(filename, "test.csv");
A plea here - if you can help it, please don't use sprintf! Use snprintf instead - it works almost exactly the same way, but requires you to specify the maximum length of the buffer it'll write to. This removes the risk of a buffer overflow screwing up your code when you're not expecting it. Effectively the code would become:
char filename[12];
snprintf(filename, sizeof(filename),"test.csv");
Fri, 07 Mar 2014 22:09:36 +0000
sorry majenko and jacob, I am trying to set the date and time of the file creation.
Sat, 08 Mar 2014 16:57:04 +0000
I've never tried this, but I found a thread here that may be applicable:
http://forum.arduino.cc/index.php?topic=72739.0
Jacob
Mon, 10 Mar 2014 12:54:18 +0000
OOOOH!! Good find Jacob. I am working on it now. Again, many thanks.
Mon, 10 Mar 2014 13:44:42 +0000
Here is a copy of the my testing file. Please ignore some of the randomness in it.
#include <SD.h> #include "Wire.h" #include <RTClib.h>
File myFile; const uint8_t SD_CS = 4; // SD chip select RTC_DS1307 RTC; // define the Real Time Clock object
// Default SD chip select const int chipSelect_SD_default = 4;
// chipSelect_SD can be changed if you do not use default CS pin const int chipSelect_SD = chipSelect_SD_default;
//*Begin Real Time Clock///
#define DS1307_I2C_ADDRESS 0x68 // This is the I2C address // Arduino version compatibility Pre-Compiler Directives #if defined(ARDUINO) && ARDUINO >= 100 // Arduino v1.0 and newer #define I2C_WRITE Wire.write #define I2C_READ Wire.read #else // Arduino Prior to v1.0 #define I2C_WRITE Wire.send #define I2C_READ Wire.receive #endif
// Global Variables
int command = 0; // This is the command char, in ascii form, sent from the serial port
long previousMillis = 0; // will store last time Temp was updated
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
byte test;
byte xero;
char *Day[] = {
"","Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
char *Mon[] = {
"","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
int sethour, setminute, setmonth, setdayofmonth, setyear;
// Convert normal decimal numbers to binary coded decimal byte decToBcd(byte val) { return ( (val/10*16) + (val%10) ); }
// Convert binary coded decimal to normal decimal numbers byte bcdToDec(byte val) { return ( (val/16*10) + (val%16) ); }
// 1) Sets the date and time on the ds1307 // 2) Starts the clock // 3) Sets hour mode to 24 hour clock // Assumes you're passing in valid numbers, Probably need to put in checks for valid numbers.
void setDateDs1307()
{
hour = sethour;
minute = setminute;
month = setmonth;
dayOfMonth = setdayofmonth;
year = setyear;
Wire.beginTransmission(DS1307_I2C_ADDRESS); I2C_WRITE(xero); I2C_WRITE(decToBcd(second) & 0x7f); // 0 to bit 7 starts the clock I2C_WRITE(decToBcd(minute)); I2C_WRITE(decToBcd(hour)); // If you want 12 hour am/pm you need to set // bit 6 (also need to change readDateDs1307) I2C_WRITE(decToBcd(dayOfWeek)); I2C_WRITE(decToBcd(dayOfMonth)); I2C_WRITE(decToBcd(month)); I2C_WRITE(decToBcd(year)); Wire.endTransmission(); }
void getDateDs1307() { // Reset the register pointer Wire.beginTransmission(DS1307_I2C_ADDRESS); I2C_WRITE(xero); Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
// A few of these need masks because certain bits are control bits second = bcdToDec(I2C_READ() & 0x7f); minute = bcdToDec(I2C_READ()); hour = bcdToDec(I2C_READ() & 0x3f); // Need to change this if 12 hour am/pm dayOfWeek = bcdToDec(I2C_READ()); dayOfMonth = bcdToDec(I2C_READ()); month = bcdToDec(I2C_READ()); year = bcdToDec(I2C_READ());
sethour = hour; setminute = minute; setmonth = month; setdayofmonth = dayOfMonth; setyear = year;
}
//------------------------------------------------------------------------------ // call back for file timestamps void dateTime(uint16_t* date, uint16_t* time) { DateTime now = RTC.now();
// return date using FAT_DATE macro to format fields *date = FAT_DATE(now.year(), now.month(), now.day());
// return time using FAT_TIME macro to format fields *time = FAT_TIME(now.hour(), now.minute(), now.second()); }
void setup() { int buff; unsigned int check[buff]; char settingsBuffer1[72]; char settingsBuffer2[72]; char settingsBuffer3[72]; char settingsBuffer4[72]; char settingsBuffer5[72]; char settingsBuffer6[72]; char settingsBuffer7[72]; char settingsBuffer8[72]; char settingsBuffer9[72]; char settingsBuffer10[72]; char settingsBuffer11[72]; char settingsBuffer12[72]; char settingsBuffer13[72]; char settingsBuffer14[72]; char settingsBuffer15[72]; char settingsBuffer16[72]; char settingsBuffer17[72]; char settingsBuffer18[72]; char settingsBuffer19[72]; char settingsBuffer20[72]; char settingsBuffer21[72]; char settingsBuffer22[72];
Serial.begin(9600); Wire.begin();
Serial.print("Initialixing SD card...");
pinMode(chipSelect_SD_default, OUTPUT); digitalWrite(chipSelect_SD_default, HIGH);
pinMode(chipSelect_SD, OUTPUT); digitalWrite(chipSelect_SD, HIGH);
if (!SD.begin(chipSelect_SD)) { Serial.println("initialixation failed!"); return; } Serial.println("initialixation done.");
char filename[50]; int num = 22; char testName[num]; int i = 0; int y = 1; int currentScale = 1; char scaleBuffer[3]; double loadLock = 12.97; char loadBuffer[6]; double timeLoad = 9999; char timeBuffer[5]; String testname = "AAAAAAAAAAAAAAAAAAAAA"; sprintf(filename, "setup.csv");
while (SD.exists(filename)) { SD.remove(filename); }
SdFile::dateTimeCallback(dateTime);
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another. myFile = SD.open("setup.csv",FILE_WRITE); delay(200);
//if the file opened okay, write to it:
if (myFile) { myFile.print("Current Scale_"); myFile.println(currentScale); //current scale myFile.println(" "); myFile.print("Load Lock_"); myFile.println(loadLock); //load lock on or off myFile.println(" ");
//close the file:
myFile.close();
Serial.println("done.");
} else { //if the file didn't open, print an error: Serial.println("error opening"); }
//re-open the file for reading: myFile = SD.open("setup.csv"); if (myFile) { //Serial.println("setup.csv");
//read from the file until there's nothing else in it:
while (myFile.available()) {
check[buff] = (myFile.read());
//Serial.println(check[buff]);
if (check[buff] == 95)
{
settingsBuffer1[i] = myFile.read();
delayMicroseconds(10);
settingsBuffer2[i] = myFile.read();
delayMicroseconds(10);
settingsBuffer3[i] = myFile.read();
delayMicroseconds(10);
settingsBuffer4[i] = myFile.read();
delayMicroseconds(10);
settingsBuffer5[i] = myFile.read();
delayMicroseconds(10);
settingsBuffer6[i] = myFile.read();
delayMicroseconds(10);
settingsBuffer7[i] = myFile.read();
delayMicroseconds(10);
settingsBuffer8[i] = myFile.read();
delayMicroseconds(10);
settingsBuffer9[i] = myFile.read();
delayMicroseconds(10);
settingsBuffer10[i] = myFile.read();
delayMicroseconds(10);
settingsBuffer11[i] = myFile.read();
delayMicroseconds(10);
settingsBuffer12[i] = myFile.read();
delayMicroseconds(10);
settingsBuffer13[i] = myFile.read();
delayMicroseconds(10);
settingsBuffer14[i] = myFile.read();
delayMicroseconds(10);
settingsBuffer15[i] = myFile.read();
delayMicroseconds(10);
settingsBuffer16[i] = myFile.read();
delayMicroseconds(10);
settingsBuffer17[i] = myFile.read();
delayMicroseconds(10);
settingsBuffer18[i] = myFile.read();
delayMicroseconds(10);
settingsBuffer19[i] = myFile.read();
delayMicroseconds(10);
settingsBuffer20[i] = myFile.read();
delayMicroseconds(10);
settingsBuffer21[i] = myFile.read();
delayMicroseconds(10);
settingsBuffer22[i] = myFile.read();
delayMicroseconds(10);
i++;
}
}
//close the file:
myFile.close();
} else { //if the file didn't open, print an error: Serial.println("error opening.csv"); } Serial.println("Done");
}
void loop() { // nothing happens after setup }
Mon, 10 Mar 2014 13:45:19 +0000
it works great at creating a file with the created on and last modified date.
Thu, 03 Apr 2014 14:43:41 +0000
when I save the test name to the SD card, and then read it back on start up, a 'space' and 'carraige return' are appended to the end. The test name goes from: testName.csv
to testName(space) (space).csv
Thu, 03 Apr 2014 15:20:22 +0000
ah, println adds the \n and I am picking up a (space).
strchr search and clip idea might work...
Thu, 24 Apr 2014 14:00:31 +0000
Now that I am writing and reading the files correctly, I am trying to read all file names, ls_date and ls_time and save into an array. I want to be able to display four files w/time stamps on my 4D systems display.
I found the following example:
#include <SD.h>
// set up variables using the SD utility library functions: Sd2Card card; SdVolume volume; SdFile root;
const int chipSelect_SD_default = 10; // Change 10 to 53 for a Mega
const int chipSelect_SD = chipSelect_SD_default;
void setup() { Serial.begin(9600); Serial.print("\nInitializing SD card...");
pinMode(chipSelect_SD_default, OUTPUT); digitalWrite(chipSelect_SD_default, HIGH);
pinMode(chipSelect_SD, OUTPUT); digitalWrite(chipSelect_SD, HIGH);
if (!card.init(SPI_HALF_SPEED, chipSelect_SD)) { Serial.println("Error"); return; } else { Serial.println("Loading..."); }
// Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32 if (!volume.init(card)) { Serial.println("No files"); return; }
Serial.println("Files"); root.openRoot(volume);
// list all files in the card with date and size root.ls(LS_R | LS_DATE | LS_SIZE); }
void loop(void) {
}
But I am not able to store anything as the .h file has this
void SdFile::ls(uint8_t flags, uint8_t indent) { dir_t* p;
rewind(); while ((p = readDirCache())) { // done if past last used entry if (p->name[0] == DIR_NAME_FREE) break;
// skip deleted entry and entries for . and ..
if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue;
// only list subdirectories and files
if (!DIR_IS_FILE_OR_SUBDIR(p)) continue;
// print any indent spaces
for (int8_t i = 0; i < indent; i++) Serial.print(' ');
// print file name with possible blank fill
printDirName(*p, flags & (LS_DATE | LS_SIZE) ? 14 : 0);
// print modify date/time if requested
if (flags & LS_DATE) {
printFatDate(p->lastWriteDate);
Serial.print(' ');
printFatTime(p->lastWriteTime);
}
// print size if requested
if (!DIR_IS_SUBDIR(p) && (flags & LS_SIZE)) {
Serial.print(' ');
Serial.print(p->fileSize);
}
Serial.println();
// list subdirectory content if requested
if ((flags & LS_R) && DIR_IS_SUBDIR(p)) {
uint16_t index = curPosition()/32 - 1;
SdFile s;
if (s.open(this, index, O_READ)) s.ls(flags, indent + 2);
seekSet(32 * (index + 1));
}
} }
it directly prints everything.
Any suggestions or tips are very appreciated.
Thank you.
Mon, 28 Apr 2014 14:10:20 +0000
I am using the following code to capture the file names when reading them from the uSD card, but I am having trouble saving the names to an array. What I have come up with so far only saves the last file name into the [0] location. Here is a copy of my code. Any suggestions would help.
#include <SD.h>
File root;
char fileName[21]; char fileName1[21]; char fileName2[21]; char fileName3[21]; int counter; int stamp; char* storefileName[200]; char* capturefileName[200];
void setup() { //genieBegin(GENIE_SERIAL, 9600); //Serial at 9600 baud for display Serial.begin(9600); pinMode(10, OUTPUT);
SD.begin(10);
root = SD.open("/"); }
void loop() { printDirectory(root, 0);
if(counter < 4) { Serial.println("done!"); //Serial.println(captureFilename); Serial.println("restart"); } else if(counter == 4) { sprintf(fileName, capturefileName[1]); Serial.println(fileName); sprintf(fileName1, capturefileName[2]); Serial.println(fileName1); sprintf(fileName2, capturefileName[3]); Serial.println(fileName2); sprintf(fileName3, capturefileName[4]); Serial.println(fileName3); Serial.println("printed fileName"); counter = 0; }; }
void printDirectory(File& dir, int numTabs) { while(true && counter <= 3) {
File entry = dir.openNextFile();
if (! entry)
{
// no more files
Serial.println("**nomorefiles**");
counter = 5;
}
else
{
storefileName[stamp] = entry.name();
capturefileName[stamp] = storefileName[stamp];
Serial.println(storefileName[stamp]);
Serial.println(counter,DEC);
Serial.println(stamp,DEC);
}
counter++;
stamp++;
}; }
Thank you.
Mon, 28 Apr 2014 18:28:07 +0000
I almost have it. I have created a vector of Strings.
Vector<String> filefinder; for (int num = 0; num < 512; ++num) { //boolean isfilefinder = true; for (size_t idx = 0; idx < filefinder.size(); ++idx) filefinder.push_back(num); filefinder[num] = tempfileName; /while(filecounter <= filefinder.size()) { //Serial.println(prime[counter]); filecounter++; if(filecounter == filefinder.size()) { //Serial.println(""); filecounter = 0; break; } }/ //delay(1000); } sprintf(fileName, "%s", filefinder[0]); genieWriteStr(37, fileName); } but I am getting the following error: error: cannot pass objects of non-trivially-copyable type 'class String' through '...'