B4R Question ESP8266 strange results on the log when listing files on flash

max123

Well-Known Member
Licensed User
Longtime User
Hi all,

I started to use ESP8266 with SPIFFS File System B4R library following Erel tutorial
https://www.b4x.com/android/forum/threads/resp8266filesystem-spiffs.76487/#post-512263

Initially I had problems and ESP8266 crashed any time when listing files, after Erel's suggest me to increase a buffer size and it magically started to work.

I just increased the StackBufferSize to 2000 bytes.

Now I've a new problem, I count files with this code, it count 118 files and this is ok, but the log show a strange result as count of files...

See on the log a number inside a first square bracket, as you can see, very strange results. I use a local UInt variable to count all files, if I declare it (fileCount) as Global do not work at all.

This sometime works, sometime do not works....

This is the code:
B4X:
Sub ListFiles
    Dim fileCount As UInt = 0
    For Each f As File In fs.ListFiles("/")
        fileCount = fileCount + 1
        Log("[", fileCount, "]   [ ", f.Name, " ]    ", f.Size, " bytes     StackBufferUsage: ", StackBufferUsage)
        astream.Write(f.Name).Write(Array As Byte(10))
    Next
    astream.Write(Array As Byte(0xff, 0xff, 0xff))
    Log("Found ", fileCount, " files")
End Sub

And this is the log:

Any suggestion?
Many thanks.
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
What is strange in the logs?

Don't create a new array of bytes each iteration. Change the code to:
B4X:
Dim ten() As Byte = Array As Byte(10)
For Each f As File In fs.ListFiles("/")
 fileCount = fileCount + 1
Log("[", fileCount, "] [ ", f.Name, " ] ", f.Size, " bytes StackBufferUsage: ", StackBufferUsage)
 astream.Write(f.Name).Write(ten)
Next
 
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
In the log is strange the number of file count, the first number of every line.

But now i know my error as you suggested, I need to declare the array that sends chr(10) outside a For Each loop.

Many thanks for your great support.

EDIT: sometime works and sometime log show wrong file number, in strange order, as my last log, eg. 72, 73, 74, 90, 96, 100, 92, 97 etc.. non progressive order
 
Last edited:
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Mmmmm... I tried to add a Delay(100) inside a For Each loop, it is very slow listing files but do not solve the problem.
The question still open.
 
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
I think this is not relative to AStream.Write line, I've tried to reproduce this issue on a small project, the problem persirst even if I add a Delay(100).
The problem seem to be relative to a serial logger or the fs.ListFiles("/") file iterator, this is strange, while I list all files the IDE do not respond, while we exit from a For Each loop, the IDE return to respond. Or maybe is wrong my code when I enable or disable timers.

This is the code:
B4X:
Sub Process_Globals
    Public Serial1 As Serial
    Private fs As ESP8266FileSystem
    Private Timer1 As Timer
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Log(" ") : Log("AppStart")
    If Not(fs.Initialize()) Then
        Log("Unable to initialize File System")
        Return
    End If
    Log("File System successfully initialized")
    Timer1.Initialize("ListFiles", 5000)
    Timer1.Enabled = True
End Sub

Sub ListFiles
    Timer1.Enabled = False
    Dim fileCount As UInt = 0
    For Each f As File In fs.ListFiles("/")
        fileCount = fileCount + 1
        Log("[", fileCount, "] [ ", f.Name, " ] ", f.Size, " bytes StackBufferUsage: ", StackBufferUsage)
        Delay(100)
    Next
    Log("Found ", fileCount, " files")
    Timer1.Enabled = True
End Sub
 
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Yes #AutoFlushLogs attribute is set to true by default.

Full code:
B4X:
#Region Project Attributes
    #AutoFlushLogs: True
    #CheckArrayBounds: True
    #StackBufferSize: 2000
#End Region

Sub Process_Globals
    Public Serial1 As Serial
    Private fs As ESP8266FileSystem
    Private Timer1 As Timer
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Log(" ") : Log("AppStart")   
    If Not(fs.Initialize()) Then
        Log("Unable to initialize File System")
        Return
    End If
    Log("File System successfully initialized")
    Timer1.Initialize("ListFiles", 5000)
    Timer1.Enabled = True
End Sub

Sub ListFiles
    Dim fileCount As UInt = 0   
    For Each f As File In fs.ListFiles("/")
        fileCount = fileCount + 1
        Log("[", fileCount, "] [ ", f.Name, " ] ", f.Size, " bytes StackBufferUsage: ", StackBufferUsage)
        Delay(100)
    Next   
    Log("Found ", fileCount, " files")
