0

I am working on an Arduino application that logs sensors values into SD files. It is essential that the SD is inserted and working when a test is started, thus I need to check the presence of the SD regularly (every 2 seconds or so) to prevent launching a test without SD inserted by the user.

When I run the following code, it runs very fast when the SD test succeeds (<10ms), but it takes more than 2000ms when the test fails. Is there another test I could run that does not takes 2 seconds to indicate that the SD is not inserted (or not working)? All my buttons are frozen and they do not trigger any action while checking if no SD is inserted.

Here is my code (both loops have the same issue):

#define csSD   53
#include <SD.h>

Sd2Card card;

void setup() {
  Serial.begin(57600);
  bool SDOK = SD.begin(csSD);
  if(SDOK) {
    Serial.println("SD.Begin Setup OK");
  } else {
    Serial.println("SD.Begin Setup Fail");
  }
}

unsigned long t;
//void loop() {
//  t=millis();
//  if(SD.begin(csSD)){ // SD.Begin test runs fast when there is a SD, even though it return true when you try to begin SD a second time
//    Serial.print("SD.Begin loop OK : ");
//  }else {
//    Serial.print("SD.Begin loop Fail : ");
//  }
//  Serial.println(String(millis()-t)+"ms");
//  delay(500);
//}

void loop() {
  t=millis();
  if(card.init(SPI_HALF_SPEED, csSD)) {
    // card.init test returns true as it should (when SD is present and working), but runs fast only when SD is working
    Serial.print("card.init loop OK : ");
  } else {
    Serial.print("SD.Begin loop Fail : ");
  }
  Serial.println(String(millis()-t)+"ms");
  delay(500);
}
dda
  • 1,595
  • 1
  • 12
  • 17
Etienne P.
  • 53
  • 4

2 Answers2

1

The SD library builds on the sdfatlib library, in which SD_INIT_TIMEOUT is defined as 2000 ms, which gives your 2 second timeout. You could try lowering that number to get a faster response, although that may run the risk of timing out even when a card is present.

Four different timeout periods are defined in the sdfatlib source:

/** init timeout ms */
uint16_t const SD_INIT_TIMEOUT = 2000;
/** erase timeout ms */
uint16_t const SD_ERASE_TIMEOUT = 10000;
/** read timeout ms */
uint16_t const SD_READ_TIMEOUT = 300;
/** write time out ms */
uint16_t const SD_WRITE_TIMEOUT = 600;

The 300 ms read timeout is faster, as @Paul suggests in his comment, so you could just use a card read as the test rather than an initialisation, or try setting the init timeout to 300 instead. A read test would be simpler, as it doesn't involve modifying library files. It might not cope with a re-inserted card, though - I suspect that requires reinitialisation each time.

Note: the version of sdfatlib included with the SDlib in my Arduino install appears rather older than the current version. The included version defines the timeouts in Sd2Card.h, while the latest has is in SdInfo.h. The snippet above is from the older, included code.

AndyW
  • 111
  • 4
0

You could always try this very simple sketch. I have never measured how quick it runs, but it is pretty quick.

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

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

Just make sure to change 4 in !SD.begin(4) to whatever your ChipSelect pin happens to be for your component.

Furthermore, you could add a return statement after your "initilization fails" loop because that will immediately stop the program, after all you do not want to run it if the SD card is not reading data! And last thing, it may be a little overkill to check the SD card after initial initilization, after all, it will be highly unlikely for an error to occur once everything is working fine unless you mess with the SD card alot while it is running, which I am sure you won't.

tyler a
  • 73
  • 3
  • 12