SPIFFS - Fragen und Antworten - [Teil 1] - AZ-Delivery

Teil 1

Zwei unserer älteren Blogbeiträge behandeln das Thema SPIFFS auf dem ESP8266. An dieser Stelle möchte ich auf die Nutzerkommentare eingehen und Fragen beantworten. Details zur Verwendung des Flashspeichers und des Dateisystems finden Sie hier von Albert Vu und hier von Tobias Kuch.
Ich werde versuchen, die Fehler der Nutzer zu reproduzieren und Lösungen zu finden. Gleichzeitig werde ich Beispiele zeigen und testen. Los geht's.

SPIFFS Error: esptool not found!

Diese Fehlermeldung erhielten einige unserer Nutzer und auch ganz allgemein scheint das ein Problem zu sein. Ich habe also kurzerhand folgendes gemacht und hatte diesen Fehler nicht:

Ich habe einen D1 Mini NodeMCU mit ESP8266-12F aus dem AZ-Delivery Shop an den Computer angeschlossen. Diesen habe ich gewählt, weil ein Leser damit Probleme hatte. Dann bin ich dem Link aus den Kommentaren von dem Leser Max gefolgt und bin die Anleitung Schritt für Schritt durchgegangen, wie sie dort zu finden ist. Ich übernehme diese Anleitung und übersetze sie hier:

1. Download Arduino-ESP8266FS-PlugIns

Download des Arduino-ESP8266FS-PlugIns von hier. Dies ist die neuere Version 0.5.0, bei der der Fehler nicht auftreten soll.

2. Ordner tools anlegen

In den Voreinstellungen der Arduino IDE findet man den Sketchbook-Speicherort. Diesen Ordner muss man mit einem Dateibrowser aufsuchen und dort den Ordner "tools" erstellen, wenn er noch nicht existiert.

3. ESP8266FS-0.5.0.zip entpacken

Dort hinein entpackt man den Inhalt der aus Punkt 1 heruntergeladenen ZIP-Datei. In dieser gepackten Datei befindet sich die esp8266fs.jar. Bei mir sieht die Ordnerstruktur nun so aus:

...\Arduino\Sketchbooks\tools\ESP8266FS\tool\

und darin die besagte JAR-Datei.

Gibt es diese Datei bereits, sollte sie überschrieben oder vorher gelöscht werden.

4.Arduino IDE neu starten

5.Einen neuen Sketch anlegen

Entweder man nutzt ein bereits existierendes Arduino-Programm und öffnet es, oder man erstellt einen neuen Sketch.

6.Sketch-Ordner öffnen

In der Arduino IDE betätigt man die Tastenkombination STRG+K oder öffnet in der Menüleiste den Punkt Sketch. Dort wählt man anschließend "Sketch-Ordner anzeigen" aus. Es öffnet sich ein Dateibrowserfenster.

7.data-Ordner erstellen

Im Fenster sieht man die .INO Programmdatei. Hier erstellt man nun einen neuen Ordner mit der Bezeichnung "data". In diesen Ordner können Sie Dateien legen, auf die sie in ihrem Arduino-Programm im laufenden Betrieb zugreifen möchten. Zum Testen eignet sich eine Textdatei mit Namen test.txt. Dort hinein habe ich drei Zahlenwerte verteilt auf drei Zeilen geschrieben. Der Ordner sieht nun so aus:

SPIFFSTest\SPIFFS\SPIFFS.ino
SPIFFSTest\SPIFFS\data

SPIFFS_Test\SPIFFS\data\test.txt

SPIFFS_Test ist mein Überordner. Dort hinein habe ich mein Programm SPIFFS gespeichert. Er enthält die SPIFFS.ino und den Ordner data. Im Ordner data liegt die Datei test.txt.

8.Board auswählen

Im Menü Werkzeuge habe ich als Board (wie im folgenden Bild zu sehen) NodeMCU 1.0 (ESP-12E Module) gewählt. Die Speichergröße "Flash Size" habe ich mit 1M (von 4M) für SPIFFS angegeben. Der Port wird bei Ihnen anders lauten. Bei mir ist es COM10.


9.Bootloader-Modus aktivieren

Für einige Boards ist es notwendig, einen Taster zu betätigen, damit der Bootloader-Modus aktiviert wird. Bei dem von mir verwendeten D1 Mini ist das nicht notwendig.

10.ESP8266 Sketch Data Upload

Wichtig: Seriellen Monitor schließen, falls geöffnet.
Das könnte die Frage von dem Leser Tom beantworten, warum der Upload fehlschlägt.

Auf dem vorherigen Bild sieht man im Menü Werkzeuge den Punkt "ESP8266 Sketch Data Upload". Wird er betätigt, startet der Upload des Dateisystems inklusive des Inhalts des Ordners data, den wir zuvor angelegt haben.

Nach dem Upload sieht das wie im folgenden Bild aus:

Testprogramm

Wie man sieht, habe ich keine Fehlermeldung erhalten. Die Textdatei müsste nun im Flashspeicher des D1 Mini liegen. Um das herauszufinden, nutze ich den Quellcode von Albert Vu:

#include "FS.h" // Hier binden wir die benötigte Bibliothek ein

void setup() {
  Serial.begin(115200); // 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() {
}

Ich habe lediglich die Baudrate für den Seriellen Monitor geändert.

Ich kompiliere und lade das Programm auf den Mikrocontroller. Mir fällt an dieser Stelle auf, dass sich meine Firewall meldet. Das passiert nicht mit einem Arduino Uno oder Nano. Wenn also etwas nicht funktioniert, könnte das eine Fehlerquelle sein. Ich erlaube den Zugriff und der Upload startet.

Über das Menü Werkzeuge oder der Tastenkombination STRG+UMSCH+M starte ich den Seriellen Monitor. Dort passiert erst mal nichts. Ich resette das Board über den Taster.

Ich erhalte dann folgende Ausgabe:


Die Zahlen 12, 22 und 44 werden aus der test.txt ausgelesen. Es werden noch kryptische Zeichen dargestellt, die allerdings vor der Ausgabe erscheinen. Sie sollten also nicht direkt mit dem Inhalt der Datei zu tun haben. Das kann ich mir später noch ansehen. Der Dateiinhalt wird jedenfalls ausgelesen und angezeigt.

Check Flash Config

Der Leser Peter hat in einem Kommentar darauf hingewiesen, dass im Quellcode des extern verlinkten Check Flash Config Programms Tippfehler enthalten sind. Er hat sich auch freundlicherweise die Mühe gemacht und korrigierten Code in seinem Kommentar hinterlassen. Das möchte ich mir auch genauer ansehen, für diejenigen, die das auch interessiert. Die Frage, wie groß der Flash Speicher meines D1 Mini überhaupt ist, hat mich außerdem auch sehr interessiert.

Albert Vu hat in seinem Beitrag auf den Quelltext von Markus Sattler verwiesen. Der sieht folgendermaßen aus: 

/*
  ESP8266 CheckFlashConfig by Markus Sattler

  This sketch tests if the EEPROM settings of the IDE match to the Hardware

*/

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 real size: %u bytes\n\n", realSize);

  Serial.printf("Flash ide  size: %u bytes\n", ideSize);
  Serial.printf("Flash ide speed: %u Hz\n", ESP.getFlashChipSpeed());
  Serial.printf("Flash ide mode:  %s\n", (ideMode == FM_QIO ? "QIO" : ideMode == FM_QOUT ? "QOUT" : ideMode == FM_DIO ? "DIO" : ideMode == FM_DOUT ? "DOUT" : "UNKNOWN"));

  if (ideSize != realSize) {
    Serial.println("Flash Chip configuration wrong!\n");
  } else {
    Serial.println("Flash Chip configuration ok.\n");
  }

  delay(5000);
}

Er wird problemlos kompiliert und auch hochgeladen. Wenn das Programm ausgeführt wird, erscheint folgende Ausgabe im Seriellen Monitor:


Die Größe sind also
4194304 Bytes, was umgerechnet exakt 4 MB sind. Nun möchte ich mir den korrigierten Quelltext von dem Nutzer Peter ansehen (danke dafür an dieser Stelle):

/*
  ESP8266 CheckFlashConfig von Markus Sattler (geaendert von Peter)
  Diese Skizze testet, ob die EEPROM-Einstellungen der IDE mit der Hardware übereinstimmen

*/

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);
}

Ich habe den Quellcode direkt aus dem Kommentar entnommen. Dabei fällt auf, dass Anführungszeichen nicht korrekt kopiert werden. Mit Suchen und Ersetzen kann man das schnell austauschen. Man erhält sonst einen Fehler /342. Einrückungen werden im Kommentar nicht berücksichtigt. Das habe ich schnell selbst geändert.

