Flash geheugen

Modules met een ESP8266 of ESP32 processor, zoals de nodeMCU en de WeMos/LoLin D1 mini hebben vaak veel intern flash geheugen, bijvoorbeeld 4MB. In een geheugen van 4MB kun je de informatie van ruim 1000 pagina's A4 tekst opslaan, bij 16 MB wordt dat ongeveer 5000 pagina's A4. Je kunt er echter betrekkelijk weinig kleurenplaatjes in opslaan. Je kunt er wel honderden niet al te grote zwart-wit plaatjes in opslaan.
Flash-geheugen kan niet worden gebruikt als programmageheugen. Dus als je programma te groot wordt dan kun je dat niet oplossen met flash. Wel kun je tekst e.d. opslaan in het flash geheugen. Overigens hebben ESP8266 en ESP32 processoren vaak ook veel meer werkgeheugen beschikbaar voor programma's dan een Arduino Uno, waardoor je minder snel tegen de grenzen oploopt.
Als je veel kleurenplaatjes wilt opslaan dan is het beter een micro SD kaartlezer aan te sluiten. Je hebt dan vele GB tot je beschikking en je kunt gemakkelijk bestanden uploaden. Zie hier voor een beschrijving hoe dit werkt .

Waarschuwing: het in het vervolg beschreven SPIFFS bestandssysteem heeft enkele nadelen en zal daarom mogelijk in latere versies van de Arduino niet meer ondersteund worden. Het wordt vervangen door LittleFS. Voor de gebruiker werkt LittleFS ongeveer hetzelfde als SPIFFS, maar het is een ander, veiliger bestandssysteem (bijvoorbeeld als de spanning uitvalt tijdens het wegschrijven). Ik zal te zijner tijd de onderstaande tekst aanpassen.

Verschil SPIFFS en LittleFS

De belangrijkste verschillen voor de gebruiker zijn:

Data uploaden naar de ESP8266 of ESP32

Hier gaat het om het uploaden van veel gegevens tegelijkertijd, vanaf een lokale schijf naar het flash geheugen. Dit doe je vanuit de IDE (je gebruikt er geen sketch voor - erg handig!).
Hoe je gegevens via een Arduino sketch in flash opslaat is beschreven op de Arduino-uitvoeringen pagina.

Data uploaden naar de ESP8266 (SPIFFS bestandssysteem)

Voorbereiden van de Arduino IDE

Ik ga ervan uit dat je de esp borden al hebt geïnstallleerd (zie bij Arduino-uitvoeringen).
Dan kun je nu de plug-in installeren. Ga naar https://github.com/esp8266/arduino-esp8266fs-plugin.
Daar staat alle benodigde informatie over hoe je moet installeren. Ik beschrijf het ook, maar op zeker moment kunnen mijn instructies verouderd zijn. Ergens in het bestand Readme.md staat een link naar releases. Klik op die link en download het bestand ESP8266FS-0.5.0.zip of een hogere versie als die er is.
Pak het bestand uit naar de map waarin de Arduino software is geïnstalleerd in de map tools. Bij mijn Windows computer is dat C:\Program Files (x86)\Arduino\tools. Als de map tools niet bestaat kun je die zelf aanmaken. Als je de Arduino opnieuw opstart, dan zou er nu een menu optie "ESP8266 Data Upload" bij moeten zijn gekomen. Zo niet, kijk dan alles nog eens goed na.

Links: zo ziet het nieuwe menu-item eruit (groene pijl); rechts: zo vind je gemakkelijk de actieve map.

Om bestanden te kunnen uploaden moet het volgende kloppen:
  1. De bestanden moeten zich bevinden in een map met de naam data. Die map moet zich bevinden in de map van het programma dat in de Arduino IDE actief is. In de Arduino IDE kun je die map gemakkelijk vinden via menu Schets→Schetsmap weergeven (zie de beeldschermafdruk hierboven).
  2. De seriële monitor (of plotter) moet uit staan.
  3. Het juiste bord moet geselecteerd zijn.
  4. De juiste poort moet zijn gekozen.
  5. Je moet genoeg geheugen beschikbaar hebben. Je kan ook een deel van het flash geheugen gebruiken (zie bij de rode pijl: ik heb voor 2 MB gekozen).
Je moet nog opgeven alleen de sketch te wissen bij uploaden van het programma.
De bestanden blijven nu in het flash geheugen staan tot er opnieuw iets wordt geüpload. Omdat flash geheugen slijt bij het overschrijven van gegevens is het jammer dat je op deze manier geen incrementele uploads kunt doen. Aan de andere kant is modern flash geheugen heel vaak opnieuw te beschrijven voor het stuk gaat. Bij het lezen van het flash geheugen speelt dit niet, dat kan zo vaak je maar wilt.

Hoe werkt het nu?