End Sub
 
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Using this code on Arduino IDE works perfectly without need to reset watchdog timer or add any delay:

B4X:
void listFileSystem(const char *dir) {
  String str = "";
  short fileCount = 0;
  Serial.println("\nListing files in folder \"" + (String)dir + "\"\n");
  Dir d = SPIFFS.openDir(dir);
  while (d.next()) {
      fileCount++;
      str += "[";
      str += (String)fileCount;
      str += "]  ";
      str += d.fileName();
      str += "\t";
      str += d.fileSize();
      str += " bytes\r\n";
  }
  if (fileCount == 0) {
    Serial.println("No files found in folder \"" + (String)dir + "\"");
  } else {
    Serial.println(str);
    Serial.println("Found " + (String)fileCount + " files");
  }
}
 
Last edited:
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Do you intend a B4R or Arduino code? I can send you....

I searched inside a rESP8266FileSystem cpp file, I see this:
B4X:
bool FileIterator::MoveNext() {
        current->file.close();
        if (dir.next()) {
            current->file = dir.openFile("r");
            return true;
        } else {
            return false;
        }
    }

Because you open any file as read mode to test it?

This line I think is not needed: current->file = dir.openFile("r");
just return True if dir.next(), open a file require time.
 
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
I've tested it with this code:
B4X:
Private Sub AppStart
   Serial1.Initialize(115200)
   Log("AppStart")
   Log(sp.Initialize)
   'sp.Format
   Log("after format")
   Log(sp.Exists("/1.txt"))
   If sp.Exists("/1.txt") = False Then
     For i = 1 To 200
       Log(i)
       CreateFile(i)
     Next
   End If
   Dim fileCount As UInt = 0
   For Each f As File In sp.ListFiles("/")
     fileCount = fileCount + 1
     Log("[", fileCount, "] [ ", f.Name, " ] ", f.Size, " bytes StackBufferUsage: ", StackBufferUsage)
   Next
   Log("after")
End Sub

Sub CreateFile(i As Int)
   sp.OpenReadWrite(JoinStrings(Array As String("/", i, ".txt")))
   sp.Stream.WriteBytes("abc", 0, 3)
   sp.Stream.Flush
   sp.Close
End Sub
The code creates 200 files on the first run and then lists all the files.
The output was correct.
 
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Many thanks for your code, I test it....

To create files I've used this tool as Arduino IDE plugin to send any file I want to ESP8266 flash, then i can list and read any file, .txt files, .ini files, .html files, image files and virtually any file that fits on the flash (My NodeMCU has 4MB, Wemos D1 and D1 Mini too, Wemos D1 Mini Pro has 16Mb flash).

https://github.com/esp8266/arduino-esp8266fs-plugin

Using this tool I send on ESP8266 Flash up 160 bitmap images, then I read it one by one and show on small 96x64 65535 colors Oled (with SSD1331 controller) over SPI bus and my library I wrote for this Oled show up 30 FPS, so I can see small videos from flash. My library can use SD too...
Using this tool I can send a Wave file, then read it's header, extract data and read/write any sample one by one, copy wave file data and append to another wave file with library I wrote.

Flash works very well....

If you want I have some Arduino code that write and read on flash
 
Last edited:
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
Your code works!

But you used same commands? I still searched to know what is the difference, only you put it inside AppStart sub
B4X:
   Dim fileCount As UInt = 0
   For Each f As File In fs.ListFiles("/")
     fileCount = fileCount + 1
     Log("[", fileCount, "] [ ", f.Name, " ] ", f.Size, " bytes StackBufferUsage: ", StackBufferUsage)
   Next
What is the difference? Maybe because I've decided to format Flash memory before to create new files? Now I try to rewrite my images and test with your code.
 
Upvote 0

max123

Well-Known Member
Licensed User
Longtime User
As you see my code is small.... and same code on Arduino IDE works very well. The problem I think is a very slow serial log.

I've tried to program ESP8266 on Arduino IDE, and then tried only to show serial log of Arduino sketch on B4R (the Arduino serial log and any my B4J program that show a serial log works well, in the B4R serial log I've strange results, sometime it miss some lines, sometime it show duplicate lines.

On same Sketch but visualized on different serial log this is the result:

Arduino IDE Serial log:

B4R Serial log:
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…