Hallo und willkommen zu unserem heutigen Beitrag.
Die ESP Module erfreuen sich sehr großer Beliebtheit. Wir haben in der Vergangenheit schon gezeigt wie einfach es ist sich mit dem WLAN zu verbinden, Webseiten anzuzeigen, und Relais zu schalten.
Eine sehr nützliche Funktion ist jedoch das ablegen von Daten in den Flash Speicher des ESPs. So ist es möglich Dateien hochzuladen, auf die wir später mit unserem Sketch zugreifen können. Oder Informationen zu speichern die auch nach einem Neustart noch verfügbar sind.
Dateien auf den ESP hochladen
Wir benötigen das Tool "ESP8266FS" - eine Erweiterung die sich in die Arduino IDE integriert. Es fügt im Menü "Werkzeuge" den Eintrag "ESP8266 Sketch Data Upload" hinzu.
Als erstes laden wir uns das Tool von der ESP8266 GitHub Seite herunter:
https://github.com/esp8266/arduino-esp8266fs-plugin/releases/download/0.1.3/ESP8266FS-0.1.3.zip
Wir erstellen nun einen Ordner mit dem Namen "tools" im gleichen Ordner wie unsere Arduino-Sketche. Normalerweise befindet sich dieser unter "C:\Users\<benutzername>\Documents\Arduino\".
Entpacken Sie die heruntergeladene .zip Datei und kopieren Sie den Ordner ESP8266FS in das "tools" Verzeichnis. Am Ende haben wir dann "C:\Users\<benutzername>\Documents\Arduino\tools\ESP8266FS\tool\esp8266fs.jar".
Nun starten wir die Arduino IDE neu, und machen einen neuen Sketch. Ich nenne meinen in diesem Beispiel "ESP-Data-Test". Diesen Sketch müssen wir nun speichern.
Wir navigieren nun in den neu erstellten Ordner "C:\Users\<Benutzername>\Documents\Arduino\ESP-Data-Test" und legen dort den Ordner "data" an. Alle Dateien die hier abgelegt werden, werden in den Flash-Speicher des ESPs hochgeladen, sobald wir den Upload durchführen.
Ich lege eine neue Textdatei mit dem Namen test.txt an, schreibe ein Paar Zeilen Text hinein, und speichere diese in den neuen "data" Ordner.
Ich verwende einen ESP8266-01S mit USB-Adapter, also stelle ich unter Werkzeuge folgende Optionen ein:
- Board: "Generic ESP8266 Module"
- Flash Size: "1M (64K SPIFFS)
- Upload Speed: "115200"
- Port: "COMx" - ihren COM-Port auswählen
Falls Sie die Speichergröße ihres Moduls nicht kennen, gibt es am Ende des Artikels einen Tipp wie Sie diese bestimmen können.
Als Test versuchen wir nun den leeren Sketch (nur void setup() und void loop()) auf den ESP zu laden. Für meinen ESP muss ich dafür sicherstellen dass der Programmiermodus aktiviert ist.
Wenn das alles funktioniert hat, können wir versuchen den Inhalt des "data" Ordners auf den ESP zu laden. Dafür gehen wir auf "Werkzeuge" -> "ESP8266 Sketch Data Upload".
In der IDE erscheint "SPIFFS Uploading Image..." ... und nach kurzer Zeit erscheint: "SPIFFS Image Uploaded":
Falls an dieser Stelle ein Fehler kommt ("SPIFFS Upload failed!"), dann vermutlich weil sich der ESP nicht mehr im Programmiermodus befindet. Einfach die USB Verbindung trennen und wieder verbinden, und dabei sicherstellen das der Programmiermodus aktiviert wird.
SPIFFS im Sketch verwenden
Um SPIFFS im Sketch nutzen zu können, binden wir die Bibliothek FS.h ein:
#include "FS.h"
Nun stehen uns folgende Befehle zur Verfügung:
Filesystem Objekt (SPIFFS)
SPIFFS.begin()
Mountet das SPIFFS Filesystem. Muss immer vor allen anderen Befehlen ausgeführt werden. Gibt "true" zurück, falls das Mounten funktioniert hat, ansonsten "false".
SPIFFS.format()
Formatiert (löscht) das Filesystem. Gibt "true" zurück wenn die Formatierung erfolgreich war.
SPIFFS.open(path, mode)
Öffnet eine Datei. Als "path" geben sie den Dateinamen inklusive dem absoluten Pfad an (z.B. "/Ordnername/test.txt"). "mode" gibt die Art des Zugriffs an. Kann folgende Optionen enthalten: "r", "w", "a", "r+", "w+", "a+".
- "r" Öffnet die Datei zum Lesen. Die Datei muss existieren
- "w" Erstellt eine neue Datei ohne Inhalt. Falls eine Datei mit gleichem Namen existiert wird deren Inhalt gelöscht, und die Datei wird als neue leere Datei gesehen.
- "a" Hängt Daten an die Datei an ("append"). Die Daten werden am Ende der Datei angehängt. Falls die Datei nicht existiert, wird eine neue erstellt.
- "r+" Öffnet eine Datei zum lesen und schreiben. Die Datei muss existieren.
- "w+" Erstellt eine leere Datei zum lesen und schreiben.
- "a+" Öffnet eine Datei zum lesen, sowie zum anhängen.
if (!f) {
Serial.println("file open failed");
}
SPIFFS.exists(path)
Gibt "true" zurück falls der Pfad existiert, ansonsten "false".
SPIFFS.openDir(path)
Öffnet das angegebene Verzeichnis. Gibt ein "dir" Objekt zurück.
SPIFFS.remove(path)
Löscht den angegebenen Pfad. Gibt ein "true" zurück falls die Löschung erfolgreich war.
SPIFFS.rename(pathFrom, pathTo)
Nennt eine Datei um von "pathFrom" nach "PathTo". Der Pfad muss absolut sein. Gibt ein "true" zurück falls das Umbenennen erfolgreich war.
Filesystem Info Struktur
FSInfo fs_info;
SPIFFS.info(fs_info);
Füllt die FSInfo Struktur mit Informationen zum Filesystem. Gibt ein "true" zurück bei Erfolg, ansonsten ein "false".
Struktur:
struct FSInfo {
size_t totalBytes;
size_t usedBytes;
size_t blockSize;
size_t pageSize;
size_t maxOpenFiles;
size_t maxPathLength;
};
Verzeichnis Objekt (Dir)
Das "Dir" Objekt ermöglicht es uns Dateien innerhalb eines Verzeichnisses anzusprechen mittels den Methoden "next()", "filename()" und "openFile(mode)".
Dir dir = SPIFFS.openDir("/data");
while (dir.next()) {
Serial.print(dir.fileName());
File f = dir.openFile("r");
Serial.println(f.size());
}
dir.next() ist "true" solange es Dateien in dem Verzeichnis findet. Es muss vor "fileName" oder "openFile" aufgerufen werden.
"openFile" nimmt das "mode" Argument, welches identisch ist wie bei SPIFFS.open.
Datei Objekt (file)
SPIFFS.open und dir.openFile geben ein "file" Objekt zurück. Dieses ist ein Streamobjekt und unterstützt alle Funktionen wie "readbytes", "findUntil", "parseInt", "println" und alle anderen Stream Methoden.
Es gibt aber auch einige die für das Datei Objekt (file) spezifisch sind.
file.seek(offset, mode)
Funktioniert wie die fseek Funktion in C. Die aktuelle Position verschiebt sich je nach dem Wert von "mode" wie folgt:
- SeekSet -> Position wird auf "offset" Bytes vom Anfang gesetzt
- SeekCur -> aktuelle Position wird um "offset" Bytes verschoben
- SeekEnd -> Position wird auf "offset" Bytes vom Ende der Datei desetzt
file.position()
Gibt Aktuelle Position innerhalb der Datei als Wert in Bytes wieder
file.size()
Gibt die Dateigröße in Bytes wieder.
file.name();
Gibt den Dateinamen als "const char*" wieder. Kann mittels "String name = file.name();" in einen String gespeichert werden.
file.close()
Schließt die Datei.
Praxisbeispiel
Nun schreiben wir einen kleinen Sketch um das ganze zu testen: wir wollen unsere Textdatei "test.txt" welche wir am Anfang erstellt und mit ein Paar Zeilen Text befüllt haben auf den seriellen Monitor ausgeben.
#include "FS.h" // Hier binden wir die benötigte Bibliothek ein void setup() { Serial.begin(9600); // Serielle Ausgabe aktivieren delay(1000); // Kurze Pause, damit wir Zeit haben den Seriellen Monitor zu öffnen. SPIFFS.begin(); // Filesystem mounten File f = SPIFFS.open( "/test.txt", "r"); // Datei zum lesen öffnen if (!f) { Serial.println("file open failed"); } String data = f.readString(); // Inhalt der Textdatei wird gelesen... Serial.println("Inhalt der geöffneten Datei:"); Serial.println(data); // ... und wieder ausgegeben f.close(); // Wir schließen die Datei } void loop() { }
Nach dem hochladen erscheint dann die Ausgabe auf dem seriellen Monitor:
Bonus Tipp: Wie groß ist der Flash-Speicher meines ESP 8266?
Je nachdem welches ESP8266-Modul Sie verwenden, kann sich die Größe des flash Speichers unterscheiden. Zwar kann man anhand der Beschriftung auf dem Chip nach dem Datenblatt suchen, aber um ganz sicher zu gehen gibt es einen kleinen Sketch der die Größe, Geschwindigkeit und den Modus Ihres Moduls überprüft. Den Sketch gibt es auf https://github.com/esp8266/Arduino/tree/master/libraries/esp8266/examples/CheckFlashConfig
Diesen Sketch einfach hochladen, und den Seriellen Monitor auf 115200 Baud stellen, schon wird uns die Größe des Chips angezeigt.
Ich hoffe unser heutiger Blog-Beitrag hat Ihnen gefallen, und ihre Kreativität angeregt. Ab sofort können Sie die SPIFFS Funktion ihres ESP nutzen um z.B. HTML Textbausteine abzulegen, Sensordaten dauerhaft zu speichern, und vieles mehr.
Wir freuen uns sehr über Lob, Kritik und Anregungen zu unserem Blog.
Ihr Markus Neumann
14 Kommentare
Adele
https://github.com/esp8266/arduino-esp8266fs-plugin/releases/download/0.5.0/ESP8266FS-0.5.0.zip
löst das SPIFFS Error: esptool not found! – Problem
Bernd Albrecht
@ Tom: Bitte der Anleitung folgen, die Max dankenswerterweise am 30. März hier “geposted” hat.
(Ein Bild mit den Einstellungen habe ich per Email gesendet.)
@ all: Einer unserer Blogger wird das Thema, die Fragen und Anregungen erneut aufgreifen.
Zieldatum für Veröffentlichung Mitte Juli 2020
Tom
Hallo Zusammen,
Funktioniert das Flashen von SPIFFS beim “D1 Mini NodeMcu mit ESP8266-12F WLAN Modul für Arduino” nicht.
Ich habe das nun genau nach Anleitung gemacht und bleibe leider bei genau dieser Meldung “SPIFFS Upload failed!” hängen. Den D1 Mini muss man ja nicht extra in den Programmiermodus bringen soweit mir das bekannt ist, oder? Auf jeden Fall finde ich keine Lösung um den Fehler zu beseitigen. Im Anschluss habe ich den gesamten LOG aus dem Arduino IDE kopiert. Vielleicht hat jemand noch eine Idee woran es liegen könnte.
-—————————————————————————————————————————————-
esptool.py v2.8
Serial port COM3
Connecting….
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: ec:fa:bc:59:3f:98
Uploading stub…
Running stub…
Stub running…
Changing baud rate to 460800
Changed.
Configuring flash size…
Auto-detected Flash size: 4MB
Compressed 259824 bytes to 190276…
Writing at 0×00000000... (8 %)
Writing at 0×00004000... (16 %)
Writing at 0×00008000... (25 %)
Writing at 0×0000c000… (33 %)
Writing at 0×00010000... (41 %)
Writing at 0×00014000... (50 %)
Writing at 0×00018000... (58 %)
Writing at 0×0001c000… (66 %)
Writing at 0×00020000... (75 %)
Writing at 0×00024000... (83 %)
Writing at 0×00028000... (91 %)
Writing at 0×0002c000… (100 %)
Wrote 259824 bytes (190276 compressed) at 0×00000000 in 4.3 seconds (effective 482.7 kbit/s)…
Hash of data verified.
Leaving…
Hard resetting via RTS pin…
[SPIFFS] data : C:\Users\Thomas Schmid\Documents\Arduino\D1-Mini-WebserverV4b\data
[SPIFFS] size : 2024
[SPIFFS] page : 256
[SPIFFS] block : 8192
/Test.txt
[SPIFFS] upload : C:\Users\THOMAS~1\AppData\Local\Temp\arduino_build_524988/D1-Mini-WebserverV4b.spiffs.bin
[SPIFFS] address : 0×200000
[SPIFFS] reset : —before default_reset —after hard_reset
[SPIFFS] port : COM3
[SPIFFS] speed : 921600
[SPIFFS] python : python.exe
[SPIFFS] uploader : C:\Users\Thomas Schmid\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.6.3\tools\upload.py
SPIFFS Upload failed!
Danke im Voraus für Eure Hilfe
Gruß Tom
steve
Hallo,
danke für die sehr guten Anleitungen.
Aber wie könnte man als nächstes die entstandene SPIFFS-Datei “test.txt” per SFTP zu aaaaa.bplaced.net (user: bbbbb; passwort: ccccc) hochladen. Beim Raspi funktionierte es mit curl…. oder ncftp…. .
steve
Max
Wer Probleme mit SPIFFS Error: esptool not found! hat tauscht sein ESP8266FS aus.
ESP8266FS-0.5.0.zip
https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html#uploading-files-to-file-system
Peter
Hallo, sehr schönes Tool, beim Kopieren des Codes zeigten sich aber doch viele Tipp-Fehler. Nach Korrektur der (meisten) Fehler sieht es so aus:
/*
Diese Skizze testet, ob die EEPROM-Einstellungen der IDE mit der Hardware übereinstimmenESP8266 CheckFlashConfig von Markus Sattler
*/
void setup (void)
{
Serial.begin(115200);
}
void loop ()
uint32_t realSize = ESP.getFlashChipRealSize(); uint32_t ideSize = ESP.getFlashChipSize(); FlashMode_t ideMode = ESP.getFlashChipMode(); Serial.printf (“Flash-Real-ID:% 08X \n”, ESP.getFlashChipId ()); Serial.printf (“Flash-Realgröße:% u Bytes \n \n”, realSize); Serial.printf (“Flash-Ide-Größe:% u Bytes \n”, ideSize); Serial.printf (“Flash-Ide-Geschwindigkeit:% u Hz \n”, ESP.getFlashChipSpeed()); Serial.printf (“Flash-Ide-Modus:% s \n”, (ideMode == FM_QIO? “QIO”: ideMode == FM_QOUT? “QOUT”: ideMode == FM_DIO? “DIO”: ideMode == FM_DOUT? "DOUT " : “UNBEKANNT”)); if (ideSize != realSize) { Serial.println (“Flash-Chip-Konfiguration falsch! \ N”); } else { Serial.println (“Flash Chip Konfiguration ok. \ N”); } delay(5000);{
}
O.Wenzel
“Soweit so gut, funktioniert das.
Nur wie kann ich die Datei jetzt wieder Zeilenweise auslesen?
Bzw. wie kann ich den Inhalt der Datei wieder in Variablen einlesen?”
*************************
das würde mich auch brennend interessieren, alle Versuche mit array’s , f.seek(3, fs::SeekEnd); etc. führen zu keinem Ergebnis !
Äd Franzis
Lieben Dank, für die Info.
Mal eine Frage: Kann man nur Text-Dateien speichern (also Type char) oder lassen sich auch Messwerte direkt als Integer ablegen. Char ist halt sehr Daten-hungrig.
Ich konnte leider kein entsprechendes Beispiel finden.
/Äd
Matthias
Hallo,
die Fehlermeldung:“SPIFFS Error: esptool” lässt einen Fehler mit dem Setup vermuten und hat nichts mit dem hier zur Verfügung gestellten Code und der Erklärung der Funktionsweise zu tun (danke dafür).
Gruß Matthias
Detlef
vom September 20, 2019
Hallo,
gibt es denn jetzt eine Lösung für den Fehler
SPIFFS Error: esptool not found!
Ich habe das gleiche Problem aber noch keine Lösung gefunden.
wo ist die Lösung ????
Klaus
Hallo,
gibt es denn jetzt eine Lösung für den Fehler
SPIFFS Error: esptool not found!
Ich habe das gleiche Problem aber noch keine Lösung gefunden.
Danke.
Andreas Engelmann
Hallo Herr Neumann,
Danke für den Beitrag. Das Thema Flash wird bei den meisten Tutorials garnicht behandelt. Auch die Informationen zur Flashgrösse gehen meist unter.
Grade für HTML-Seiten für einen Server auf dem ESP32/8266 ist das prima.
Lieber Torsten, ich habe neulich ein schönes Zitat bei " Microkontroller.net "gelesen:
“Wer schnelle Lösungen sucht sollte nicht programmieren”.
Jedes Proggramm ist eine Herausforderung . Nim sie an und finde die Lösung.
Dann kannst du sagen: “Das habe ich programmiert”.
Viel Spaß beim Basteln.
Andreas
Torsten
Wie üblich funktioniert der ganze Kram nur nach tausenden Suchen….
Ich bekomme immer wieder: SPIFFS Error: esptool not found!
Ist und bleibt schlicht Bastelkram,
Christian
Hallo!
Soweit so gut, funktioniert das.
Nur wie kann ich die Datei jetzt wieder Zeilenweise auslesen?
Bzw. wie kann ich den Inhalt der Datei wieder in Variablen einlesen?
Danke