Als je op de menuoptie klikt dan zoekt de IDE bij de actieve sketch naar de map met de naam data. Alles wat daarin staat wordt gekopieerd naar het flash geheugen, zolang er genoeg geheugen vrij is. Als het geheugen vol raakt dan krijg je een melding en wat reeds geüpload is blijft erin staan.
Dit systeem is erg handig. Er zijn twee voor de hand liggende manieren om hiermee te werken:
  1. Je kunt een dummy sketch maken met een makkelijk te onthouden naam. Een dummy sketch kan een lege sketch zijn met alleen een lege setup() en een lege loop() functie (ook wel BareMinimum genoemd). Sla de sketch op met de gewenste naam en zet in de bijbehorende sketchmap de map data. Je werkt aan je programma en zodra je gegevens naar het flashgeheugen wilt sturen open je tijdelijk het dummy programma. Na uploaden kun je terug naar het programma waarmee je bezig was. Deze methode is handig als je veel versies van hetzelfde programma's maakt met dezelfde data.
  2. Je kunt de map aanmaken onder het programma waarmee je bezig bent, zodat je verschillende mappen kunt uploaden afhankelijk van de toepassing die je hebt. Deze methode is handig als je maar een versie van een prgramma maakt, of als je oudere versies onder een andere naam wegschrijft.

Je ziet beide methodes geïllustreerd in de mappen hiernaast. Ik heb een sketch voor displays met 154 bij 212 pixels en een andere sketch voor displays met 200 bij 200 pixels. De plaatjes die ik wil laten zien zijn verschillend, want ze zijn aangepast aan de grootte van het display. Ik maak dus onder beide sketches een data map aan met daarin de juiste plaatjes. Zodra ik bezig ben met de sketch voor het 200x200 display worden automatisch de juiste plaatjes voor dat display geüpload.

De eerste methode zie je daaronder. Het dummy programma heb ik "UploadPlaatjes" genoemd en dus heet de bijbehorende map ook zo. Onder deze map is een datamap gemaakt met de bestanden die ik in het flash geheugen wil hebben. Als ik nu een Versie4 aanmaak hoef ik geen datamap te maken. Ik blijf gewoon de datamap van UploadPlaatjes gebruiken.

Voorbeeldprogramma

Hieronder laat ik een voorbeeld programma zien. Zet onder de map waarin je je testprogramma hebt opgeslagen een map genaamd data met daarin een paar kleine tekstbestanden. Upload de map naar het flash geheugen. Als alles goed is gegaan kun je het testprogramma uitproberen. Het programma dat de data uploadt neemt de mappenstructuur die je eventueel onder data hebt gemaakt over. De bovenste map (de "root") geef je aan met een backslash. Dus als je zelf een bestand wil lezen uit de root, dan moet je een / voor de bestandsnaam zetten! Het testprogramma laat de bestanden zien met hun inhoud.
// Test voor esp8622 flash geheugen
// Zet niet meer dan een paar korte tekstbestanden in de data map!
#include "FS.h"
void setup() {
  Serial.begin(9600);
  Serial.println();
  if (!SPIFFS.begin()) {
    Serial.println("Kan het bestandssysteem niet openen");
    return;
  }
  leesAlleBestanden();
}

void leesAlleBestanden() {
  Dir dir = SPIFFS.openDir("/");
  while (dir.next()) {
    Serial.print("Bestand: "); Serial.println(dir.fileName());
    File bestand = SPIFFS.open(dir.fileName(), "r");
    while (bestand.available()) {
      String s = bestand.readStringUntil('\n');
      Serial.println(s);
    }
  }
}

void loop() {
}

Data uploaden naar de ESP32 (SPIFFS bestandssysteem)

Je kunt het flash-geheugen op dezelfde manier uploaden als bij de op de ESP8266 gebaseerde modules, maar je moet een nieuwe aanpassing maken. Nu download je ESP32FS-1.0.zip of een nieuwere versie als die bestaat. Pak deze uit op dezelfde plaats als hierboven bij de ESP8266.
Helaas is het zo dat de meeste programma's die het flash geheugen beschrijven of uitlezen anders werken dan bij de ESP8266 modules. Niet erg handig, maar het is niet anders.
Omdat er zoveel verschillende uitvoeringen van bordjes met de ESP32 processor zijn, die allemaal net iets anders zijn kan het nog erg lastig zijn om dit alles aan de praat te krijgen. Belangrijk is dat je het juiste bord selecteert, maar helaas staat dat lang niet altijd goed aangeven op de modules. De software die het flash geheugen beschrijft en leest is voor de ESP32 anders dan voor de ESP8266. Hieronder kun je dat zien in het testprogramma.
Voor de esp32:
// Test voor esp32 flash geheugen
// Zet niet meer dan een paar korte tekstbestanden in de data map!
#include "SPIFFS.h"
void setup() {
  Serial.begin(9600);
  Serial.println();
  if (!SPIFFS.begin(true)) {
    Serial.println("Kan het bestandssysteem niet openen");
    return;
  }
  leesAlleBestanden();
}

void leesAlleBestanden() {
  File root = SPIFFS.open("/");
  File bestand = root.openNextFile();
  while (bestand) {
    Serial.print("Bestand: "); Serial.println(bestand.name());
    while (bestand.available()) {
      String s = bestand.readStringUntil('\n');
      Serial.println(s);
    }
    bestand = root.openNextFile();
  }
}

void loop() {
}