Error trying to open SD file

Hi. I'm trying to use a SD memory card. I'm using the ReadWrite example and it runs well. I've copied the code and pasted at my setup() and it runs well too. Then I'm trying to make separated write / read SD memory functions by using the same code so I could call em within other functions but then it won't open the file.

At the setup() the code that works:

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

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

  myFile = SD.open("test.txt", FILE_WRITE);

  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println("testing 1, 2, 3.");
    // close the file:
    myFile.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }

  // re-open the file for reading:
  myFile = SD.open("test.txt");
  if (myFile) {
    Serial.println("test.txt:");

    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      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");
  }

The functions I'm tryin to use but that throw an error opening:

void saving_SD()  {

  myFile = SD.open("test.txt", FILE_WRITE);

  // if the file opened okay, write to it:
  if (myFile) {
    //Serial.print("Writing to test.txt...");
    myFile.println("testing 1, 2, 3.");
    // close the file:
    myFile.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
}

void reading_SD()   {

  myFile = SD.open("test.txt");
  if (myFile) {
    Serial.println("content of the file:");

    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      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");
  }
}

I'm not sure what I'm doing wrong. Please help.

Can you post the whole code that works as well as the whole code that doesn't.

Its a thousand code lines, are you sure is a good idea?

Both are in the same code. Just the one that works is within the setup() and the one that doesn't is within the named functions and are located above the setup function.

Hi again. I've taken the SD library code to a new sketch and it works well both within the setup() and as separated functions being called from the loop(). I may have russed posting here. I gotta check the large code again and I will come back with some feedback. Thanks

As per forum guidelines, if your code is big/long, then create a short program that demonstrates the issue. It's a lot easier to spot the issue on a smaller codebase and it sometimes reveals the solution to the problem.

1 Like

And as per post #4, the smaller code solved the problem :smiley:

1 Like

Hi. Thanks.

The problem has not been solved. I've tracked the issue until one single instruction that causes an error trying to open the SD file. At the setup() function, this line:

server.begin();

If I turn this line into a comment then the program can open the SD file. I honestly don't know why such incompatibility. I've traked this issue to this line since I felt that by implimenting a server using the ethernet shield could cause a conflict, so I went back to previous versions of the code before adding this server feature and the SD file opening worked fine. I don't know if this issue is related to the SPI even though I'm not including its library.

I also haven't been able to perform this instruction:

  if (SD.exists("test.txt")) { 
    SD.remove("test.txt") ;
    }

It only worked one time and then I could not get it back to delete the SD file so it won't accumulate the data when its written.

If you can't solve it, what do you think? There might be somebody that is bored out of his/her mind :wink:

Have you checked array boundaries? Extensive use of String concatenation? Direct or indirect recursive function calls?

1 Like

@alexokaban what is your hardware setup? If you are using an ethernet shield, then I seem to recall that it might use the SPI interface. If that's the case, have you got separate CS (chip select) signals for your ethernet board and SD card module?

1 Like

Thanks a lot. I can't avoid thinking that it could be confusing for those who want to help me and the least I want to do is to make it harder for them. But it seems it won't be necesary as the program is not throwing an error anymore.

Yes sir you're right. I'm using an ethernet shield. Honestly I don't understand well how the ethernet shield, the SPI and the SD card module are related or the roll of the CS (chip select) pin. I googled a little bit and I somehow was a little bit confused as well. I just copied / pasted some example code within my code and it worked well (starting, reading and writing the SC card). I checked and I'm pretty sure that the only difference btw what I was trying and this new try is this line at the setup:

  pinMode(53, OUTPUT);

BUT there is one thing I still can't manage to work and is this part:

  if (SD.exists("test.txt")) {
    SD.remove("test.txt") ;
  }

What I want to do is to delete the file before saving on it, because if I don't do so it grows and grows and affects the time count and the input reading. I just need the first lines of this file to save some configuration data.

Here the code:

#include <SD.h>

File myFile;
const int chipSelect = 4;

void saving_SD()  {

  if (SD.exists("test.txt")) {
    SD.remove("test.txt") ;
  }

  myFile = SD.open("test.txt", FILE_WRITE);

  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println("testing 1, 2, 3.");
    myFile.close();
    Serial.println("done.");
  } else {
    Serial.println("error opening test.txt");
  }
}

void reading_SD()   {

  myFile = SD.open("test.txt");
  if (myFile) {
    Serial.println("content of the file:");
    while (myFile.available()) {
      Serial.write(myFile.read());
    }
    myFile.close();
  } else {
    Serial.println("error opening test.txt");
  }
}

void setup() {
  Serial.begin(9600);
  Serial.print("Initializing SD card...");
  
  pinMode(53, OUTPUT);

  if (!SD.begin(chipSelect))
  {
    Serial.println("Card failed to initialize, or not present");
    return;
  }
  Serial.println("Card initialized.");
}

void loop() {
  saving_SD();
  reading_SD();
}

I apologize if there are any typos or weird grammar, my main language is spanish.

SPI is a serial bus. Each device is wired to the same MOSI, MISO and SCK signals. The only signal that isn't shared is SS. Each device has its own SS signal. The arduino pin that is connected to the device SS pin is usually specified when you call the .begin() function for the device.

Regarding the SD.remove(), is SD.exists() detecting the file "test.txt"? Add a print statement inside the if statement to check this:

if (SD.exists("test.txt")) {
    Serial.println(" test.txt exists. ");
    SD.remove("test.txt") ;
  }

Hi. Thanks a lot for the explanation, it makes sense now. I have a doubt, what's the difference between SS and CS?.

I also got to mention that besides adding the pinMode(53, OUTPUT) instruction; I also stopped using the PIN 4 for the program to stop showing an error when trying to open the file.

I've added the line you said and it does show that the file exists:

t⸮Initializing SD card...Card initialized.
test.txt exists.
Writing to test.txt...done.
content of the file:
testing 1, 2, 3.
testing 1, 2, 3.

It won't delete it tho and its growing and growing. Why can't it be deleted?

SS = Slave Select. It's the name of the signal that is used to select the slave device that you want to communicate with on the SPI bus.

CS = Chip Select. It's a more generic version of SS, but they both mean the same thing.

Strange that you cannot delete the file. You can create it and you can write to it which, to me, indicates that the SD adapter is wired up correctly and that you have write access to the SD card.

I looked at the source to the Arduino SD library on github and it looks like SD.remove() should return a boolean value. It might be worth printing out the value returned to see what you get.

It's a bit of a long shot given how much SD functionality works, but there is an example in the IDE Files->Examples->SD-> Files that creates and deletes files. I wonder if that works correctly for you?

1 Like

You can try if this will work to open a file; it will hopefully delete the contents and allow you to write.

  myFile = SD.open("test.txt", O_TRUNC | O_WRITE);
1 Like

Hi, thanks. Uhm it didn't work but thanks!.

Hi @markd833 thanks a lot for the help. You've been very kind by explaining me with a lot of patience. The example did work!!. And I just copied / pasted to replace some parts at the sketch that I posted above and it worked too!! I don't know what would be the difference though, just that the remove() instruction is out of the if statement, but we already had seen that the program flow would get into the if. I don't know if I'm missing other changes. This is the code that is working now:

#include <SD.h>

File myFile;
const int chipSelect = 4;

void deleting_SD()  {

  Serial.println("Removing test.txt...");
  SD.remove("test.txt");

  if (SD.exists("test.txt")) {
    Serial.println("test.txt exists.");
  } else {
    Serial.println("test.txt doesn't exist.");
  }
}

void saving_SD()  {

  Serial.println("Creating test.txt...");
  myFile = SD.open("test.txt", FILE_WRITE);

  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println("testing 1, 2, 3.");
    myFile.close();
    Serial.println("done.");
  } else {
    Serial.println("error saving test.txt");
  }
}

void reading_SD()   {

  myFile = SD.open("test.txt");
  if (myFile) {
    Serial.println("Content of the file:");
    while (myFile.available()) {
      Serial.write(myFile.read());
    }
    myFile.close();
  } else {
    Serial.println("error reading test.txt");
  }
}

void setup() {
  Serial.begin(9600);
  pinMode(53, OUTPUT);

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

  if (!SD.begin(chipSelect))
  {
    Serial.println("Card failed to initialize or not present");
    return;
  }
  Serial.println("Card initialized.");
}

void loop() {
  deleting_SD();
  saving_SD();
  reading_SD();
}

I think that the issue for which I started this topic has been solved already. I will just include this last code within the large code that runs a control system for taking care of a plant / cultive.

I have one final question why examples include SPI.h and is not even used? I didn't include it and the sketch runs well, should I include it anyway?

Alright. I tried including this sketch into the large code and it didn't work (deleting the file). Then I tried back running the sketch alone, like the same code I posted above and now it doesn't work.. it keeps concatenating the data. I'm really confused as its the same code that was working minutes ago, but after calling remove() it says that "test.txt exists". I don't know what's happening.

Scratching around now for ideas, but do you have a different SD card that you can try?

Also, in case you missed it, there's a sticky at the top of the forum about how to format SD cards for Arduino. A long shot but maybe there's something going on in the low level data structures in the card ...

I just tried with another SD card formated according to the other thread recommendation and I'm having the same issue the program cannot remove the SD file.

I've uploaded the "Files" example from the SD card section (again). This example works fine as it shows these results over the COM:

Initializing SD card...initialization done.
example.txt doesn`t exist.
Creating example.txt...
example.txt exists.
Removing example.txt...
example.txt doesn`t exist.

So it means its not a hardware or external issue. I will try not to go to too far away from the "File" example code and see what happens.

That's good news. Hopefully you can narrow down what the issue is now you have a working example.