Introduction: Arduino IDE: How to Store and Retrieve Data From a File.

About: IoT - Internet of Things. Iota - small thing. Thingamajig - An object whose name can't be recalled. Iotamajig - A little unnamed internet connected gizmo!

When programming with the Arduino IDE, often times we will get data we need from the web, or save data we collected to the web.

Sometimes though, we don't have an internet connection. You can save data to a variable of course, and then wait for such a time that we have an internet connection again - that will probably be the solution most of the time.

But, what happens if our circuit loses power? Our variables get flushed. Consequently, they will get flushed on a reset as well, which could be from a manual reset, or with an ESP, the use of the deepSleep() function.

There are a number of ways to work around this, such as storing to EEPROM, but what I'll cover here is using the file system library. We'll look at an example of an ESP using deepSleep(), and how to keep track of the number of loops in a file based "global variable".

Step 1: Materials Needed

We're going to focus on the code here. You could use an Arduino to run this. This example is geared at the reset that occurs using deepSleep() on an ESP8266 though, so an ESP is recommended. You can use an ESP-01 with a minor modification explained here, or use an ESP-12 wired for a reset.

Or just comment out the deepSleep() line, and you can leverage the code using manual resets on the chip/board of your choice.

Step 2: Upload Your Code:

Upload the attached code. It doesn't need any tweaking, as it's just a basic example on reading and writing to files and I kept it pretty generic:

#include "FS.h"
#include 

long intSleep = 1800000;  // Sleep for 30 minutes 

unsigned long prvTime = 0; //last time we took action


int loopCount() {

    int curCnt = 0;
    
      File f = SPIFFS.open("/count.txt", "r");

    if (!f) {
      Serial.println("Count file open failed on read.");
    } else {
      while(f.available()) {
        //Lets read line by line from the file
        String line = f.readStringUntil('\n');
        curCnt = line.toInt();
        Serial.print("Program has run ");
        Serial.print(line);
        Serial.print(" times  ");
        break; //if left in, we'll just read the first line then break out of the while.
      } 
      f.close();
    }

//opening "w" will truncate the file, so we know we only store our 1 value.
    f = SPIFFS.open("/count.txt", "w"); 

    if (!f) {
      Serial.println("Count file open failed on update.");
    } else {
      f.println(curCnt + 1); 
      f.close();
      Serial.println("Adding one");
    }

    return curCnt;
}

int loopReset() {
    
    File f = SPIFFS.open("/count.txt", "w");

    if (!f) {
      Serial.println("Count file open failed on reset.");
    } else {
      f.println(0); 
      f.close();
    }
}

void takeAction() {
  Serial.println("We did something!");
  //reset our loop counter:
  loopReset();
}

void setup() {
  
  Serial.begin(74880);
  delay(10);

  SPIFFS.begin();
  
  // Take some action if we've had 6 iterations (0 index)
  if (loopCount() > 5) {
    takeAction();
  }
  
//1,000,000 = 1 second
  ESP.deepSleep(20000000); //20 seconds
  
}


void loop() {

  //nothing to do here, since deep sleep prevents it from getting this far...
    
}

Step 3: Important Points:

The File System include lets us access the file handling capabilities:

#include "FS.h"

This lets us use the SPIFFS object (SPI Flash File System), which you'll see several calls to.

I strongly recommend reading this page for an excellent explanation of the file system functionality.

In this example, once we've been reset 6 times (0 index counter), we'll take some action. Just a simple write to serial in this case. Once we've taken our action, then we reset the loop count and continue on.

There are a number of ways to open the file. Here we used "r" for read, and "w" to write. There is also "a" for appending data, as well as multiple versions of these same options (explained here). While "r" is pretty self explanatory, I specifically chose the "w" write option in several parts of the code because it truncates the file - making sure we have an empty file before we store the data - AND it will create the file if it doesn't exist.

Again, this is just one way to store and access data, but I hope you've found this example helpful!