Read from SD not matching with the write

Hello,

I am building a counter that would survive reset and decided to save data to an SD card.
Definitely I am not doing it correct because no matter the value I write it’s reading “-1”.
Could someone please point me in the right direction?
Thanks.

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

#define SENSOR D4
#define RELAY D3

long num = 0;

void setup() {
  Serial.begin (9600);
  pinMode (SENSOR, INPUT);
  pinMode (RELAY, OUTPUT);
  delay (50);
  Serial.begin(9600);
    File myFile = SD.open("datalog.txt");
  if (myFile) {
    Serial.println("Datalog found and opened");
    while (myFile.available()) {
      Serial.print("What's in the file - ");
      Serial.println(myFile.read());
      Serial.println("Writing from file to variable");
      num = myFile.parseInt();
      Serial.print("And in the variable - ");
      Serial.println(num);
      }
    myFile.close();
  delay(50);
  Serial.println("SYSTEM STARTED");
  }
}

void action() {
  SD.remove("datalog.txt");
  File myFile = SD.open("datalog.txt", FILE_WRITE);
  myFile.println(num);
  myFile.close();
  myFile = SD.open("datalog.txt");
  Serial.print("What's in the file - ");
  Serial.println(myFile.read());
  Serial.println("Writing from file to variable");
  Serial.print("And in the variable - ");
  Serial.println(num);
  myFile.close();
  delay (50);
}

void loop() {
  int L = digitalRead (SENSOR);
  if (L == 0){
    num++;
    Serial.println("ACTION");
    action();
    }
  delay (50);
}

This code worked for me:

/*
  SD card read/write
  Mod 01 make file name a string and iterate until we find a unused file name.
  Mod 02 add capability to increment filename.
  Rev 03 tested successfully on Arduino M0

  SD card attached to SPI bus on ICSP Header.
  SD Board power = 5V (for large board with EEPROM)

  based on code created: Nov 2010 by David A. Mellis, 9 Apr 2012 by Tom Igoe
  This code is in the public domain.

driver has a 512 byte buffer then write to SD

Closing the file forces any buffered data to be written to the SD and also updates
the file's directory entry.

If you don't close the file, you will lose all data written the file since it was opened,
not just the last buffer, since the directory entry will not be updated.
*/

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

// *** SD Card declarations **************************************************
// ***************************************************************************

#define SDCARD_CS_PIN 4

uint8_t fileNumb = 100;
char dataFile[8];
bool SD_Error = false;

File myFile;			// create instance of a "File" class

void setup() {
  SerialUSB.begin(115200);
  delay (2000);
// Initializing SD card....
  if (!SD.begin(SDCARD_CS_PIN))
    {SerialUSB.print("initialization failed");
     SD_Error = true;
    }

// loop until we find a file that doesn't already exist.......
  do
    {
     itoa(fileNumb, dataFile, 10);  // (value, Array, base)
     const char *extension = ".csv";
     strcat(dataFile, extension);  // syntax  strcat(dest, source)
     ++fileNumb;
    } while (SD.exists(dataFile));


SerialUSB.print("READY TO OPEN FILE FOR WRITING   = ");
SerialUSB.println(dataFile);
  myFile = SD.open(dataFile, FILE_WRITE);   // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
SerialUSB.println(myFile);
  // if the file opened okay, write to it:
  if (myFile) {
    myFile.println("data from boiler");     // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    SerialUSB.println("data from boiler");
    //SerialUSB.print(" data written to file:   ");
    myFile.close();                         // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 SerialUSB.println(dataFile);
    }
  else {
    // if the file didn't open, print an error:
    SD_Error = true;
    }
  SerialUSB.print("SD_Error = ");
  SerialUSB.print(SD_Error);
}
void loop() {
  // nothing happens after setup
}

Your code lacks an SD.begin() statement.

Declaration of the CS pin and SD begin statements were missing and now added.
I can write to the file and at least it’s not a -1 value all the time but still far from expected.
No matter the value in the file on the SD it’s reading it as 49 and then each time counter is triggered it’s adding +1 until it gets to 57. Strange thing is that 49 isn’t what goes to my system counter variable. After reset it turns into zero and +1 is added each time counter is activated.
Interesting thing is that SD card opened on the PC is showing correct value of the counter. So from the example here SD card file has 11 recorded in it. Maybe it’s different format? Text or something? Do I need to convert my readings from an SD somehow so it’s a numerical value?
Here is the COM console log:

