[SOLVED]: List files from SD card on Seriall Monitor: not repeating

Hello,

I am pretty new with Arduino and programming in general.
I am playing with files in an SD card, using "SD.h" library. I tried most of the options and made them work correctly in a program. But I have found issues with listing files, and I got stuck.

Find below an example code (the original is embedded in a larger sketch, but this section is the one causing problems):

#include <SD.h>

File root;
String command;

void menu() {
  Serial.println(F("Menu options:"));
  Serial.println(F("'menu'  - Menu options"));
  Serial.println(F("'dir'   - List files and directories"));
  Serial.println();
}

void setup() {
  Serial.begin(9600);
  pinMode(10, OUTPUT);
  SD.begin(10);
  root = SD.open("/");
  menu();
}

void loop() {
  while(!Serial.available());
  if (Serial.available()) {  
    command = Serial.readStringUntil('\n');
    Serial.print(F("Command: "));
    Serial.println(command);
    
    if      (command == "menu")   menu();
    else if (command == "dir")    {
      printDirectory(root, 0);
      Serial.println("done!");
      Serial.println();
    }
  }
}

void printDirectory(File dir, int numTabs) {
  while(true) {
    File entry = dir.openNextFile();
 
    if (!entry)   break;
    
    for (uint8_t i=0; i<numTabs; i++) {
      Serial.print('\t');
    }
    Serial.print(entry.name());
    if (entry.isDirectory()) {
      Serial.println("/");
      printDirectory(entry, numTabs+1);
    } 
    else {
      Serial.print("\t\t");
      Serial.println(entry.size(), DEC);
    }
  }
}

If I enter the command "dir" for the first time (list all files and folders) it prints all files and directories from my SD card correctly.
But if I enter "dir" again, then it only prints "done!".

Please find below results from the serial monitor when I enter "menu", then when I enter "dir" for the first time, and then when I enter "dir" for the second time:

Menu options:
'menu' - Menu options
'dir' - List files and directories

Command: menu
Menu options:
'menu' - Menu options
'dir' - List files and directories

Command: dir
TEST.TXT 465
PREFS.TXT 0
TRAINER.LOG 799
TEXT.TST 0
SYSTEM~1/
INDEXE~1 76
WPSETT~1.DAT 12
TESTDIR/
TEST1.TXT 0
done!

Command: dir
done!

I can't find the problem myself. I would appreciate any suggestions.
Thanks in advance!

listTest.ino (1.16 KB)

You need to use rewindDirectory() before you try again.

Hi Wildbill, thanks for the response!

I have tried using "rewindDirectory()", but I still get some weird behavior:

The first time I enter the "dir" command, I get all the files and folders.
The second time, I only get a few of them.
The third time, I get nothing (only "done!", like when I was not using "rewindDirectory()").

Please find below my modified code and the results in the Serial Monitor:

#include <SD.h>

File root;
String command;

void menu() {
  Serial.println(F("Menu options:"));
  Serial.println(F("'menu'  - Menu options"));
  Serial.println(F("'dir'   - List files and directories"));
  Serial.println();
}

void setup() {
  Serial.begin(9600);
  pinMode(10, OUTPUT);
  SD.begin(10);
  root = SD.open("/");
  menu();
}

void loop() {
  while(!Serial.available());
  if (Serial.available()) {  
    command = Serial.readStringUntil('\n');
    Serial.print(F("Command: "));
    Serial.println(command);
    
    if      (command == "menu")   menu();
    else if (command == "dir")    {
      printDirectory(root, 0);
      Serial.println("done!");
      Serial.println();
    }
  }
}

void printDirectory(File dir, int numTabs) {
    while(true) {
    File entry = dir.openNextFile();

    if (!entry) {
      dir.rewindDirectory();
      break;
    }
    
    for (uint8_t i=0; i<numTabs; i++)   Serial.print('\t');
    Serial.print(entry.name());
    
    if (entry.isDirectory()) {
 
      Serial.println("/");
      printDirectory(entry, numTabs+1);
    } 

    else {
      Serial.print("\t\t");
      Serial.println(entry.size(), DEC);
    }
  }
}

Results when entering "dir" command three times:

Menu options:
'menu' - Menu options
'dir' - List files and directories

Command: dir
TEST.TXT 465
PREFS.TXT 0
TRAINER.LOG 799
TEXT.TST 0
TEST1.TXT 0
TEST7.TXT 0
NEWDIR/
SYSTEM~1/
INDEXE~1 76
WPSETT~1.DAT 12
TESTDIR/
TEST2.TXT 30
TEST3.TXT 0
TEST1.TXT 0
done!

