Retrieving last saved SD card data in case Arduino power source dies

Hello,

I was looking at designing a solar current data logger such that this current is used to provide charge to a 6000mah lipo battery.

I am currently monitoring the current charge of the battery and overall solar current and storing this data on a 32 GB SD card while transmitting this value with bluetooth via a JSON file so it can update on my phone application.

The reason for the SD card was to be able to retrieve the last saved values once the battery runs out of charge and turns off the Arduino to be able to better calculate the current produced by the Solar Panel.

My question is if there's a way to retrieve the last saved values of my SD card and send them as a JSON file to my app??

My values are represented like this:

Initializing SD card...initialization done.
done.
TEST1.CSV
The current is: -0.07
The current charge is: 10.00
The current is: -0.07
The current charge is: 10.00
The current is: -0.07
The current charge is: 10.00
The current is: -0.04
The current charge is: 10.00
The current is: -0.04
The current charge is: 10.00
The current is: 0.00
The current charge is: 10.00
The current is: 0.04
The current charge is: 10.00
The current is: 0.04
The current charge is: 10.01
The current is: 0.04
The current charge is: 10.01
The current is: 0.04
The current charge is: 10.01
The current is: 0.07
The current charge is: 10.02
The current is: 0.07
The current charge is: 10.03
The current is: 0.07
The current charge is: 10.04
The current is: 0.07
The current charge is: 10.04
The current is: 0.07
The current charge is: 10.05
The current is: 0.07
The current charge is: 10.06
The current is: 0.07
The current charge is: 10.06
The current is: 0.07
The current charge is: 10.07
The current is: 0.04
The current charge is: 10.08
The current is: 0.04
The current charge is: 10.08
The current is: 0.07
The current charge is: 10.09
The current is: 0.07
The current charge is: 10.09
The current is: 0.04
The current charge is: 10.10
The current is: 0.04
The current charge is: 10.10
The current is: 0.04
The current charge is: 10.10
The current is: 0.07
The current charge is: 10.11
The current is: 0.04
The current charge is: 10.11
The current is: 0.04
The current charge is: 10.12
The current is: 0.04
The current charge is: 10.12
The current is: 0.04
The current charge is: 10.13
The current is: 0.04
The current charge is: 10.13
The current is: 0.04
The current charge is: 10.13
The current is: 0.07
The current charge is: 10.14
The current is: 0.07
The current charge is: 10.15
The current is: 0.07
The current charge is: 10.15
The current is: 0.07
The current charge is: 10.16
The current is: 0.07
The current charge is: 10.17
The current is: 0.14
The current charge is: 10.18
The current is: 0.14
The current charge is: 10.20
The current is: 0.14
The current charge is: 10.21
The current is: 0.14
The current charge is: 10.23
The current is: 0.14
The current charge is: 10.24
The current is: 0.18
The current charge is: 10.26
The current is: 0.22
The current charge is: 10.28
The current is: 0.25
The current charge is: 10.31
The current is: 0.25
The current charge is: 10.33
The current is: 0.29
The current charge is: 10.36
The current is: 0.25
The current charge is: 10.38
The current is: 0.25
The current charge is: 10.41
The current is: 0.25
The current charge is: 10.43
The current is: 0.25
The current charge is: 10.46
The current is: 0.22
The current charge is: 10.48
The current is: 0.22
The current charge is: 10.50
The current is: 0.18
The current charge is: 10.52
The current is: 0.11
The current charge is: 10.53
The current is: 0.11
The current charge is: 10.54
The current is: 0.11
The current charge is: 10.55
The current is: 0.14
The current charge is: 10.57
The current is: 0.14
The current charge is: 10.58
The current is: 0.18
The current charge is: 10.60
The current is: 0.18
The current charge is: 10.62
The current is: 0.22
The current charge is: 10.64
The current is: 0.22
The current charge is: 10.66
The current is: 0.25
The current charge is: 10.69
The current is: 0.32
The current charge is: 10.72
The current is: 0.32
The current charge is: 10.75
The current is: 0.29
The current charge is: 10.78
The current is: 0.29
The current charge is: 10.81
The current is: 0.29
The current charge is: 10.84
The current is: 0.29
The current charge is: 10.87
The current is: 0.32
The current charge is: 10.90
The current is: 0.32
The current charge is: 10.93
The current is: 0.36
The current charge is: 10.97
The current is: 0.36
The current charge is: 11.00
The current is: 0.36
The current charge is: 11.04
The current is: 0.36
The current charge is: 11.07
The current is: 0.36
The current charge is: 11.11
The current is: 0.36
The current charge is: 11.15
The current is: 0.32
The current charge is: 11.18
The current is: 0.32
The current charge is: 11.21
The current is: 0.32
The current charge is: 11.24
The current is: 0.32
The current charge is: 11.27
The current is: 0.32
The current charge is: 11.31
The current is: 0.32
The current charge is: 11.34
The current is: 0.36
The current charge is: 11.38

