#c #file #esp32
#c #файл #esp32
Вопрос:
Я пишу GPS и другие сенсорные программы. Точное приложение не так важно. Что я хочу сделать, так это записать данные журнала на SD-карту. Используя ESP32, мне, наконец, удалось подключить SD-модуль с использованием файлов mySD — используя пример под названием «nanosdcard» https://github.com/nhatuan84/esp32-micro-sdcard . Это позволяет мне получить доступ ко всем данным карты (тип карты, размер тома и т. Д.). Очень сложно найти примеры, которые позволяют вам назначать свои собственные соединительные контакты, например, то, что необходимо для ESP32 — проводка Arduino является стандартной и, по-видимому, жестко запрограммирована в файлах SD.
Используя пример, найденный здесь https://forum.arduino.cc/index.php?topic=348562.0 , я могу убедиться, что все файлы, записанные на SD-карту, имеют текущие и измененные метки даты и времени. Я написал функцию генератора имен файлов, которая использует следующий формат: YMMDDHHs.ext. «S» — это порядковый номер от 0 до 9, поэтому я могу генерировать до 10 уникальных файлов за час, при этом размер имени файла ограничен 8.3. Отметка времени — приятное дополнение.
Используя пример, найденный здесь https://forum.arduino.cc/index.php?topic=38150.0 , я могу перечислить файлы и распечатать метки даты и времени создания и изменения. Я также добавил некоторые другие вещи, такие как форматирование, тип файла и размеры файлов. Я подсчитываю размеры файлов (используя размеры блоков), чтобы получить очень приблизительную оценку используемого пространства — возможно, неточную, но ориентировочную.
Используя другой пример из приведенного выше примера, называемый «nanosdcard1», аналогичный этому http://www.iotsharing.com/2017/05/how-to-use-arduino-esp32-to-store-data-to-sdcard.html , я могу сканировать через SD-карту, содержащую вложенные папки, и код распечатывает файлы, папки и размеры файлов.
Одна вещь, которую я заметил, это то, что файл «nanosdcard» использует то, что кажется ссылками mySD.h, но «nanosdcard1» использует ссылки на типы SD (как если бы он ссылался на стандартный файл SD.h (SD.h не является включаемым файлом)).
Я изменил функцию «printDirectory», чтобы вызвать свою собственную функцию «PrintAccessData», которая принимает имя файла из printDirectory и получает доступ ко всем атрибутам файла. Функция «printDirectory» является рекурсивной, и как только она находит вложенную папку, она снова вызывает себя. Снова передаю имя файла в качестве параметра моей функции «PrintAccessData».
Все работает хорошо, когда файлы находятся только в корневой папке. Но что-то не работает, когда PrintAccessData необходимо распечатать сведения о файлах во вложенных папках.
Проблема, похоже, заключается в вызове «if (!file.open(amp;root, cFileName, FILE_READ))». Проверка в mySD показывает, что вызов должен быть «открытым (const char *filename, uint8_t mode = FILE_READ)». Файл не может быть открыт, поэтому ошибка «файл.напечатан «ошибка открытия».
Используя ссылку на тип SD, я могу открыть файл, используя полный путь, например «TXT/12345.TXT » и прочитайте содержимое. Я также могу записывать в файл, так что это не проблема. Основная цель достигнута.
Однако, как бы я ни старался, я не могу открыть файл с помощью приведенной выше команды (команды типа mySD). Я пытался:
- Жесткое кодирование имени файла и пути, с начальным «/» и без него
- Программный путь, сгенерированный из записи, найденной, когда код находит папку, также с начальным знаком «/» или без него
- Использование массивов символов (как указано в определении параметра) или строк в качестве параметра (оба работают для root, но не для вложенной папки)
It seems like there is some missing reference to the file within the subfolder preventing it from opening. Once the file has been opened (like the root files), then the dir_t struct can be populated and the various attibues read.
I’m stuck on opening a sub-folder file.
It is not a train smash that all the log files are in the root folder, but it would be nice to store different file types in different folders — I have made provision for identifying the file extention — the usual — txt, csv, dat, xls, doc, htm. The folder list could get very long.
The code works as is, but I would really like it to be more versatile / generic.
Any assistance would be greatly appreciated.
The PrintDirectory function. File dir is passed from a «SD.open(«/»)» call.
void PrintDirectory(File dir, byte numTabs) { // nanosdcard1.ino
long iFileSize = 0;
long iSizeTally = 0;
int iFileCount = 0;
// Begin at the start of the directory
dir.rewindDirectory();
while(true) {
File entry = dir.openNextFile();
if (!entry) {
// no more files
//Serial.println("**nomorefiles**");
break;
}
for (byte i=0; i<numTabs; i ) {
Serial.print(" "); // we'll have a nice indentation
}
// Print the 8.3 name
char *cFileName; // Create a pointer char variable - for the FileName
cFileName = entry.name(); // Assign the first entry of entry.name() to the FileName pointer created
Serial.print(cFileName);
// Recurse for directories, otherwise print the file size
if (entry.isDirectory()) {
Serial.println("/");
sPathName = entry.name();
// The way the creation and modification data is retrieved means that reading data from subfolders is not possible at this stage.
// The header file indicates *filepath, but I cannot get the code to recognise any conbination of filepath to open the file
PrintDirectory(entry, numTabs*2); // This is the recursion occurs
} else {
// Files have sizes, directories do not
// Display the date and time values, then file sizes
PrintAccessData(cFileName, sPathName);
Serial.print(F("t"));
if (entry.size() > 1024*1024) { // > 1 MB
Serial.print(entry.size()/1024.0/1024.0, 2);
Serial.println(F(" MB"));
} else if (entry.size() > 1024) { // > 1kB
if (entry.size() > 102400) { // > 100 kb
Serial.print(entry.size()/1024.0, 0);
} else {
Serial.print(entry.size()/1024.0, 2);
}
Serial.println(F(" kB"));
} else { // bytes
Serial.print(entry.size(), DEC);
Serial.println(F(" bytes"));
}
// Files file complete blocks of 512 bytes even if smaller than 512
iFileSize = int(entry.size()/512)*512; // Number of whole blocks
if (entry.size()%512 > 0) { // Any partial blocks
iFileSize = 512;
}
iSizeTally = iFileSize;
iFileCount ;
}
entry.close();
}
Serial.print(F(" Estimated total disk usage: "));
if (iSizeTally > 1024*1024) { // > 1 MB
Serial.print(iSizeTally/1024.0/1024.0, 2);
Serial.print(F(" MB"));
} else if (iSizeTally > 1024) { // > 1 kB
if (iSizeTally > 102400) { // > 100 kB
Serial.print(iSizeTally/1024.0, 0);
} else {
Serial.print(iSizeTally/1024.0, 2);
}
Serial.print(F(" kB"));
} else { // bytes
Serial.print(iSizeTally, 0);
Serial.print(F(" bytes"));
}
Serial.print(F(" ("));
Serial.print(float(iSizeTally)/iVolumeSize, 3);
Serial.print(F("%"));
Serial.print(F(")"));
Serial.print(F(" in "));
Serial.print(iFileCount);
Serial.println(F(" files"));
}
Функция PrintAccessData.Я добавил довольно много вызовов file.close() и root.close(), потому что программе, похоже, это нужно, чтобы записать следующий файл для чтения атрибутов.
boolean PrintAccessData(char *cFileName, String sPath) {
byte bFileTypeLen = 0; // Length of the extension name to help align the size numbers later
// open the root directory
if (!root.openRoot(amp;volume)) {
Serial.print(" openRoot failed");
file.close();
root.close();
return false;
}
// open a file
if (!file.open(amp;root, cFileName, FILE_READ)) { // Probably need to change amp;root to point to the next location / directory. Does not work with path/file
Serial.print(" file.open failed. Can't handle subfolder callstt");
file.close();
root.close();
return false;
}
dir_t d;
if (!file.dirEntry(amp;d)) { // Test with a folder name?
Serial.println("file.dirEntry failed");
file.close();
root.close();
return false;
}
Serial.print("t");
file.printFatDate(d.creationDate);
Serial.print(" ");
file.printFatTime(d.creationTime);
Serial.print("t");
file.printFatDate(d.lastWriteDate);
Serial.print(" ");
file.printFatTime(d.lastWriteTime);
Serial.print("t");
Serial.print(GetFileExtension(cFileName, bFileTypeLen));
for (byte i=0; i<(22-bFileTypeLen); i ) { // "Comma Separated Values" is the longest file name at 22 characters. Adjust if required.
Serial.print(F(" "));
}
file.close();
root.close();
}
Вывод программы выглядит следующим образом:
* Connecting to WiFi .. connected
IP address: 192.168.1.2
* Contacting to Time Server ... connected
Now is : 2020-12-16 16:19:05
* Initializing SD card...
Card type: SD2
Volume type is FAT32
Volume size: 1932.08 MB, 1.887 GB
... successful
No valid filename generated **Disabled for now, or else it generated a new file every run**
* Files on SD Card:
Name Date Created Date Modified Type Size
01210110.CSV 2020-12-15 10:21:48 2020-12-10 11:18:44 Comma Separated Values 58 bytes
01210111.CSV 2020-12-15 10:21:48 2020-12-10 11:18:48 Comma Separated Values 58 bytes
01210112.CSV 2020-12-15 10:21:48 2020-12-10 11:18:50 Comma Separated Values 58 bytes
01210113.CSV 2020-12-15 10:21:48 2020-12-10 11:18:54 Comma Separated Values 58 bytes
01210114.CSV 2020-12-15 10:21:48 2020-12-10 11:18:58 Comma Separated Values 58 bytes
01210180.TXT 2020-12-15 10:21:50 2020-12-15 09:14:28 Text File 1.96 MB
01210181.TXT 2020-12-15 10:21:50 2020-12-15 09:15:02 Text File 106 kB
01210191.TXT 2020-12-15 10:21:50 2020-12-15 09:15:02 Text File 56.64 kB
01210192.TXT 2020-12-15 10:21:50 2020-12-15 09:15:02 Text File 566 kB
01210195.TXT 2020-12-15 10:21:50 2020-12-15 09:15:02 Text File 5.53 MB
01211080.TXT 2020-12-15 10:21:52 2020-12-15 09:15:04 Text File 4.35 MB
01211081.TXT 2020-12-15 10:22:26 2020-12-15 09:15:04 Text File 4.35 MB
01213150.TXT 2020-12-15 10:22:26 2020-12-15 09:15:06 Text File 4.35 MB
01213160.TXT 2020-12-15 10:22:26 2020-12-15 09:15:06 Text File 81.05 kB
01215110.CSV 2020-12-15 10:22:26 2020-12-15 11:38:28 Comma Separated Values 152 bytes
01215111.CSV 2020-12-15 10:22:26 2020-12-15 11:39:54 Comma Separated Values 14.84 kB
01215112.CSV 2020-12-15 10:22:26 2020-12-15 11:43:38 Comma Separated Values 14.84 kB
01215113.CSV 2020-12-15 10:22:26 2020-12-15 11:45:32 Comma Separated Values 14.84 kB
01215114.CSV 2020-12-15 10:22:26 2020-12-15 11:46:44 Comma Separated Values 14.84 kB
Estimated total disk usage: 21.40 MB (0.011%) in 19 files
...done!