ESP32 a SPIFFS

14.05.2023 Arduino #esp32 #spiffs

Práce s uložištěm SPIFFS, které se používá pro ukládání větších dat ve formě souborů.


Použití souborového systému s ESP32 může být užitečné pro ukládání souborů HTML, CSS a JavaScript pro vytvoření webového serveru, místo aby bylo nutné vše zapisovat do programového kódu.

Představení SPIFFS

ESP32 obsahuje Serial Peripheral Interface Flash File System (SPIFFS). SPIFFS je odlehčený souborový systém vytvořený pro mikrokontroléry s flash čipem, které jsou propojeny sběrnicí SPI, jako je flash paměť ESP32.

SPIFFS umožňuje přistupovat k paměti flash jako v běžném souborovém systému ve vašem počítači, ale je jednodušší a omezenější. Můžete číst, zapisovat, zavírat a mazat soubory. SPIFFS nepodporuje adresáře, takže vše je uloženo na ploché struktuře.

Použití SPIFFS s  deskou ESP32 je zvláště užitečné pro:

  • Vytváření konfiguračních souborů s nastavením;
  • Ukládání trvalých dat;
  • Vytváření souborů pro uložení malého množství dat namísto použití karty microSD;
  • Uložení souborů HTML, CSS a JavaScript pro vytvoření webového serveru;
  • Ukládání obrázků a ikon;
  • A mnohem víc.

Nahrávání souborů do ESP32 SPIFFS

Soubory, které chceme nahrát do souborového systému ESP32, by měly být umístěny ve složce nazvané data ve složce projektu. Abychom  pochopili, jak vše funguje, nahrajeme txt soubor s nějakým náhodným textem. Můžeme nahrát jakýkoli jiný typ souboru.

Vytvoření datové složky

Ve složce projektu vytvořme složku s názvem dataTo lze provést přímp ve VS Code. Pomocí myši vyberte složku projektu, na které pracujete. Kliknutím na ikonu Nová složka vytvoříme novou složku.

Tato nová složka se musí nazývat data, jinak nebude fungovat.

Poté vyberte nově vytvořenou datovou složku a kliknutím na ikonu Nový soubor vytvořte soubory, které chcete nahrát. V tomto příkladu vytvoříme soubor s názvem text.txt. Můžete vytvořit a nahrát jakékoli jiné typy souborů, jako jsou například soubory .html.css nebo .js.

Napište do něj nějaký náhodný text.

Složka dat by měla být ve složce projektu a soubory, které chceme nahrát, by měly být uvnitř složky data. Jinak to nepůjde.

Nahrávání souborů do souborového systému

Po vytvoření a uložení souboru nebo souborů, které chceme nahrát do datové složky, postupujme podle následujících kroků:

  1. Klikněte na ikonu PIO na levém postranním panelu. Měly by se otevřít projektové úkoly.
  2. Vyberte env:esp32doit-devkit-v1 (může se mírně lišit v závislosti na desce, kterou používáme).
  3. Rozbalte nabídku Platform.
  4. Vyberte Vytvořit obraz souborového systému.
  5. Nakonec klikněte na Nahrát obrázek systému souborů.

Po chvíli byste měli dostat zprávu o úspěchu.

Testování SPIFFS

Níže uvedený příklad zahrnuje všechny funkce pro akce, které lze nad souborovým systémem provádět.

#include "FS.h"
#include "SPIFFS.h"

void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
    Serial.printf("Listing directory: %s\r\n", dirname);

    File root = fs.open(dirname);
    if(!root){
        Serial.println("- failed to open directory");
        return;
    }
    if(!root.isDirectory()){
        Serial.println(" - not a directory");
        return;
    }

    File file = root.openNextFile();
    while(file){
        if(file.isDirectory()){
            Serial.print("  DIR : ");
            Serial.println(file.name());
            if(levels){
                listDir(fs, file.path(), levels -1);
            }
        } else {
            Serial.print("  FILE: ");
            Serial.print(file.name());
            Serial.print("\tSIZE: ");
            Serial.println(file.size());
        }
        file = root.openNextFile();
    }
}