Wenn ich das Programm kompiliere, werden mir noch Warnings angezeigt. Was nicht funktioniert, ist
\ N. Escape Sequenzen wie z.B. der für den Zeilenumbruch muss \n lauten. Das ändere ich ab. Kompiliere ich erneut, gibt es keine Warnings und in der Ausgabe auf dem Seriellen Monitor wird mir folgendes angezeigt:


Ich konnte konkret keine Tippfehler finden. Die Texte der Bildschirmausgabe waren vorher in englischer Sprache. Peter hat sie für uns übersetzt.

Was würde ich hier noch anders machen?

Markus Sattler hat alles in die Hauptschleife geschrieben. Ich denke, dass es nicht nötig ist, die Ausgabe zu wiederholen. Also würde ich alles in eine separate Funktion schreiben und diese im setup() einmal aufrufen. In jedem Schleifendurchlauf werden die drei Variablen realSize, ideSize und ideMode immer wieder neu deklariert. Das würde ich vermeiden und sie global deklarieren. In C oder C++ versucht man, globale Variablen in der Regel auch zu vermeiden.

Schreiben wir alles in eine separate Funktion, sind es ab dann lokale Variablen. Dann hat der ursprüngliche Autor des Programms formatierte Ausgaben verwendet, wie man sie in C benutzt. Das ist legitim, allerdings nutzt er Kontrollstrukturen in Kurzschreibweise als Argumente. Das liest sich etwas umständlich, auch wenn der Quellcode kürzer ist.

Die ESP-Funktionen und deren Beschreibung findet man übrigens hier. Sie gehören zum ESP8266 core. Den kann man hinzuladen, indem man in den Voreinstellungen der Arduino IDE in der Zeile "Zusätzliche Boardverwalter-URLs:" folgendes einträgt:

http://arduino.esp8266.com/stable/packageesp8266comindex.json

Dann kann man über das Menü Werkzeuge -> Board -> Boardverwalter nach esp8266 suchen und sollte esp8266 by ESP8266 Community finden und installieren können.

Mein geänderter Quellcode sieht nun so aus:

/*
  ESP8266 CheckFlashConfig by Markus Sattler (geaendert von Andreas Wolter)
  This sketch tests if the EEPROM settings of the IDE match to the Hardware
*/

void configInfo() {
  uint32_t realSize = ESP.getFlashChipRealSize();
  uint32_t ideSize = ESP.getFlashChipSize();
  FlashMode_t ideMode = ESP.getFlashChipMode();
  
  Serial.println("ESP8266 CheckFlashConfig by Markus Sattler");
  Serial.println("Remix by Andreas Wolter\n");
  Serial.printf("Flash real id:   %08X\n", ESP.getFlashChipId());
  Serial.printf("Flash real size: %u bytes\n\n", realSize);

  Serial.printf("Flash ide size:  %u bytes\n", ideSize);
  Serial.printf("Flash ide speed: %u Hz\n", ESP.getFlashChipSpeed());
  Serial.printf("Flash ide mode:  ");
  if (ideMode == FM_QIO)
    Serial.println("QIO");
  else if(ideMode == FM_QOUT)
    Serial.println("QOUT");
  else if(ideMode == FM_DIO)
    Serial.println("DIO");
  else if(ideMode == FM_DOUT)
    Serial.println("DOUT");
  else
    Serial.println("UNKNOWN");

  if (ideSize != realSize) {
    Serial.println("Flash Chip configuration wrong!\n");
  } else {
    Serial.println("Flash Chip configuration ok.\n");
  }
}

void setup(void) {
  Serial.begin(115200);
  configInfo();
}

void loop() {}

Ich habe als erste Ausgabe println statt printf benutzt. Dadurch verschwinden die kryptischen Zeichen in der Ausgabe. Die Kontrollstruktur für den ide mode habe ich aus den Argumenten der Ausgabe entfernt. Es war nicht falsch. Ich habe es nur für die bessere Lesbarkeit geändert.

Für manche Werte wurden Variablen verwendet, für manche nicht. Man spart sich die erneuten Funktionsaufrufe, wenn man Werte in Variablen schreibt. Das spart in der Regel Rechenzeit. Die Ausgabe des Programms sieht nun folgendermaßen aus:

Zeilenweise Text auslesen

Die Leser Christian und O.Wenzel möchten wissen, wie man nun Text aus der Textdatei zeilenweise ausliest. Wenn ich das Beispielprogramm von Albert Vu betrachte, mit dem wir den Inhalt der Textdatei ausgelesen haben, wird dort alles in einen String geschrieben. Auch die Zeilenumbrüche. Anschließend wird der komplette Inhalt der String-Variablen in einem Rutsch ausgegeben.

Um die Zeilen einzeln zu erhalten, kommt man nicht drum herum, den Inhalt zu zerlegen. Für den Fall, dass in der Textdatei viele Informationen stehen, würde ich nicht alles in eine Variable lesen, sondern mit Delimitern arbeiten. Das sind festgelegte Zeichen, die Abschnitte in Texten eingrenzen. Codestrukturen wie HTML oder XML bieten solche Zeichen. Wir könnten Text auch zeichenweise auslesen, bis ein "\n" erreicht wird, also ein Zeilenumbruch.

Diese Escape Sequenz ist nicht sichtbar. Sie ist aber da. In meinem Test deutlich zu sehen, da die Zahlen untereinander ausgegeben wurden. Genau wie ich sie in die test.txt eingetragen habe. Speichern wir also Werte eines Sensors oder Zeitangaben zeilenweise in eine Textdatei, dann können wir das auch wieder zeilenweise auslesen. Der Funktionsaufruf für das Auslesen einer Zeichenkette bis zu einem bestimmten Zeichen ist readStringUntil(). Ich ändere das ursprüngliche Testprogramm folgendermaßen:

#include "FS.h" // Hier binden wir die benötigte Bibliothek ein

void readLines(File f) {
  String data;
  unsigned int zeilenZaehler = 0;
  
  Serial.println("Inhalt der geöffneten Datei:");
  while(f.available()) {
    data = f.readStringUntil('\n'); // lesen bis Zeilenumbruch...
    Serial.print("Zeile ");
    Serial.print(zeilenZaehler);
    Serial.print(": ");
    Serial.println(data);           // ... und wieder ausgegeben
    zeilenZaehler++;
  } 
}

void setup() {
  Serial.begin(115200);
  SPIFFS.begin();                           // Filesystem mounten
  File f = SPIFFS.open( "/test.txt", "r");  // Datei zum Lesen öffnen
  if (!f) {
    Serial.println("file open failed!");
  }
  else {
    readLines(f);       // Funktion fuer das Zeilenweise Auslesen
    f.close();          // Datei schliessen
  }
  SPIFFS.end();         // Filesystem unmounten
}

void loop() {}

Im setup() wird das zeilenweise Einlesen nur ausgeführt, wenn die Datei geöffnet werden konnte. Das Dateisystem wird hier auch "unmounted", wenn der Vorgang abgeschlossen wurde. Das Lesen des Textes habe ich in eine Funktion ausgelagert. Ihr wird der File Pointer auf die Datei übergeben. In der Funktion wird eine Schleife ausgeführt. Es wird eine Zeichenkette gelesen, die mit einem Zeilenumbruch endet. Danach die nächste und immer so weiter.

Die Schleife läuft so lange, wie Bytes zur Verfügung stehen. Ich habe noch einen Zähler eingefügt, der die Zeilennummern mit zählt. Das dient in diesem Fall nur der Ausgabe auf dem Bildschirm. Wenn ich das Programm auf den D1 Mini hochlade, erhalte ich folgende Ausgabe auf dem Seriellen Monitor:


Der Inhalt wurde zeilenweise in Textform ausgelesen.

Text in Ganzzahlen wandeln

Der Leser Äd Franzis fragte, ob man nun die Messwerte wieder als Integer auslesen kann, da char datenhungriger ist als int. Zuerst schauen wir mal, ob der Character-Datentyp tatsächlich datenhungriger ist, wie er vermutet. Ein char ist in der Regel ein Byte groß. Also 8 Bit. Ein Integer auf dem Arduino ist 4 Byte groß, also 32 Bit.

Diese Information erhält man mit dem Aufruf
sizeof(int) bzw. sizeof(char). Also ist theoretisch ein Integer wesentlich datenhungriger, als ein char. Da man normalerweise aber mit mehrziffrigen Zahlen arbeitet, setzt sich z.B. die Zahl 1234 auch aus vier Bytes vom Typ char zusammen. Die Zahl 1234 als Integer ist ebenfalls 4 Byte groß. Das gleicht sich also aus. Anders wird es nun, wenn die Zahl größer wird.

Eine Vorzeichen-behaftete Ganzzahl kann den Wert 2.147.483.647 einnehmen. Also 10 Ziffern (vorzeichenlos sind es genauso viele Ziffern). Es bleiben aber 4 Bytes. 10 chars wären 10 Bytes und übertreffen damit das int um mehr als das Doppelte. Somit ist in diesem Fall das char tatsächlich datenhungriger als das int.