Command: dir
TEST.TXT 465
PREFS.TXT 0
TRAINER.LOG 799
TEXT.TST 0
TEST1.TXT 0
TEST7.TXT 0
NEWDIR/
SYSTEM~1/
done!

Command: dir
done!

I guess I am not using "rewindDirectory()" correctly, but I cannot guess what would be the right way. I was looking at SD.h examples and this is how it was used...

listTest.ino (1.21 KB)

As additional info: I tried reducing the number of files and folders in the SD. Using the same sketch, with "rewindDirectory()", now I get the following:

The first time I enter "dir" command: all files and folders are shown correctly.
The second time I enter "dir" command: all files and folders are shown correctly.
The third time, I start loosing some files.
The fourth time, I loose some more files.
The fifth time I get nothing.

Find below results:

Menu options:
'menu' - Menu options
'dir' - List files and directories

Command: dir
TEST.TXT 465
TRAINER.LOG 799
SYSTEM~1/
INDEXE~1 76
WPSETT~1.DAT 12
TESTDIR/
TEST1.TXT 0
done!

Command: dir
TEST.TXT 465
TRAINER.LOG 799
SYSTEM~1/
INDEXE~1 76
WPSETT~1.DAT 12
TESTDIR/
TEST1.TXT 0
done!

Command: dir
TEST.TXT 465
TRAINER.LOG 799
SYSTEM~1/
INDEXE~1 76
TESTDIR/
done!

Command: dir
TEST.TXT 465
TRAINER.LOG 799
SYSTEM~1/
TESTDIR/
done!

Command: dir
done!

listTest.ino (1.21 KB)

IIRC, the SD library can only handle four open files. You may need to close some. To start with, I'd try moving the opening of root to your print directory function. I also wonder if dir.openNextFile consumes one of those four.

I'd rewind at the start of printDirectory unconditionally too.

:smiley: :smiley: :smiley:

I think you got it!! Thanks a lot for your help, I would have never found it myself :sob: :sob:

I did not know that "SD library can only handle four open files". That is a very good point. And I was not realizing that the sketch keeps opening every file, but it never closes any file.

I just entered "entry.close()" at the very end of the "while" funcition.
So everytime I print a file name, I close this file.

It is working good now. I also tried adding a few more files and directories, and it keeps working on and on.

Find below the final code:

#include <SD.h>

File root;
String command;

void menu() {
  Serial.println(F("Menu options:"));
  Serial.println(F("'menu'  - Menu options"));
  Serial.println(F("'dir'   - List files and directories"));
  Serial.println();
}

void setup() {
  Serial.begin(9600);
  pinMode(10, OUTPUT);
  SD.begin(10);
  root = SD.open("/");
  menu();
}

void loop() {
  while(!Serial.available());
  if (Serial.available()) {  
    command = Serial.readStringUntil('\n');
    Serial.print(F("Command: "));
    Serial.println(command);
    
    if      (command == "menu")   menu();
    else if (command == "dir")    {
      printDirectory(root, 0);
      Serial.println("done!");
      Serial.println();
    }
  }
}

void printDirectory(File dir, int numTabs) {
    while(true) {
    File entry = dir.openNextFile();

    if (!entry) {
      dir.rewindDirectory();
      break;
    }
    
    for (uint8_t i=0; i<numTabs; i++)   Serial.print('\t');
    Serial.print(entry.name());
        
    if (entry.isDirectory()) {
      Serial.println("/");
      printDirectory(entry, numTabs+1);
    } 

    else {
      Serial.print("\t\t");
      Serial.println(entry.size(), DEC);
    }
    entry.close();
  }
}

Find also below the results in Serial.Monitor (same results when I command "dir" again and again):

Command: dir
TEST.TXT 465
TEST13.TXT 0
TRAINER.LOG 799
TEST14.TXT 0
TEST15.TXT 0
TEST16.TXT 0
TESTDIR2/
FILE1.TXT 0
FILE2.TXT 0
FILE3.TXT 0
FILE4.TXT 0
FILE5.TXT 0
TESTDIR3/
TESTDIR4/
SYSTEM~1/
INDEXE~1 76
WPSETT~1.DAT 12
TESTDIR/
DIR2/
TEST2.TXT 0
TEST3.TXT 0
TEST4.TXT 0
TEST5.TXT 0
TEST6.TXT 0
TEST7.TXT 0
TEST10.TXT 0
TEST1.TXT 0
TEST11.TXT 0
TEST12.TXT 0

Thanks again, you fixed my issue!!