Вопросы по библиотеке SdFat (Bill Greiman)

Я не прибедняюсь. Если бы сам мог разобраться, то не создавал бы тему и не спрашивал. К сожалению в документации на библиотеку я не могу пока найти ответ. Уже смотрел даже на код функции ls(), которая выводит листинг всех файлов.

Так вроде в правильную сторону глядите. У функции этой и флаг есть для рекурсивного обхода. Т.е. весь код уже есть готовый. Нужно сделать её аналог, не печатающий ничего в сериал, а только штуки считающий.

Да я выше написал, что вижу фигу, а не книгу.
В общем заработало, но я не могу понять в чем собственно дело
Рабочий кусок кода выглядит так:

void scanSD(FsFile &dir) {
  FsFile entry;  // вот и все изменение
  dir.rewind();
  while(entry.openNext(&dir, O_RDONLY)) {
    if (entry.isDir() && !entry.isHidden()) {
    Serial.print(F("/")); Serial.print(dirCnt);
    Serial.println(F(" DIR Found..."));    
    dirCnt++;
    scanSD(entry); 
  } 
  else if (entry.isFile()) {        
        fileCnt++;
    }
    entry.close();
  }
}

Собственно заработало, когда объявил структуру внутри функции. Почему не работало с глобально объявленной структурой я не знаю.

а где там “глобально обьявленная структура”? В вашем коде в #10 эта структура вообще никак обьявляется.

Но даже если бы она была глобальной - как вы себе представляете рекурсию с одной глобальной структурой?

не в сообщении #10, а в #1

Да просто в этом месте мои познания Си закончились. Я Вам ответить не смогу

Вы издеваетесь? Спрашиваете совета по коду, при этом часть его не показываете?

Совершенно очевидно, что раз вы задаете вопрос по коду - значит не до конца понимаете, как он работает. А значит не можете судить, какие части кода важны, а какие нет. Поэтому запомните - код всегда надо приводить ПОЛНОСТЬЮ.

нет.

#include "SdFat.h"
#include <SPI.h>

#define SD_CS           10
#define filenameLength  64

// SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h,
// 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT.
#define SD_FAT_TYPE 3

#if SD_FAT_TYPE == 0
SdFat sd;
File entry, currentDir;
#elif SD_FAT_TYPE == 1
SdFat32 sd;
File32 entry, currentDir;
#elif SD_FAT_TYPE == 2
SdExFat sd;
ExFile entry, currentDir;
#elif SD_FAT_TYPE == 3
SdFs sd;
FsFile entry, currentDir;
#else  // SD_FAT_TYPE
#error Invalid SD_FAT_TYPE
#endif  // SD_FAT_TYPE

uint16_t fileCnt;
uint16_t dirCnt;

char fName[filenameLength + 1];

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    // wait for serial port to connect. Needed for native USB port only
  }
  Serial.print(F("\nInitializing SD card..."));
  while (!sd.begin(SD_CS, SD_SCK_MHZ(4))) {
    delay(1000);
    Serial.println(F("initialization failed. Things to check:"));
    Serial.println(F("* is a card inserted?"));
  } 
  Serial.println(F("Wiring is correct and a card is present.")); 
  currentDir.close();
  currentDir.open("/", O_RDONLY); //set file to root directory
  Serial.println(F("\nDebug ScanSD"));
  scanSD(currentDir); // подсчитываем число папок и файлов  
  Serial.print(F("DIRs: \t")); Serial.println(dirCnt);
  Serial.print(F("FILEs: \t")); Serial.println(fileCnt);
}

void loop() {}

void scanSD(FsFile &dir) {
  FsFile entry; 
  dir.rewind();
  while(entry.openNext(&dir, O_RDONLY)) {
    if (entry.isDir() && !entry.isHidden()) {
    Serial.print(F("/")); Serial.print(dirCnt);
    Serial.println(F(" DIR Found..."));    
    dirCnt++;
    scanSD(entry); 
  } 
  else if (entry.isFile()) {        
        fileCnt++;
    }
    entry.close();
  }
}

А какое отношение рекурсия имеет к Си?