Der Inhalt von Textdateien kann auf zwei Arten ausgelesen werden. Binär und als Text. Reine Integer kann man so nicht speichern. Aber man kann sie auslesen und wieder umwandeln. Man liest einen String aus, der die Ziffern enthält, und wandelt ihn dann um in eine Zahl. Dafür muss man wissen, wo die Zahl beginnt und wo sie endet.

Im obigen Beispiel haben wir das mit der Escape Sequenz "\n" gemacht. In dem Programm wird bereits jede Zahl zusammenhängend als String eingelesen. Man kann nun auch Trennzeichen nutzen. Schreibt man eine Rechenaufgabe in die Textdatei, z.B.
4+4*8/2, dann kann man die Operanden als Trennzeichen, sogenannten Delimiter, verwenden. In XML-Dateien könnte man sich eigene Felder definieren:

<zahl1>1234</zahl1>
<zahl2>5678</zahl2>

Man kann dann zeichenweise durch den Text parsen und immer nach dem > und bis zum < einlesen. Ähnlich geht das auch in HTML.

Wie wandeln wir nun den String in eine Ganzzahl? In der Arduino IDE gibt es dafür die Stringobjekt-Funktion toInt(). Sie untersucht den String auf Ziffern und gibt dann eine Zahl vom Typ long zurück, wenn das erste Zeichen eine Ziffer ist. Ich habe meinem Quellcode einige Zeilen hinzugefügt:

#include "FS.h" // Hier binden wir die benötigte Bibliothek ein

void readLines(File f) {
  String data;
  unsigned int zeilenZaehler = 0;
  long zahlen[3];
  
  Serial.println("Inhalt der geöffneten Datei:");
  while(f.available()) {
    data = f.readStringUntil('\n'); // lesen bis Zeilenumbruch...
    Serial.print("Zeile ");
    Serial.print(zeilenZaehler);
    Serial.print(": ");
    Serial.println(data);           // ... und wieder ausgegeben
    zahlen[zeilenZaehler] = data.toInt();  // Zeichenkette in Zahl wandeln
    zeilenZaehler++;
  }
  Serial.print("Addition aus allen Zahlen: ");
  Serial.println(zahlen[0]+zahlen[1]+zahlen[2]);
}

void setup() {
  Serial.begin(115200);
  SPIFFS.begin();                           // Filesystem mounten
  File f = SPIFFS.open( "/test.txt", "r");  // Datei zum Lesen öffnen
  if (!f) {
    Serial.println("file open failed!");
  }
  else {
    readLines(f);       // Funktion fuer das Zeilenweise Auslesen
    f.close();          // Datei schliessen
  }
  SPIFFS.end();         // Filesystem unmounten
}

void loop() {}

Ich habe ein Array deklariert, in das ich die drei Zahlen aus der Textdatei schreiben kann. Der Zeilenzähler eignet sich nun wunderbar, um über das Array zu iterieren und die Zahlen dort nacheinander hineinzuspeichern.

Die Funktion
toInt() wird mit einem Punkt an die Stringvariable geschrieben, da es eine Objektfunktion ist. Am Ende addiere ich alle Zahlen. Das geht nur, da es sich jetzt tatsächlich um Zahlen handelt. Die Ausgabe auf dem Seriellen Monitor sieht dann so aus:


Was wäre, wenn wir nun negative, also vorzeichenbehaftete, Zahlen in der Textdatei stehen hätten? Gehen wir davon aus, dass weiterhin nur eine Zahl in jeder Zeile stünde. Wir bekämen z.B. einen String, der die Zeichenkette "-22" enthielte.

Wir müssten also prüfen, ob das erste Zeichen ein "-" ist. Das kann man mit der Stringobjekt-Funktion
startsWith() umsetzen. Der Quellcode wird ergänzt durch eine Abfrage nach dem ersten Zeichen. Ist das ein Minus, wird es zuerst aus dem String entfernt. Dafür nutze ich die Stringobjekt-Funktion substring(). Anschließend wird die Zahl gewandelt und in das Array geschrieben. Nun muss man aus der positiven Zahl eine negative machen. Dafür multipliziere ich einfach mit -1. Der Quellcode sieht nun wie folgt aus:

#include "FS.h" // Hier binden wir die benötigte Bibliothek ein

void readLines(File f) {
  String data;
  unsigned int zeilenZaehler = 0;
  long zahlen[3];
  
  Serial.println("Inhalt der geöffneten Datei:");
  while(f.available()) {
    data = f.readStringUntil('\n'); // lesen bis Zeilenumbruch...
    Serial.print("Zeile ");
    Serial.print(zeilenZaehler);
    Serial.print(": ");
    Serial.println(data);           // ... und wieder ausgegeben
    if(data.startsWith("-", 0)) {
      data = data.substring(1);              // Minus entfernen
      zahlen[zeilenZaehler] = data.toInt();  // Zeichenkette in Zahl wandeln
      zahlen[zeilenZaehler] = zahlen[zeilenZaehler] * -1; // Zahl wird negativ
    }
    else {
      zahlen[zeilenZaehler] = data.toInt();  // Zeichenkette in Zahl wandeln
    }
    zeilenZaehler++;
    data = "";
  }
  Serial.print("Addition aus allen Zahlen: ");
  Serial.println(zahlen[0]+zahlen[1]+zahlen[2]);
}

void setup() {
  Serial.begin(115200);
  delay(1000);
  SPIFFS.begin();                           // Filesystem mounten
  File f = SPIFFS.open( "/test.txt", "r");  // Datei zum Lesen öffnen
  if (!f) {
    Serial.println("file open failed!");
  }
  else {
    readLines(f);       // Funktion fuer das Zeilenweise Auslesen
    f.close();          // Datei schliessen
  }
  SPIFFS.end();         // Filesystem unmounten
}

void loop() {}

Wenn die Zahl nicht negativ ist, dann wird sie genau wie vorher einfach gewandelt. Ich ändere meine Textdatei und lade sie auf den D1 Mini (dabei daran denken, dass der Serielle Monitor geschlossen werden muss, sonst erscheint eine Fehlermeldung). Wenn ich das Programm ausführe, bekomme ich folgende Ausgabe:


Für den Fall, dass man Gleitkommazahlen eines Sensors gespeichert hat, kann man diese Werte mit der Stringobjekt-Funktion toFloat() umwandeln. Natürlich sollte dann die Variable vom Datentyp float sein und der String muss einen Punkt enthalten. Das erste Zeichen muss eine Ziffer sein. Ich schreibe dazu kein Beispiel, da es identisch zu toInt() funktioniert. Eine Übersicht zu den Stringobjekt-Funktionen findet man in der Arduino Reference.

Das war es bis hierher für den ersten Teil. Auf eine Frage bin ich noch nicht eingegangen. Diese zu beantworten, ist etwas schwieriger. Es geht dabei um den Upload aus dem Flash-Speicher auf einen SFTP-Server.
Ob ich eine Lösung dafür finden konnte, erfahren Sie im nächsten Teil.
Bis dahin.

Andreas Wolter

für AZ-Delivery Blog

Grundlagen software

2 Kommentare

Andreas Wolter

Andreas Wolter

Hallo Herr Wemheuer,

ich hätte in dem Beitrag erwähnen sollen, dass ich darauf im zweiten Teil der Reihe eingehe. Im ersten Teil wollte ich nur versuchen nachzuvollziehen, was die Leser für Probleme hatten und ob ich sie lösen kann. Aber Sie haben natürlich recht. Danke für den Hinweis an dieser Stelle.

Grüße,
Andreas Wolter

Jürgen Wemheuer

Jürgen Wemheuer

Hallo, Andreas Wolter,
laut Dokumentation der Boardverwalter-Community steht das SPIFFS-Dateisystem auf der “Abschussliste”: “SPIFFS is currently deprecated and may be removed in future releases of the core. Please consider moving your code to LittleFS.” Darauf sollte man vielleicht noch hinweisen…
(Quelle: https://arduino-esp8266.readthedocs.io/en/2.7.2/filesystem.html)
Ist aber nicht so schlimm, denn im Prinzip funktioniert LittleFS genauso wie SPIFFS, es soll etwas schneller sein, braucht je Datei allerdings einen Overhead von 4kByte statt 256 Byte wie beim SPIFFS.

Kommentar hinterlassen

Alle Kommentare werden von einem Moderator vor der Veröffentlichung überprüft

Empfohlene Blogbeiträge

  1. ESP32 jetzt über den Boardverwalter installieren - AZ-Delivery
  2. Internet-Radio mit dem ESP32 - UPDATE - AZ-Delivery
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1 - AZ-Delivery
  4. ESP32 - das Multitalent - AZ-Delivery