void readFile(fs::FS &fs, const char * path){
    Serial.printf("Reading file: %s\r\n", path);

    File file = fs.open(path);
    if(!file || file.isDirectory()){
        Serial.println("- failed to open file for reading");
        return;
    }

    Serial.println("- read from file:");
    while(file.available()){
        Serial.write(file.read());
    }
    file.close();
}

void writeFile(fs::FS &fs, const char * path, const char * message){
    Serial.printf("Writing file: %s\r\n", path);

    File file = fs.open(path, FILE_WRITE);
    if(!file){
        Serial.println("- failed to open file for writing");
        return;
    }
    if(file.print(message)){
        Serial.println("- file written");
    } else {
        Serial.println("- write failed");
    }
    file.close();
}

void appendFile(fs::FS &fs, const char * path, const char * message){
    Serial.printf("Appending to file: %s\r\n", path);

    File file = fs.open(path, FILE_APPEND);
    if(!file){
        Serial.println("- failed to open file for appending");
        return;
    }
    if(file.print(message)){
        Serial.println("- message appended");
    } else {
        Serial.println("- append failed");
    }
    file.close();
}

void renameFile(fs::FS &fs, const char * path1, const char * path2){
    Serial.printf("Renaming file %s to %s\r\n", path1, path2);
    if (fs.rename(path1, path2)) {
        Serial.println("- file renamed");
    } else {
        Serial.println("- rename failed");
    }
}

void deleteFile(fs::FS &fs, const char * path){
    Serial.printf("Deleting file: %s\r\n", path);
    if(fs.remove(path)){
        Serial.println("- file deleted");
    } else {
        Serial.println("- delete failed");
    }
}

void testFileIO(fs::FS &fs, const char * path){
    Serial.printf("Testing file I/O with %s\r\n", path);

    static uint8_t buf[512];
    size_t len = 0;
    File file = fs.open(path, FILE_WRITE);
    if(!file){
        Serial.println("- failed to open file for writing");
        return;
    }

    size_t i;
    Serial.print("- writing" );
    uint32_t start = millis();
    for(i=0; i<2048; i++){
        if ((i & 0x001F) == 0x001F){
          Serial.print(".");
        }
        file.write(buf, 512);
    }
    Serial.println("");
    uint32_t end = millis() - start;
    Serial.printf(" - %u bytes written in %u ms\r\n", 2048 * 512, end);
    file.close();

    file = fs.open(path);
    start = millis();
    end = start;
    i = 0;
    if(file && !file.isDirectory()){
        len = file.size();
        size_t flen = len;
        start = millis();
        Serial.print("- reading" );
        while(len){
            size_t toRead = len;
            if(toRead > 512){
                toRead = 512;
            }
            file.read(buf, toRead);
            if ((i++ & 0x001F) == 0x001F){
              Serial.print(".");
            }
            len -= toRead;
        }
        Serial.println("");
        end = millis() - start;
        Serial.printf("- %u bytes read in %u ms\r\n", flen, end);
        file.close();
    } else {
        Serial.println("- failed to open file for reading");
    }
}

void setup(){
    Serial.begin(115200);
    if(!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)){
        Serial.println("SPIFFS Mount Failed");
        return;
    }

    listDir(SPIFFS, "/", 0);
    writeFile(SPIFFS, "/hello.txt", "Hello ");
    appendFile(SPIFFS, "/hello.txt", "World!\r\n");
    readFile(SPIFFS, "/hello.txt");
    renameFile(SPIFFS, "/hello.txt", "/foo.txt");
    readFile(SPIFFS, "/foo.txt");
    deleteFile(SPIFFS, "/foo.txt");
    testFileIO(SPIFFS, "/test.txt");
    deleteFile(SPIFFS, "/test.txt");
    Serial.println( "Test complete" );
}

void loop(){

}

Literatura:

[1] ESP32 with VS Code and PlatformIO: Upload Files to Filesystem (SPIFFS) Random Nerd Tutorials [online]. USA: 2023 [cit. 2023-05-14]. Dostupné z: https://randomnerdtutorials.com/esp32-vs-code-platformio-spiffs/

[2] SPIFFS Espressif [online]. USA: 2023 [cit. 2023-05-14]. Dostupné z: https://github.com/espressif/arduino-esp32/blob/master/libraries/SPIFFS/examples/SPIFFS_Test/SPIFFS_Test.ino