Go Down

Topic: Can't do subsequent reads from SD card (Read 807 times) previous topic - next topic

joecatch

I am having problems trying to read from my SD card. I have the number 5.0 save in the first 3 bytes of the card. I can read the 3 bytes and convert to a float on the first pass, no problem. But I can't read from the second pass and on. I get a Can't Open File error. Here is the code. I hope it is something simple that I am missing.

Thanks.

JC


Code: [Select]


#include <SD.h>

char kwh[4];
int j;
float kwhr;

File myFile;

void setup()
{
  Serial.begin(9600);
  pinMode(10, OUTPUT);
   
  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;   }
   Serial.println("initialization done.");
}

void loop()
{
  myFile = SD.open("killog.txt", FILE_READ);
  if (myFile) {
    Serial.println("open killog.txt:");
    j = 0;
      // read from the file until there's nothing else in it:
      while (kwh[j] != '\r') {
      kwh[j] = myFile.read();
      j++;  }
     
      kwhr = atof(&kwh[0]);  //convert read string to float
      Serial.println(kwhr);
      Serial.println("Closing file"); 
      myFile.close(); }
   
      else {
  // if the file didn't open, print an error:
    Serial.println("error opening killog.txt");
   }   
}

KirAsh4

Only thing I can think of is that you're lopping through it so fast that SD itself can't keep up and fails.  Try adding a delay so it only runs every 1/4 second for example, or every second, or however long between when you close the file and when you re-open it again.
Code: [Select]

volatile long lastRun;

void setup() { ... }

void loop() {
  if (millis() - lastRun > 250) {   // run every 1/4 second
    myFile = SD.open(...);
    if (myFile) {
       ...
    } else {
       ...
    }
    lastRun = millis();
  }
}
   

joecatch

I tried the delay but it didn't help.

I replaced the WHILE with a FOR loop, letting it run 4 times and that works. The WHILE doesn't. I thought maybe I was reading beyond EOF but that doesn't seem to be the case but I am not sure. Anyway, the FOR loop with a fix count is working.

JC

el_supremo

Can you look at that file with a hex editor? I suspect that it isn't  "5.0\r" but perhaps "5.0\n\r" so that you write over the end of the kwh array.

Pete

joecatch

Pete, thanks. The file DOES have a CR/LF at the end and I will change the WHILE and try it again.

But I don't understand why it would effect the file as I am only doing a read, close and reopen. I'll let you know if it works.

JC

el_supremo

When you run over the end of the array, it might be clobbering the filename so that instead of being "killog.txt", it is "\nillog.txt" or something similar. That kind of thing is hard to predict unless you get the assembler output so that you can see which variable has been allocated space after the kwh array. Even then, the linker might change things around.

Pete

fat16lib

The problem is this while loop.  kwh[j] has not been read when you test it.  Who knows what memory is being written over.
Code: [Select]

      while (kwh[j] != '\r') {
      kwh[j] = myFile.read();
      j++;  }


Here is a loop that should work better.  Replace the above loop with this.

Code: [Select]

    do {
      // test for kwh full
      if (j == sizeof(kwh)) {
        Serial.println("line too long");
        break;
      }
      kwh[j] = myFile.read();
    } while (kwh[j++] != '\r');




joecatch

Excellent. I used that code and it worked fine.

I also tried the code given to me elsewhere here to measure SRAM because I am running out of it. Before I used your code, my available SRAM started at 404 and gradually dropped to below 200. With you code, it goes from 404 and drops to 386 and stays there. Very interesting!

Thanks!!

JC







The problem is this while loop.  kwh[j] has not been read when you test it.  Who knows what memory is being written over.
Code: [Select]

      while (kwh[j] != '\r') {
      kwh[j] = myFile.read();
      j++;  }


Here is a loop that should work better.  Replace the above loop with this.

Code: [Select]

    do {
      // test for kwh full
      if (j == sizeof(kwh)) {
        Serial.println("line too long");
        break;
      }
      kwh[j] = myFile.read();
    } while (kwh[j++] != '\r');





Go Up