WEMOS D1 MINI PRO ESP8266: flash memory writing problems [SOLVED]

Good evening everyone (it's currently midnight in Italy).
I'm having a problem with the flash memory on my ESP8266-based WEMOS D1 MINI PRO (4MB).
I need to save two usernames and two passwords in the flash memory. To program the WEMOS, I use the Arduino IDE and the ESP_EEPROM.h library.
The program seems to work because after entering the four character strings, the sketch reads the memory locations and displays all the strings (even if doubled).
However, if I reset the WEMOS, upon reboot, there's nothing left in the memory cells; the sketch displays four empty strings. If I upload the sketch to Arduino UNO, it works perfectly.

Thank you all :slight_smile:

I'm attaching the sketch.

#include <ESP_EEPROM.h>

String ssidWifi, passwordWifi, ftpUser, ftpPassword;
//int indirizzo = 0;

void setup()
{
  Serial.begin(74880);
  EEPROM.begin(128);
  leggi_credenzial_su_EEPROM();
}

void loop()
{
  leggi_USB();
  delay(10);
}

void leggi_USB()  //----------- sub che legge i caratteri in arrivo dalla porta USB e ne ricava il comando
{
  if(Serial.available())                // se sulla seriale c'è qualcosa...
    {
      char c = (Serial.read());          // ... acquisisci il carattere
      if (c == 'r' || c == 'R')
        {
          chiedi_user_e_password();
        }
 
    }
}

void chiedi_user_e_password()
{
  cancella_buffer_seriale();
  char c;
  ssidWifi = "";
  passwordWifi = "";
  ftpUser = "";
  ftpPassword = "";
  Serial.println("Digitare la SSID del WiFi");
  do
    {
      delay(10);
    } while(Serial.available() == 0);

  if(Serial.available())                // se sulla seriale c'è qualcosa...
    {
      do
        {
          c = (Serial.read());          // ... acquisisci il carattere
          if (c != '\n' && c != -1)                // se non è il carattere di fine riga...
            {
              ssidWifi += c;           // ... aggiungi il carattere letto alla stringa
            }
        } while(c != '\n');            // rimani nel ciclo fino a che non ricevi il fine riga
    }

  cancella_buffer_seriale();
  Serial.println("Digitare la password del WiFi");

  do
    {
      delay(10);
    }while(Serial.available() == 0);

  do
    {
      c = (Serial.read());          // ... acquisisci il carattere
      if (c != '\n' && c != -1)                // se non è il carattere di fine riga...
        {
          passwordWifi += c;           // ... aggiungi il carattere letto alla stringa
        }
    }while(c != '\n');            // rimani nel ciclo fino a che non ricevi il fine riga

  cancella_buffer_seriale();
  Serial.println("Digitare la username ftp");

  do
    {
      delay(10);
    }while(Serial.available() == 0);

  do
    {
      c = (Serial.read());          // ... acquisisci il carattere
      if (c != '\n' && c != -1)                // se non è il carattere di fine riga...
        {
          ftpUser += c;           // ... aggiungi il carattere letto alla stringa
        }
    }while(c != '\n');            // rimani nel ciclo fino a che non ricevi il fine riga

  cancella_buffer_seriale();
  Serial.println("Digitare la password ftp");

  do
    {
      delay(10);
    }while(Serial.available() == 0);

  do
    {
      c = (Serial.read());          // ... acquisisci il carattere
      if (c != '\n' && c != -1)     // se non è il carattere di fine riga...
        {
          ftpPassword += c;         // ... aggiungi il carattere letto alla stringa
        }
    }while(c != '\n');              // rimani nel ciclo fino a che non ricevi il fine riga

  scrivi_credenziali_su_EEPROM(0, ssidWifi, passwordWifi, ftpUser, ftpPassword);
}

void scrivi_credenziali_su_EEPROM(int address, String & s1, String & s2, String & s3, String & s4)
{
  Serial.println("Sto per scrivere sulla EEPROM");
  delay(1500);
  for (unsigned int i = 0; i < s1.length(); i++)
    {
      EEPROM.write(address + i, s1[i]);
      EEPROM.commit();
    }
  address += s1.length();
  EEPROM.write(address, '\0'); // carattere di fine stringa
  EEPROM.commit();
  address++;

  for (unsigned int i = 0; i < s2.length(); i++)
    {
      EEPROM.write(address + i, s2[i]);
      EEPROM.commit();
    }
  address += s2.length();
  EEPROM.write(address, '\0'); // carattere di fine stringa
  EEPROM.commit();
  address++;

  for (unsigned int i = 0; i < s3.length(); i++)
    {
      EEPROM.write(address + i, s3[i]);
      EEPROM.commit();
    }
  address += s3.length();
  EEPROM.write(address, '\0'); // carattere di fine stringa
  EEPROM.commit();
  address++;

  for (unsigned int i = 0; i < s4.length(); i++)
    {
      EEPROM.write(address + i, s4[i]);
      EEPROM.commit();
    }
  address += s4.length();
  EEPROM.write(address, '\0'); // carattere di fine stringa
  EEPROM.commit();
  Serial.println("Credenziali salvate nella EEPROM");
  leggi_credenzial_su_EEPROM();
}

void cancella_buffer_seriale()
{
  Serial.end();
  delay(10);
  Serial.begin(74880);
}

void leggi_credenzial_su_EEPROM()
{
  int indirizzo = 0;
  while (true)                                // ciclo che permette di leggere la stringa rappresentante l'SSID.
    {
      char c = EEPROM.read(indirizzo);          // Leggi un byte all'indirizzo di memoria corrente (indirizzo 0 in questo caso).
      indirizzo++;                              // incrementa l'indirizzo.
      if (c == '\0')                            // se contiene il terminatore...
        {
          break;                                // ...esci dal ciclo.
        }
      ssidWifi += c;                            // Aggiungi il carattere alla stringa.
    }

  while (true)                                // ciclo che permette di leggere la stringa rappresentante l'SSID.
    {
      char c = EEPROM.read(indirizzo);          // Leggi un byte all'indirizzo di memoria corrente (indirizzo 0 in questo caso).
      indirizzo++;                              // incrementa l'indirizzo.
      if (c == '\0')                            // se contiene il terminatore...
        {
          break;                                // ...esci dal ciclo.
        }
      passwordWifi += c;                        // Aggiungi il carattere alla stringa.
    }

  while (true)                                // ciclo che permette di leggere la stringa rappresentante la password (memorizzata immediatamente dopo l'ssid)
    {
      char c = EEPROM.read(indirizzo);        // Leggi un byte all'indirizzo corrente (indirizzo attuale = 1 + lunghezza ssid))
      indirizzo++;                            // Passa all'indirizzo successivo
      if (c == '\0')                          // se si tratta del terminatore...
        {
          break;                              // ...esci dal ciclo.
        }
      ftpUser += c;                           // Aggiungi il carattere alla stringa.
    }

  while (true)                                // ciclo che permette di leggere la stringa rappresentante la password (memorizzata immediatamente dopo l'ssid)
    {
      char c = EEPROM.read(indirizzo);        // Leggi un byte all'indirizzo corrente (indirizzo attuale = 1 + lunghezza ssid))
      indirizzo++;                            // Passa all'indirizzo successivo
      if (c == '\0')                          // se si tratta del terminatore...
        {
          break;                              // ...esci dal ciclo.
        }
      ftpPassword += c;                       // Aggiungi il carattere alla stringa.
    }
  Serial.print("Attuale SSID WiFi: ");       // stampa il corrente ssid.
  Serial.println(ssidWifi);
  Serial.print("Attuale password WiFi: ");   // stampa la password wifi corrente.
  Serial.println(passwordWifi);
  Serial.print("Attuale user ftp: ");        // stampa il corrente user ftp.
  Serial.println(ftpUser);
  Serial.print("Attuale password ftp: ");    // stampa la password corrente.
  Serial.println(ftpPassword);
  Serial.println();
  Serial.println("Per cambiare SSID e password del WiFi e username e password della connessione");
  Serial.println("ftp, connettersi alla porta seriale del modulo e inviare \"r\" oppure \"R\"");
}

Looking at your code, it appears that it may have something to do with using that. The code looks fine in general, except maybe for repeated calls to :

EEPROM.commit();

The idea of calling commit() separately on ESP based boards is to prevent excessive writing to the flash chip.
Basically you should complete all of the writing to the EEPROM, and once you are done with all of that,... then call commit() and the actual writing will take place. And with the normal EEPROM library, only the bytes that are different from their previous value, will be overwritten.
The ESP_EEPROM.h library states that

This library writes a new copy of your data when you save (commit) it and keeps track of where in the sector the most recent copy is kept using a bitmap.

When committing a single character all the time, that is anyway not the way you should be doing it, but in this case that may result in something that was not intended to happen at all.

I use the normal EEPROM library on my ESP boards, and for a similar purpose as you and have not run into the lifecycle limitation at all ever. Writing for at least a 1000 times, does not sound like a lot, but unless you are doing something automated, it is quite a lot of work to reach up to that with manual input. If you change your settings every day, you will need 3 years before anything may start to show (a 1000 writes are guaranteed, but probably a lot more will be possible)

Hi Deva
It's not working.
I removed all but one of the commits() statements, but the problem persists.
I found a partial solution by changing the board in the IDE menu to "Lolin wemos d1 mini (clone)" instead of "Lolin wemos D1 mini PRO." I have a mini PRO (at least according to what I found written on the board).
The board probably has a problem.
Thanks a lot :slight_smile:

P.S. If I fix the problem, I'll come back and post it.

Maybe you could try this

Well you could actually not have the correct amount of flash. It could be fake. Anybody can write anything on a board they sell. A friend of mine used to have a 2CV with Turbo written on it. I only use generic ESP8266 as such.
I have a vague recollection of a sketch that tests for flash size.

Have you tried using

#include <EEPROM.h>

instead of

#include <ESP_EEPROM.h>

When i read the documentation i concluded that the latter version doesn't degrade flash memory cells as quickly but rather uses loads of different ones. Speed wise that could be an improvement, but in some ways i don't think it matters much.

That said, i do hope that the successor to the ESP32 does have a true EEPROM on board.

I'm starting to think so too, because I paid very little for them (€1.50).

Yes. Nothing as changed

I hope so too, because it works great with Arduino UNO.

Thank you for all the help you've given me :slight_smile:

You were right: it's a fake board.
I had to choose the "Generic ESP8285" board. Now it works fine.

I have to chose that fora lot of for ESP-01. It's a particular type of flash.

I solved the problem.
Using the "Effortless_SPIFFS" library from "thebigpotatoe," I can write permanently to the flash memory and then read back what I've written….

… but another one has arisen and regard it I'll open another request.

Thanks to everyone :slight_smile:

Antonio

:rofl: :rofl: :rofl: :rofl: