Loss of data stored in flash

Hello, all, I'm pretty confused and I'll try to get some support by the community.

I have created a circuit with a 1.5F supercapacitor connected to the 3V3 pin of a Wroom Devboard, allowing the board to save a list of variables to flash memory using the preferences.h library.

When power is lost, the board detects the voltage dropping to a logical 0, initiates a light sleep, saves the data to flash, and then enters deep sleep.

If I reapply power before the supercapacitor discharges (a few seconds later), the board exits deep sleep and correctly reads the variables. However, if the supercapacitor discharges completely or I disconnect it during deep sleep, upon reboot the flash memory variables are not read. Reading the variables from memory is based on a flag that is part of the variables saved when the power loss was detected.

Why do I lose the variables saved in flash memory if the board loses power during deep sleep?

Thank you very much for your help.

Post the code in code tags, and tell us which variables that are not being saved. Also which board are you using.

1 Like

Show a sketch that illustrates this alleged loss of data please. And perhaps a schematic.

1 Like

Have you read the following https://docs.arduino.cc/language-reference/en/variables/utilities/PROGMEM/

@sonofcy

Have you read the following

I have created a circuit with a 1.5F supercapacitor connected to the 3V3 pin of a Wroom Devboard, allowing the board to save a list of variables to flash memory using the preferences.h library.

@seitretre is using an ESP32 and PROGMEM is not relevant.

1 Like

DUH, I didn't check, my bad.

And that library is intended to replace the previous EEPROM emulation library for the ESP32, which was mentioned in a post, but then edited out.

As far as the OPs original request for help goes, then without seeing the code being used its difficult to see what the problem might be.

Maybe you are using a library that uses flash memory to emulate EEPROM?

Since data is written to flash in pages, versus EEPROM where data is written byte by byte, your code may need to call a commit function to write the data to flash. Without that commit, the data remains in RAM memory. As long as the chip has power, the contents of the RAM are not lost.

1 Like

I dont recall seeing a requirement for a 'commit' command to ensure that the ESP32 preferences library actually writes and stores data in Flash.

1 Like

OK, I share some code, maybe it is more helpful.
Here you can find the parts that are related to the use of the memory.

//Libreria per il salvataggio nella Non Volatile Storage (NVS)
#include <Preferences.h>

Before the setup, I declare this global variable

//Oggetto memoria non volatile
Preferences mnv;  //Memoria non volatile

In the setup I have the following:

// Lettura della memoria non volatile, quando necessario
  mnv.begin("memnonvolatile", false);                //true vuol dire solo lettura, false vuol dire lettura e scrittura
  bool abilitato = mnv.getBool("mnv_abilit"/*, 0*/);  // Lettura di abilitato che è il flag che quando è a 1 indica che vanno letti i valori presenti in memoria. Il secondo parametro è il valore di default
  if (abilitato) { //Se era stato salvato un valore di abilitato ed il valore era uno, si leggono i valori
    caricamento();
    abilitato = 0;
    mnv.putBool("mnv_abilit", abilitato);  //Si porta a 0 il valore di abilitato
  }
  mnv.end();  //Chiusura della memoria non volatile
  Serial.println("We are live");
  delay(2500);
}

When we go to the loop, we have

  if (!digitalRead(vita)) {
    esp_light_sleep_start();
    salvataggio();
    esp_deep_sleep_start();  // Entra in deep sleep
  }

I have introduced the light sleep today, I don't know if it really makes the difference.

Salvataggio is te function that saves the variables

