SD card reader + Nokia 5110 display strange behaviour

Hello guys,

I posted half of my problem (the display flickers) at this forum post. I put a 10k pullup resistor to the CS leg of the SD card which seems to make it flicked a bit less, however...

I have a function, which reads a file and prints it to the LCD:

bool Show1(const char* FileName) {
  Serial.println("Opening file...");
  File myFile = SD.open(FileName);
  if (myFile) {
    uint8_t bmp[288];
    int i;
    uint8_t w;
    uint8_t h;
    for (i=0; i<sizeof(bmp); i++) { bmp[i] = 0; }
    myFile.read((uint8_t *)&w, sizeof(w));
    myFile.read((uint8_t *)&h, sizeof(h));
    Serial.println("Dimensions: "+String(w)+"x"+String(h));
    i = 0;
    while (myFile.available()) {
      myFile.read((uint8_t *)&bmp[i], sizeof(bmp[i]));
      Serial.print(String(bmp[i])+", ");
      if (i % 10 == 9) { Serial.println(); }
      i++;
    }
    myFile.close();
    lcd.clear(0);
    lcd.writeBitmap(bmp, 0, 0, w, h);
    lcd.renderAll();
    Serial.println();
    return true;
  } else {
    Serial.println("Failed to open file!");
    return false;
  }
}

I call this function three times:

  if (!Show1("bmp1.txt")) {
    Serial.println("Failed to show file");
  }
  delay(10000);

 
  if (!Show1("bmp2.txt")) {
    Serial.println("Failed to show file");
  }
  delay(10000);

  if (!Show1("bmp3.txt")) {
    Serial.println("Failed to show file");
  }
  delay(10000);

The first and the last picture shows, for the middle the function dies at this line:
File myFile = SD.open(FileName);

Now the strange thing. If I insert a dummy call before bmp2.txt, let's say fake.txt... as the file does not exist, fake.txt will fail but bmp2.txt will show up! The next one will fail though... which makes me think something should be wrong as I MUST have a failed call before each successful one, otherwise it won't work.

Now why it is strange? In the moment I remove the LCD display (physically or just the display part from the function) it works fine and dumps files on the serial console...

I'm going crazy here. Anyone has any ideas? :expressionless:

Not enough SRAM for your application.

    Serial.println("Dimensions: "+String(w)+"x"+String(h));

Is it really necessary to piss away resources on the String class, just to save typing ONE TIME?

4 Serial.print() statements will use less memory that that bastard.

Very good call with the free memory, I did not even think on that. However, unfortunately that does not seem to be the case here. I used the code available here to print the useable memory size:

int freeRam () {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

I ran that function several times at several points, see the output:

Initializing SD...
Free memory: 1425
Free memory at beginning of function: 1024
Opening file...
Free memory after opening file: 993
Dimensions: 18x1
126, 255, 195, 195, 255, 126, 24, 24, 24, 24,
24, 24, 120, 120, 56, 120, 120, 24,
Free memory after reading file: 993

Free memory: 1425
Free memory: 1425
Free memory at beginning of function: 1024
Opening file...
Free memory after opening file: 1024
Failed to open file!
Failed to show bmp2.txt
Free memory: 1425
Free memory: 1425
Free memory at beginning of function: 1024
Opening file...
Free memory after opening file: 1024
Failed to open file!
Failed to show bmp3.txt
Free memory: 1425

If the code (and my assumption) is correct, it means that at the worst point of my program I still have ~1000 bytes of free memory without any leaks.

As for the String class - I'm only using it while testing, my projects are - mostly - not using Serial at all.

Okay, now this drives me EXTREMELY mad... right before the SD.open I put a digitalWrite(5,HIGH) command and the whole thing started to work!!!!!!!!!!!!!!!

So I decided to remove that line... and guess what... it works.

Nothing was changed physically or in-code. Nothing. And now it works.... :o

I am thinking that Coding Badly was actually right about memory issues. I ported the working function from the test to the final application and the issue appeared again... the strange thing is that

int freeRam() {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

still says I am well equipped with memory (function returns 990).

As sad as it can get, I will need to invest into an Arduino Mega to be able to drive my small LCD and my SD reader together :frowning:

Serial.println("Failed to open file!");

...change to...

Serial.println( F( "Failed to open file!" ) );

https://www.google.com/search?q=arduino+f+macro

Sorry for the bump, and for necroing the post... I just realized I never posted the "solution" to the above.

It seems the SD card (or the library I am using, not sure) is a bit fussy about how things should be handled. I added a new function:

bool InitSD() {
  if (!card.begin(PIN_SD)) { return false; }
  if (!Fat16::init(&card)) { return false; }
  return true;
}

In case I call this function every single time before an SD card operation... it works perfectly. Not sure why I have to reinitialize the card and the file system over and over again, but I do.

So just change this:

bool Show1(const char* FileName) {
  Serial.println("Opening file...");
  File myFile = SD.open(FileName);

to:

bool Show1(const char* FileName) {
  Serial.println("Opening file...");
  InitSD();
  File myFile = SD.open(FileName);

and we are all good.

Again, I'm sorry for bumping this up. I just hate to find forum posts where a solution is available, it's just not mentioned :slight_smile:

Given this...

aehimself:
...posted the "solution"...

...an apology is never necessary.

Thank you for the follow-up.