ESP32 / SD-карта: чтение атрибутов файлов в папке suf

#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!