I used the edited official example (shown below) to test creating a folder and creating files under that folder.
#include <SPI.h>
#include <SD.h>
#define DATA_DIR "SENSOR" // limit 8 characters (8.3 filenmae)
#define RECORD_FILE_EXT ".CSV"
#define SERIAL_PRINTLN(x) (Serial.println(F(x))) // for decrease RAM usage
const int chipSelect = 10; // 4
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(115200);
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:
while (1);
}else {
Serial.println("card initialized.");
if (SD.mkdir(DATA_DIR))
{
SERIAL_PRINTLN("dir is created.");
}
else
{
SERIAL_PRINTLN("1.dir is exist, or");
SERIAL_PRINTLN("2. dir name is invalid, or");
SERIAL_PRINTLN("3. parent is not dir, or");
SERIAL_PRINTLN("4. parent is already open");
}
}
}
void loop() {
String dataString = String(random(1000));
char str[32] = "";
strcat(str, DATA_DIR);
strcat(str, "/");
strcat(str, "20191213");
strcat(str, RECORD_FILE_EXT);
File dataFile = SD.open(str, FILE_WRITE);
if (dataFile) {
dataFile.println(dataString);
dataFile.close();
// print to the serial port too:
Serial.println(dataString);
} else {
SERIAL_PRINTLN("error opening dataFile");
}
delay(1000);
}
The problem I encountered was this:
If I insert a blank SD card first and let Arduino boot, the folder I want to create will be written as a file.
I have to start arduino first, then insert a blank SD card, and then reset Arduino. In this way, folders and files can be created normally.
What causes this problem?
I use Arduino Nano ATmega328P, and SD card has been formatted to FAT32, SD library version is 1.2.4
In setup(), SD.mkdir("SENSOR") will create the dir on root and current path will become that one (SENSOR). If the same dir already exists, it will just become current. Further there is no need to explicitly set path for the filename, otherwise it will actually try to write in "SENSOR/filename.CVS", the full path with filename becomes "/SENSOR/SENSOR/filename.CVS". Certainly '/SENSOR/SENSOR' dir doesn't exists, if lib itself even can parse such long string...
Just use filename instead, since current path is already set:
Since there is no SD.end() method for the SD lib, card must be inserted before firmware start to execute and must not be ejected until power is turned off.
Ans since many SD card modules do not have pin which can indicate to MCU that SD card is physically inserted or ejected, inside loop() any operation with SD card must fail if it is physically ejected after setup() and non of further actions should be possible with SD card.
I have made altered SD lib with SD.end() method which correctly flush existed data, release instance of the class, thus it will be able to eject and switch SD cards whenever explicitly ordered by firmware itself.
"delay(1000); // needed delay for SD card creating directory correctly"
I do not think that require 1000ms delay...
It may be a problem to stabilize voltage on power on, i.e. until capacitors where charged, but that is few ms only. If you have a need for 1000ms, something may be really wrong with SD card or voltage stability.
In some sketches I have seen something like this:
void setup() {
delay(10); // Voltage stabilization delay
....
}
As well this after serial port initialization:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}