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

8,017

20

5

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".

Supplies:

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!

Share

    Recommendations

    • IoT Challenge

      IoT Challenge
    • Colors of the Rainbow Contest

      Colors of the Rainbow Contest
    • Arduino Contest 2019

      Arduino Contest 2019

    5 Discussions

    0
    None
    JhalakL

    23 days ago

    Great ! I programmed esp8266 as a local data reading and processing.. where thinking about EEPROM while reboot or reset the device but it was low memory problem and irritating idea. here is the good solution ! thank you..

    0
    None
    farmerkeith

    1 year ago

    Very useful information, Iotamajig. This is helping me deal with ESP8266 deep sleep and Blynk. Not there yet but this looks like it will really help.

    By the way, the link to the explanation of "r" for read, etc. is broken. It needs to be .../filesystem.rst rather than ../filesystem.md.

    thanks for posting.

    1 reply
    0
    None
    LarsF11

    8 weeks ago

    If all you need is to store some numerical values over a reset (e.g. deep sleep), you might want to use my lib RTCVars https://github.com/highno/rtcvars (advertisement end) which has exactly this use case and offers a (hopefully) simple way to store and access variables in RTC memory which is soft reset "resistant".

    0
    None
    himsikha31

    Question 1 year ago on Step 2

    Hi,
    I am trying to read a csv file from my PC to arduino .
    Board- arduino Uno
    IDE:arduino-1.8.5
    I have use the above code but unable to locate the header file.
    root/Arduino/ReadFile/ReadFile.ino:1:16: fatal error: FS.h: No such file or directory
    #include "FS.h"

    Is it posssible for arduino uno board?
    Or is there any other method?