I realize that we are able to set the cursor further down the SD file to be able to read the values but I had very little to no success at doing this with my file being around 60.8MB and every input being sized at 51 bytes.

Here is the code I have been using to test:

/*
  SD card read/write

  This example shows how to read and write data to and from an SD card file
  The circuit:
   SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 10 (for MKRZero SD: SDCARD_SS_PIN)

  created   Nov 2010
  by David A. Mellis
  modified 9 Apr 2012
  by Tom Igoe

  This example code is in the public domain.

*/

#include <SPI.h>
#include <SD.h>

File myFile;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }


  Serial.print("Initializing SD card...");

  if (!SD.begin(10)) {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");


  // open the file for reading:
  myFile = SD.open("TEST1.CSV");
  
  if (myFile) {
    Serial.println("TEST1.CSV");

    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      int fileLength = myFile.available();
      int recordCount = fileLength / 51;
      int lastRecordStart = (recordCount - 1) * 51;
      myFile.seek(lastRecordStart); // Position the read cursor at the start of the last record
      Serial.write(myFile.read());
    }
    // close the file:
    myFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
}

void loop() {
  // nothing happens after setup
}

The file class has a size function that will give you the length of the file. You can use that to seek to the last record.

An int on an Arduino is usually 2 bytes so an unsigned int can hold 65535 as the maximum, a signed int 32767.

If your file is over 60MB, then clearly an int will not be able to give you the size in bytes.

myfile.available give you a number of bytes available not the size of the file, if you wan the size of the file then as WildBill has indicated you need to use myfile.size (which returns an unsigned long). You wil also need to use unsigned longs (or possibly longs) in you calculation to give a value to myfile.seek.

wildbill:
The file class has a size function that will give you the length of the file. You can use that to seek to the last record.

countrypaul:
An int on an Arduino is usually 2 bytes so an unsigned int can hold 65535 as the maximum, a signed int 32767.

If your file is over 60MB, then clearly an int will not be able to give you the size in bytes.

myfile.available give you a number of bytes available not the size of the file, if you wan the size of the file then as WildBill has indicated you need to use myfile.size (which returns an unsigned long). You wil also need to use unsigned longs (or possibly longs) in you calculation to give a value to myfile.seek.

Whether my code variables change from int to long, my code gives me this in the serial monitor:

eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee

Changing my file length as proposed:

 while (myFile.available()) {
      long fileLength = myFile.size();
      long recordCount = fileLength / 51;
      long lastRecordStart = (recordCount - 1) * 51;
      myFile.seek(lastRecordStart); // Position the read cursor at the start of the last record
      Serial.write(myFile.read());
    }

Give this on the serial monitor:

Initializing SD card...initialization done.
TEST1.CSV

Just do the seek once, then read the last record.

wildbill:
Just do the seek once, then read the last record.

Moving it out of the while loop seems to have solved it. Thank you very much!

Also, what type of variable can I store myFile.read() to?? Is it an int variable?

Read returns an int so it can give -1 when there's nothing to read. You would probably want to store it in a char though if you're going to print it.