void salvataggio() {
  /*
  PER DEBUG
  oraalba[0]=22;
  oraalba[1]=22;
  oraalbaart[0]=22;
  oraalbaart[1]=22;
  oratramonto[0] = 22;
  oratramonto[1] = 22;
  oratramontoart[0]=18 ;
  oratramontoart[1]=18;
  appotramontoforz[0] = 23;
  appotramontoforz[1] = 23;
  datacove[0] = 12;
  datacove[1] = 12;
  luceodierna = 22;
  giornoluce = 22;
  margine = 22;
  marginemaltempo = 22;
  sogliaalba = 22;
  sogliatramonto = 22;
  isteresialba = 22;
  isteresitramonto = 22;
  durataalbatramonto = 22;
  maxcanalem = 22;
  maxcanalef = 22;
  maxcanalel = 22;
  minaltra = 22;
  ultimopwmm = 22;
  ultimopwmf = 22;
  ultimopwml = 22;
  offsetoggi = 22;
  modooperativo = 3;
  minutiplus = 22;
  offsetluce = 22;
  durlucemin = 22;
  ecooff = 22;
  ecoon = 22;
  flagalba = 1;
  flagtramonto = 1;
  flaginalba = 1;
  flagintramonto = 1;
  perturbazionealba = 1;
  perturbazionetramonto = 1;
  albaartfissa = 1;
  tramontoartfisso = 1;
  covefisse = 1;
  luciaccese = 1;
  lunaaccesa = 1;
  aaic = 1;
  taic = 1;
  satic=18;
  primogiorno = 0;
  tramontoforzato = 1;
  modoeco = 1;*/
  mnv.begin("memnonvolatile", false);
  mnv.putShort("mnv_halbaz", oraalba[0]);
  //Serial.print("Valore oraalba[0]: ");
  //Serial.println(oraalba[0]);
  mnv.putShort("mnv_halbau", oraalba[1]);
  //Serial.print("Valore oraalba[1]: ");
  //Serial.println(oraalba[1]);
  mnv.putShort("mnv_htramz", oratramonto[0]);
  //Serial.print("Valore oratramonto[0]: ");
  //Serial.println(oratramonto[0]);
  mnv.putShort("mnv_htramu", oratramonto[1]);
  //Serial.print("Valore oratramonto[1]: ");
  //Serial.println(oratramonto[1]);
  mnv.putShort("mnv_halbartz", oraalbaart[0]);
  // Serial.print("Valore oraalbaart[0]: ");
  //Serial.println(oraalbaart[0]);
  mnv.putShort("mnv_halbartu", oraalbaart[1]);
  //  Serial.print("Valore oraalbaart[1]: ");
  //  Serial.println(oraalbaart[1]);
  mnv.putShort("mnv_htrartz", oratramontoart[0]);
  //  Serial.print("Valore oratramontoart[0]: ");
  //  Serial.println(oratramontoart[0]);
  mnv.putShort("mnv_htrartu", oratramontoart[1]);
  //  Serial.print("Valore oratramontoart[1]: ");
  //  Serial.println(oratramontoart[1]);
  mnv.putShort("mnv_aptramforzz", appotramontoforz[0]);
  //  Serial.print("Valore appotramontoforz[0]: ");
  //  Serial.println(appotramontoforz[0]);
  mnv.putShort("mnv_aptramforzu", appotramontoforz[1]);
  //  Serial.print("Valore appotramontoforz[1]: ");
  //  Serial.println(appotramontoforz[1]);
  mnv.putShort("mnv_datacovez", datacove[0]);
  //  Serial.print("Valore datacove[0]: ");
  //  Serial.println(datacove[0]);
  mnv.putShort("mnv_datacoveu", datacove[1]);
  //  Serial.print("Valore datacove[1]: ");
  //  Serial.println(datacove[1]);
  mnv.putShort("mnv_luceodierna", luceodierna);
  //  Serial.print("Valore luceodierna: ");
  //  Serial.println(luceodierna);
  mnv.putShort("mnv_giornoluce", giornoluce);
  //  Serial.print("Valore giornoluce: ");
  //  Serial.println(giornoluce);
  mnv.putShort("mnv_margine", margine);
  //  Serial.print("Valore margine: ");
  //  Serial.println(margine);
  mnv.putShort("mnv_margmalt", marginemaltempo);
  //  Serial.print("Valore marginemaltempo: ");
  //  Serial.println(marginemaltempo);
  mnv.putShort("mnv_sogliaalba", sogliaalba);
  //  Serial.print("Valore sogliaalba: ");
  //  Serial.println(sogliaalba);
  mnv.putShort("mnv_sogliatram", sogliatramonto);
  //  Serial.print("Valore sogliatramonto: ");
  //  Serial.println(sogliatramonto);
  mnv.putShort("mnv_istalb", isteresialba);
  //  Serial.print("Valore isteresialba: ");
  //  Serial.println(isteresialba);
  mnv.putShort("mnv_isttram", isteresitramonto);
  //  Serial.print("Valore isteresitramonto: ");
  //  Serial.println(isteresitramonto);
  mnv.putShort("mnv_duraltram", durataalbatramonto);
  //Serial.print("Valore durataalbatramonto: ");
  //  Serial.println(durataalbatramonto);
  mnv.putShort("mnv_maxcanalem", maxcanalem);
  //  Serial.print("Valore maxcanalem: ");
  //  Serial.println(maxcanalem);
  mnv.putShort("mnv_maxcanalef", maxcanalef);
  //  Serial.print("Valore maxcanalef: ");
  //  Serial.println(maxcanalef);
  mnv.putShort("mnv_maxcanalel", maxcanalel);
  //  Serial.print("Valore maxcanalel: ");
  //  Serial.println(maxcanalel);
  mnv.putShort("mnv_minaltra", minaltra);
  //  Serial.print("Valore minaltra: ");
  //  Serial.println(minaltra);
  mnv.putShort("mnv_ultimopwmm", ultimopwmm);
  //  Serial.print("Valore ultimopwmm: ");
  //  Serial.println(ultimopwmm);
  mnv.putShort("mnv_ultimopwmf", ultimopwmf);
  //  Serial.print("Valore ultimopwmf: ");
  //  Serial.println(ultimopwmf);
  mnv.putShort("mnv_ultimopwml", ultimopwml);
  //  Serial.print("Valore ultimopwml: ");
  //  Serial.println(ultimopwml);
  mnv.putShort("mnv_offsetoggi", offsetoggi);
  //  Serial.print("Valore offsetoggi: ");
  //  Serial.println(offsetoggi);
  mnv.putShort("mnv_modoop", modooperativo);
  //  Serial.print("Valore modooperativo: ");
  //  Serial.println(modooperativo);
  mnv.putShort("mnv_minplus", minutiplus);
  //  Serial.print("Valore minutiplus: ");
  //  Serial.println(minutiplus);
  mnv.putShort("mnv_offsetluce", offsetluce);
  //  Serial.print("Valore offsetluce: ");
  //  Serial.println(offsetluce);
  mnv.putShort("mnv_durlucemin", durlucemin);
  //  Serial.print("Valore durlucemin: ");
  //  Serial.println(durlucemin);
  mnv.putShort("mnv_ecooff", ecooff);
  //  Serial.print("Valore ecooff: ");
  //  Serial.println(ecooff);
  mnv.putShort("mnv_ecoon", ecoon);
  //  Serial.print("Valore ecoon: ");
  //  Serial.println(ecoon);
  mnv.putBool("mnv_flgal", flagalba);
  //  Serial.print("Valore flagalba: ");
  //  Serial.println(flagalba);
  mnv.putBool("mnv_flgtr", flagtramonto);
  //  Serial.print("Valore flagtramonto: ");
  //  Serial.println(flagtramonto);
  mnv.putBool("mnv_flgina", flaginalba);
  //  Serial.print("Valore flaginalba: ");
  //  Serial.println(flaginalba);
  mnv.putBool("mnv_flgintr", flagintramonto);
  //  Serial.print("Valore flagintramonto: ");
  //  Serial.println(flagintramonto);
  mnv.putBool("mnv_pertalb", perturbazionealba);
  //  Serial.print("Valore perturbazionealba: ");
  //  Serial.println(perturbazionealba);
  mnv.putBool("mnv_pertram", perturbazionetramonto);
  //  Serial.print("Valore perturbazionetramonto: ");
  //  Serial.println(perturbazionetramonto);
  mnv.putBool("mnv_albartf", albaartfissa);
  //  Serial.print("Valore albaartfissa: ");
  //  Serial.println(albaartfissa);
  mnv.putBool("mnv_trarf", tramontoartfisso);
  //  Serial.print("Valore tramontoartfisso: ");
  //  Serial.println(tramontoartfisso);
  mnv.putBool("mnv_covefisse", covefisse);
  //  Serial.print("Valore covefisse: ");
  //  Serial.println(covefisse);
  mnv.putBool("mnv_luciaccese", luciaccese);
  //  Serial.print("Valore luciaccese: ");
  //  Serial.println(luciaccese);
  mnv.putBool("mnv_lunaaccesa", lunaaccesa);
  //  Serial.print("Valore lunaaccesa: ");
  //  Serial.println(lunaaccesa);
  mnv.putBool("mnv_aaic", aaic);
  //  Serial.print("Valore aaic: ");
  //  Serial.println(aaic);
  mnv.putBool("mnv_taic", taic);
  //  Serial.print("Valore taic: ");
  //  Serial.println(taic);
  mnv.putBool("mnv_primogiorno", primogiorno);
  //  Serial.print("Valore primogiorno: ");
  //  Serial.println(primogiorno);
  mnv.putBool("mnv_trforz", tramontoforzato);
  //  Serial.print("Valore tramontoforzato: ");
  //  Serial.println(tramontoforzato);
  mnv.putBool("mnv_modoeco", modoeco);
  //  Serial.print("Valore modoeco: ");
  //  Serial.println(modoeco);
  mnv.putBool("mnv_lgiorno", lgiorno);
  //  Serial.print("Valore lgiorno: ");
  //  Serial.println(lgiorno);
  mnv.putBool("mnv_abilit", 1);  //Si porta a 1 il valore di abilitato
  mnv.end();
}
caricamento is the function that reads the variables
void caricamento() {
  noluce = 1;  //Questo è il flag che viene usato per indicare che è avvenuto un risveglio a seguito di una perdita di alimentazione
  oraalba[0] = mnv.getShort("mnv_halbaz", -1);
  //Serial.print("Valore oraalba[0]: ");
  //Serial.println(oraalba[0]);
  oraalba[1] = mnv.getShort("mnv_halbau", -1);
  //Serial.print("Valore oraalba[1]: ");
  //Serial.println(oraalba[1]);
  oratramonto[0] = mnv.getShort("mnv_htramz", -1);
  //Serial.print("Valore oratramonto[0]: ");
  //Serial.println(oratramonto[0]);
  oratramonto[1] = mnv.getShort("mnv_htramu", -1);
  //Serial.print("Valore oratramonto[1]: ");
  //Serial.println(oratramonto[1]);
  oraalbaart[0] = mnv.getShort("mnv_halbartz", -1);
  //Serial.print("Valore oraalbaart[0]: ");
  //Serial.println(oraalbaart[0]);
  oraalbaart[1] = mnv.getShort("mnv_halbartu", -1);
  //Serial.print("Valore oraalbaart[1]: ");
  //Serial.println(oraalbaart[1]);
  oratramontoart[0] = mnv.getShort("mnv_htrartz", -1);
  //Serial.print("Valore oratramontoart[0]: ");
  //Serial.println(oratramontoart[0]);
  oratramontoart[1] = mnv.getShort("mnv_htrartu", -1);
  //Serial.print("Valore oratramontoart[1]: ");
  //Serial.println(oratramontoart[1]);
  appotramontoforz[0] = mnv.getShort("mnv_aptramforzz", -1);
  //Serial.print("Valore appotramontoforz[0]: ");
  //Serial.println(appotramontoforz[0]);
  appotramontoforz[1] = mnv.getShort("mnv_aptramforzu", -1);
  //Serial.print("Valore appotramontoforz[1]: ");
  //Serial.println(appotramontoforz[1]);
  datacove[0] = mnv.getShort("mnv_datacovez", 0);
  //Serial.print("Valore datacove[0]: ");
  //Serial.println(datacove[0]);
  datacove[1] = mnv.getShort("mnv_datacoveu", 0);
  //Serial.print("Valore datacove[1]: ");
  //Serial.println(datacove[1]);
  luceodierna = mnv.getShort("mnv_luceodierna", 0);
  //Serial.print("Valore luceodierna: ");
  //Serial.println(luceodierna);
  giornoluce = mnv.getShort("mnv_giornoluce", 0);
  //Serial.print("Valore giornoluce: ");
  //Serial.println(giornoluce);
  margine = mnv.getShort("mnv_margine", 15);
  //Serial.print("Valore margine: ");
  //Serial.println(margine);
  marginemaltempo = mnv.getShort("mnv_margmalt", 60);
  //Serial.print("Valore marginemaltempo: ");
  //Serial.println(marginemaltempo);
  sogliaalba = mnv.getShort("mnv_sogliaalba", 2);
  //Serial.print("Valore sogliaalba: ");
  //Serial.println(sogliaalba);
  sogliatramonto = mnv.getShort("mnv_sogliatram", 2);
  //Serial.print("Valore sogliatramonto: ");
  //Serial.println(sogliatramonto);
  isteresialba = mnv.getShort("mnv_istalb", 2);
  //Serial.print("Valore isteresialba: ");
  //Serial.println(isteresialba);
  isteresitramonto = mnv.getShort("mnv_isttram", 7);
  //Serial.print("Valore isteresitramonto: ");
  //Serial.println(isteresitramonto);
  durataalbatramonto = mnv.getShort("mnv_duraltram", 30);
  //Serial.print("Valore durataalbatramonto: ");
  //Serial.println(durataalbatramonto);
  maxcanalem = mnv.getShort("mnv_maxcanalem", 100);
  //Serial.print("Valore maxcanalem: ");
  //Serial.println(maxcanalem);
  maxcanalef = mnv.getShort("mnv_maxcanalef", 100);
  //Serial.print("Valore maxcanalef: ");
  //Serial.println(maxcanalef);
  maxcanalel = mnv.getShort("mnv_maxcanalel", 100);
  //Serial.print("Valore maxcanalel: ");
  //Serial.println(maxcanalel);
  minaltra = mnv.getShort("mnv_minaltra", 0);
  //Serial.print("Valore minaltra: ");
  //Serial.println(minaltra);
  ultimopwmm = mnv.getShort("mnv_ultimopwmm", 0);
  //Serial.print("Valore ultimopwmm: ");
  //Serial.println(ultimopwmm);
  ultimopwmf = mnv.getShort("mnv_ultimopwmf", 0);
  //Serial.print("Valore ultimopwmf: ");
  //Serial.println(ultimopwmf);
  ultimopwml = mnv.getShort("mnv_ultimopwml", 0);
  //Serial.print("Valore ultimopwml: ");
  //Serial.println(ultimopwml);
  offsetoggi = mnv.getShort("mnv_offsetoggi", 0);
  //Serial.print("Valore offsetoggi: ");
  //Serial.println(offsetoggi);
  modooperativo = mnv.getShort("mnv_modoop", 0);
  //Serial.print("Valore modooperativo: ");
  //Serial.println(modooperativo);
  minutiplus = mnv.getShort("mnv_minplus", 0);
  //Serial.print("Valore minutiplus: ");
  //Serial.println(minutiplus);
  offsetluce = mnv.getShort("mnv_offsetluce", 0);
  //Serial.print("Valore offsetluce: ");
  //Serial.println(offsetluce);
  durlucemin = mnv.getShort("mnv_durlucemin", 0);
  //Serial.print("Valore durlucemin: ");
  //Serial.println(durlucemin);
  ecooff = mnv.getShort("mnv_ecooff", 150);
  //Serial.print("Valore ecooff: ");
  //Serial.println(ecooff);
  ecoon = mnv.getShort("mnv_ecoon", 100);
  //Serial.print("Valore ecoon: ");
  //Serial.println(ecoon);
  flagalba = mnv.getBool("mnv_flgal", 0);
  //Serial.print("Valore flagalba: ");
  //Serial.println(flagalba);
  flagtramonto = mnv.getBool("mnv_flgtr", 0);
  //Serial.print("Valore flagtramonto: ");
  //Serial.println(flagtramonto);
  flaginalba = mnv.getBool("mnv_flgina", 0);
  //Serial.print("Valore flaginalba: ");
  //Serial.println(flaginalba);
  flagintramonto = mnv.getBool("mnv_flgintr", 0);
  //Serial.print("Valore flagintramonto: ");
  //Serial.println(flagintramonto);
  perturbazionealba = mnv.getBool("mnv_pertalb", 0);
  //Serial.print("Valore perturbazionealba: ");
  //Serial.println(perturbazionealba);
  perturbazionetramonto = mnv.getBool("mnv_pertram", 0);
  //Serial.print("Valore perturbazionetramonto: ");
  //Serial.println(perturbazionetramonto);
  albaartfissa = mnv.getBool("mnv_albartf", 0);
  //Serial.print("Valore albaartfissa: ");
  //Serial.println(albaartfissa);
  tramontoartfisso = mnv.getBool("mnv_trarf", 0);
  //Serial.print("Valore tramontoartfisso: ");
  //Serial.println(tramontoartfisso);
  covefisse = mnv.getBool("mnv_covefisse", 0);
  //Serial.print("Valore covefisse: ");
  //Serial.println(covefisse);
  luciaccese = mnv.getBool("mnv_luciaccese", 0);
  //Serial.print("Valore luciaccese: ");
  //Serial.println(luciaccese);
  lunaaccesa = mnv.getBool("mnv_lunaaccesa", 0);
  //Serial.print("Valore lunaaccesa: ");
  //Serial.println(lunaaccesa);
  aaic = mnv.getBool("mnv_aaic", 0);
  //Serial.print("Valore aaic: ");
  //Serial.println(aaic);
  taic = mnv.getBool("mnv_taic", 0);
  //Serial.print("Valore taic: ");
  //Serial.println(taic);
  primogiorno = mnv.getBool("mnv_primogiorno", 1);
  //Serial.print("Valore primogiorno: ");
  //Serial.println(primogiorno);
  tramontoforzato = mnv.getBool("mnv_trforz", 0);
  //Serial.print("Valore tramontoforzato: ");
  //Serial.println(tramontoforzato);
  modoeco = mnv.getBool("mnv_modoeco", 0);
  //Serial.print("Valore modoeco: ");
  //Serial.println(modoeco);
  lgiorno = mnv.getBool("mnv_lgiorno", 0);
  //Serial.print("Valore lgiorno: ");
  //Serial.println(lgiorno);
  ripristinoluci(); //this function restores the state of the leds
}

Deep sleep and wakeup work. If I leave the esp powered and I disconnect the pin "vita" the board saves the variables and goes to sleep. When I connect the pin again, the board wakes up and restore the status according to the saved variable.

If I do the same but I disconnect as well the supercap that is keeping the board powered (it is connected directly to the 3V3pin, the variables are not read at the restart.

The same if I let the supercap taking the time to completely discharge

Snippets are generally not helpful to diagnose a potential problem. As already requested, show a sketch that illustrates this alleged loss of data please. A complete sketch.

1 Like

It's a 3k lines code where there is no more command reading or writing the flash. Just controlling some leds, reading two sensors and an rtc.

1 Like

Okay then. Good luck and good bye.

1 Like

And have you tried to reduce the sketch to the minimum that exhibits the the same problem ?

If the problem sketch is many many lines long, it can be very very difficult indeed to spot a problem.

1 Like

Good idea.
I'll try to do it to see if anything changes.

Do you see any potencial error in what I have shared?

No idea, way way to much code to check.

Reduce the 'problem' code massively, save maybe one or two variables, and see if you get the same problem ....................

You may find it more simple and faster to have all the data in a struct and have salvagiato()
and caricamento() save and retrieve the data with .putBytes() and .getBytes().

#include <Preferences.h>
Preferences prefs;

void setup()
{
  Serial.begin(115200);
  struct settings
  {
    int onbefor;
    int offabove;
    bool automatic;
    bool cent;
  };
  settings save1 = { 10, 18, true, false };
  settings retrieve1 = { 0, 0, 0, 0 };

  prefs.begin("Settings");  //namespace
  prefs.putBytes("Settings", &save1, sizeof(save1));
  prefs.getBytes("Settings", &retrieve1, sizeof(retrieve1));

  Serial.println(retrieve1.onbefor);
  Serial.println(retrieve1.offabove);
  Serial.println(retrieve1.automatic);
  Serial.println(retrieve1.cent);
  
  
}
void loop() {}
1 Like

I would agree.

I had a pile of variables I wanted to save in flash, putting the variables in a structure and using putBytes() to save the structure seemed to be the way to do it.

1 Like

Good idea, then I'll try to define a structure with all the variables and store it. Maybe save only one variable (struct) with all the values could be the solution instead of many variables.
(I'll take a couple of days before doing it due to job and family)
I'll share with you the outcome of the attempt. Maybe use a couple of stacks couls be a good alternative, as well?

Maybe for testing if the number of variables is being the issue, I'll start reducing them to 4 or 5 and see what happens...

I must admit I'm not familiar with that library. But I have seen that other libraries that emulate ERPROM, for MCUs that have only flash, have a commit function, and this often catches out beginners.