Ну может быть и не к СИ имеет отношение, но почему объявленная глобально структура обнуляется (или не передаёт своё значение) при рекурсии?

Есть еще вопрос по библиотеке SdFat.
Есть ли возможность получать расширение файла при вызове функции

size_t 	getName (char *name, size_t len)

в верхнем регистре? К примеру, вместо “.txt” получать “.TXT”?
Это для наглядности при выводе на дисплей.

Не знаю как получить сразу в верхнем, но что мешает после получения расширения (в любом регистре) перевести его в верхний функцией toUpperCase() ?

Хинт: Некоторые вопросы быстрее найти в гугле, чем на форумах спрашивать

Смотря что за структура и как она объявлена.
Например я вот здесь:

использовал глобально объявленную структуру в процессе рекурсии.
Но вообще, для каждого уровня рекурсии должен быть свой отдельный набор данных, например, та же структура. Иначе следующий уровень будет затирать данные предыдущего уровня, что сделает невозможным возврат из рекурсии.

Из соображений Всеобщей Гармонии такого быть не должно.
Манипуляции с регистром символов - это совсем не задача для библиотеки работы с накопителем.

Продолжаю изучать библиотеку SdFat. Назрела еще одна проблема и я пока не вижу лёгкого пути для её решения. Может кто-то подскажет мне?
Проблема в сортировке файлов и имен папок по алфавиту. Естественно, что при записи данных на карту памяти, данные пишутся в свободные ячейки последовательно. И при открытии файлов командой

openNext()

также последовательно и находятся файлы на карте. А хотелось бы получить сортировку по алфавиту.
В моём проекте в Arduino Uno/NANO нет просто памяти, для хранения всех имен папок и последующей сортировки программным методом.
Хочу услышать Ваши предложения. Я могу просто не знать какой-то мелочи и все окажется вполне решаемо.

Выбирайте инструмент по задаче. Нет памяти - забывайте про всякие папки, длинные пути, а то и вообще про файловые системы. Вы не за домашним компьютером! Если всё это нужно - берите контроллер с достаточными ресурсами.

А сортировка всегда делается программно - сортируется полученный список файлов, а не сами файлы на накопителе

не всегда

1 лайк

интересная опция, но вряд ли применима к случаю, когда вы часто дописываете новые файлы на частично заполненную карту

С этим спорить не буду. Но вышло так, что есть готовая железка, а прошивка мне не то, чтобы не нравится, но она еще у меня с ошибками работает. Намучавшись, решил написать свою. Времени потратил много на изучение, подошел, фактически, к финишу. Но вот сегодня столкнулся с тем, что прошивка считывает папки не по порядку и, разобравшись, понял почему. Теперь вот раздумываю, оставить как есть, или еще можно побарахтаться и спасти ситуацию? Реально 90% флэш памяти уже занято в ATmega328.

Спасибо! Изучу !
А мне друг еще такую ссылку подкинул. Изучаю…
https://forum.arduino.cc/t/sort-a-list-of-file-names-from-sd-card/899728

А если не секрет, что это всё-таки за изделие? Интересно, какой задаче необходима сортировка файлов и папок. На мой взгляд, сортировка нужна только человеку, т.е. в каком-то пользовательском интерфейсе. Логично, что в условном проводнике нам легче найти в списке конкретный файл, если список как-то упорядочен.
Но зачем это нужно микроконтроллеру - не представляю.

1 лайк

Не измеряли, сколько времени занимает просмотр папки при помощи openNext() ?
Может вас устроит это время? Тогда не сортируете, а просто ищите каждый раз заново следующий по порядку файл.

Вы всерьез считаете, что сортировка строк относится к задачам файловой системы?
В любой ОС файлы выдаются “как есть”, а сортировка, если она нужна - дело прикладной программы?

Так если ее нет, откуда она возьмется у драйвера файловой системы? Вы полагаете, что у него есть доступ к какому-то секретному пулу памяти, к которому Вас не допускают?

А тут извечная дилемма: по какому критерию оптимизировать - по памяти или по скорости. На Ардуино принято по памяти.