SYSTEM STARTED
Button pushed
Reading from the file - 49
Writing from file to variable
Reading the variable - 1
Button pushed
Reading from the file - 50
Writing from file to variable
Reading the variable - 2
Button pushed
Reading from the file - 51
Writing from file to variable
Reading the variable - 3
Button pushed
Reading from the file - 52
Writing from file to variable
Reading the variable - 4
Button pushed
Reading from the file - 53
Writing from file to variable
Reading the variable - 5
Button pushed
Reading from the file - 54
Writing from file to variable
Reading the variable - 6
Button pushed
Reading from the file - 55
Writing from file to variable
Reading the variable - 7
Button pushed
Reading from the file - 56
Writing from file to variable
Reading the variable - 8
Button pushed
Reading from the file - 57
Writing from file to variable
Reading the variable - 9
Button pushed
Reading from the file - 49
Writing from file to variable
Reading the variable - 10
Button pushed
Reading from the file - 49
Writing from file to variable
Reading the variable - 11

So I pulled the card out, and opened on the PC. datalog.txt file has 11 in it.
After reset system is reading the file and instead of 11 displays 49. In the long variable 0 is recorded.

And here is the modified code:

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

#define SENSOR D4
#define RELAY D3
#define CS_PIN D8

long num = 0;

void setup() {
  Serial.begin (9600);
  pinMode (SENSOR, INPUT);
  pinMode (RELAY, OUTPUT);
  delay (50);
  Serial.begin(9600);
  delay (50);
  SD.begin(CS_PIN);
    File myFile = SD.open("datalog.txt");
  if (myFile) {
    Serial.println("Datalog found and opened");
    while (myFile.available()) {
      Serial.print("What's in the file - ");
      Serial.println(myFile.read());
      Serial.println("Writing from file to variable");
      num = myFile.parseInt();
      Serial.print("And in the variable - ");
      Serial.println(num);
      }
    myFile.close();
  delay(50);
  Serial.println("SYSTEM STARTED");
  }
}

void action() {
  SD.remove("datalog.txt");
  File myFile = SD.open("datalog.txt", FILE_WRITE);
  myFile.println(num);
  myFile.close();
  myFile = SD.open("datalog.txt");
  Serial.print("Reading from the file - ");
  Serial.println(myFile.read());
  Serial.println("Writing from file to variable");
  Serial.print("Reading the variable - ");
  Serial.println(num);
  myFile.close();
  delay (50);
}

void loop() {
  int L = digitalRead (SENSOR);
  if (L == 0){
    num++;
    Serial.println("Button pushed");
    action();
    }
  delay (50);
}

It looks like you’re mixing up text and binary. One is ASCII character 49.

myFile.println(num);

num is being stored as ascii characters, and when the number is >9 it takes up more than one byte memory location. If num were 12, then the first byte is ‘1’ and the second is ‘2’.

myFile.read() is returning the byte value in the first memory location. To print it as a char use Serial.println((char)myFile.read());

Wow, thank you.
Serial.println((char)myFile.read()); file content is converted from ascii and displayed.
num = (char)myFile.read(); counter variable is assigned after conversion from ascii.
myFile.println(char(num)); counter value is converted to ascii and written to the file.
This all works but the numerical limit of my counter is 256 then after ascii is converter to the number it starts from zero.
Is there a way to store data on the SD in a human digestible format instead of ascii characters? :slight_smile: And use it as a numeric value for the counter. So if my counter value is 257 then write number 257 to an SD and read 257 from an SD. I hope you understand what I mean.

Button pushed
New counter value - 52
Real value on SD - 4
Button pushed
New counter value - 53
Real value on SD - 5
Button pushed
New counter value - 54
Real value on SD - 6
Button pushed
New counter value - 55
Real value on SD - 7
Button pushed
New counter value - 56
Real value on SD - 8
Button pushed
New counter value - 57
Real value on SD - 9
Button pushed
New counter value - 58
Real value on SD - :
Button pushed
New counter value - 59
Real value on SD - ;
Button pushed
New counter value - 60
Real value on SD - <
Button pushed
New counter value - 61
Real value on SD - =

ascii is the human readable form. Your are fine saving your number with file.print(num).

You can read it back with file.parseInt().

1 Like

You are the best. Helped me a lot. Thank you very much!