Pages: [1]   Go Down
Author Topic: Can't do subsequent reads from SD card  (Read 730 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 37
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

#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");
   }   
}
Logged

Colorado
Offline Offline
Edison Member
*
Karma: 47
Posts: 1562
Reviving dead brain cells with Arduinos.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
volatile long lastRun;

void setup() { ... }

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

Offline Offline
Newbie
*
Karma: 0
Posts: 37
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Offline Offline
Edison Member
*
Karma: 48
Posts: 1632
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 37
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Offline Offline
Edison Member
*
Karma: 48
Posts: 1632
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

0
Offline Offline
Edison Member
*
Karma: 64
Posts: 1638
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
      while (kwh[j] != '\r') {
      kwh[j] = myFile.read();
      j++;  }

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

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


Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 37
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
      while (kwh[j] != '\r') {
      kwh[j] = myFile.read();
      j++;  }

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

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



Logged

Pages: [1]   Go Up
Jump to: