[SOLVED] SD Card randomly stops working.

When I ran my external SD Card from an Atmega328p, I had no problem. But now that I've upgraded to an Atmega1284p, the SD Card often stops working, and won't work again until I remove power from my project, and then boot up again.

Often the problem occurs between functions; like, I might have just listened to an audio file without a hint of trouble, and then it fails when I ask for a list of more files.

I've tried switching cards, switching card holders, checked for 5 volts between the card's V5 and Gnd, added a 100 mfd cap between the card's power terminals, tested the leads to ensure they have low resistance, and shortened the leads; all without notable improvement.

Since the Atmega328p had no problem, could the native speed of the Arduino1284p's SPI be too fast for the card? Or what else could cause this problem?

How are MOSI, SCK, CS buffered, and is MISO buffered coming back?
Is the 3.3V supply hefty enough? I use a 400mA regulator with mine.

328P & 1284P have same native speed. 1284P really just has a couple more ports, 2nd hardware serial port, and more memory.

Thanks, CrossRoads. It's already a help just to know I don't need to be concerned about "native speed".

CrossRoads:
How are MOSI, SCK, CS buffered, and is MISO buffered coming back?

Below are a few lines snatched out of my 1702-line (and growing) project. The below won't run of course, but can let you see how I'm "buffering" regarding the SD Card. I'm using two 2048-byte buffers (buffA & buffB) so the software can read or write to one, while the SD Card writes or reads to the other. But I'm not sure this is what you meant by "buffering", since I don't see how it could cause the SD Card to stop working.

#include <SPI.h>
#include <SD.h>

const int NUMBER_OF_ELEMENTS = 7;
const int MAX_SIZE = 13;
char fNames [NUMBER_OF_ELEMENTS] [MAX_SIZE];
char buffA[2049];
char buffB[2049];
int buffCnt = 0;
unsigned int bCount = 0;
File myFile,dir,entry;
boolean playB = false;
boolean recordB = false;
boolean myFileDo = false;
boolean aReady;
unsigned long fSize, dSize, fRead;

void nextEntry()
{
  do
  {
    entry.close();
    entry = dir.openNextFile();
  }
  while (entry.isDirectory());
}

void listWavFiles(boolean start)
{
  if (start)
  {
    dir.close();
    entry.close();
    if (!SD.exists("/AUDIO/"))
    {
      if (!SD.mkdir("/AUDIO/"))
      {
        message("Unalbe^to open^~SD Card.^^Please^restart^~System.");
        while (true) {};
      }
    }
    dir = SD.open("/AUDIO/");
    nextEntry();
  }
  for (byte i=0; i<8; i++)
  {
    if (entry)
    {
      strcpy(fNames[i],entry.name());
      nextEntry();
    }
    else
      strcpy(fNames[i],"            ");
  }
  drawMenu(6);
}

ISR(ADC_vect)
{
   if (playB)
  {
     if(aReady)
      PORTC = buffA[buffCnt];
    else
      PORTC = buffB[buffCnt];
  }
  else if (recordB)
  {
    if(aReady)
      buffA[buffCnt]=ADCH;
    else
      buffB[buffCnt]=ADCH;
    if (bCount > 2000)
    {
      bCount = 0;
    }
    else
      bCount++;
  }
  if (buffCnt == 2047)
  {
    buffCnt = 0;
    aReady = ! aReady;
    myFileDo = true;
  }
  else
    buffCnt++;
}

void doFile()
{
  myFileDo = false;
  if (playB)
  {
    fRead += 2048;
    if (fRead > dSize)
    {
      closePlay();
    }
    else
    {
      if (aReady)
        myFile.read(buffB,2048);
      else
        myFile.read(buffA,2048);
      playClock();
     }
  }
  else if (recordB)
  {
    if (aReady)
      myFile.write(buffB,2048);
    else
      myFile.write(buffA,2048);
    recordClock();
  }
}

void setupISR()
{
  cli();//disable interrupts
  ADCSRA = 0; // clear before adding bits
  ADCSRB = 0; // clear before adding bits
  ADMUX |= (1 << MUX0); //setting input pin A7
  ADMUX |= (1 << MUX1); //setting input pin A7
  ADMUX |= (1 << MUX2); //set input pin A7
  ADMUX |= (1 << REFS0); //set reference voltage
  ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only
  bitSet(ADMUX, 6); // set bits 6, 7 for AREF of 2.56 Volts
  bitSet(ADMUX, 7); //
  ADCSRA |= (1 << ADPS1) | (1 << ADPS2); //set ADC clock
  ADCSRA |= (1 << ADATE); //enabble auto trigger
  ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete
  ADCSRA |= (1 << ADEN); //enable ADC
  ADCSRA |= (1 << ADSC); //start ADC measurements
  sei();//enable interrupts
}

void setup()
{
  // ........
  setupISR();
  // ........
}

void loop()
{
  // ........
  if (myFileDo)
    doFile();
  // ........
}

CrossRoads:
Is the 3.3V supply hefty enough? I use a 400mA regulator with mine.

This is the SD Card holder I'm using:

It has both a 5v and a 3v power pin, but I'm only supplying power to the 5v pin, letting the onboard 3V regulator do it's job. My 5V source is the project's USB port connection.

Well, I have not found a real answer; the SD Card still drops out randomly. But I spent the day developing and testing code to deal with it, which I've shared below:

  1. After initializing the card, Setup() makes sure there is a directory named "/AUDIO/" for later verifying the presence of the SD Card.

  2. Every function in my sketch that uses the SD Card, calls hasSD() first to be sure the card is working.

  3. To do this, it first checks for the directory "/AUDIO/". If not found, it assumes the card has stopped working, and restarts it by calling SD.begin(SS).

  4. If the "/AUDIO/" directory still cannot be found, it assumes the SD Card has been removed, and asks the user to reinsert the card. (Maybe they've now inserted a different card that really does not have the "/AUDIO/" directory. But if so, rebooting the project will remedy that situation.)

  5. Pressing any of the three control buttons will attempt to continue executing whatever function has called hasSD(). If the card is still not there, the same request for the card is repeated instead.

  6. notTouched() is my "press any key to continue" function, used elsewhere in my script as well.

This is my patch for now... But I'm still hoping for more info about what kind of additional "buffering" might be needed, and how "buffering" could be a problem causing the card to stop working (as told to me in post #1 above). And, of course I'll be watching to see if anyone comes up with a better answer.

#include <SPI.h>
#include <SD.h>

const byte up = 0;
const byte select = 1;
const byte dn = 2;

void setup()
{
  SPI.begin();
 if (SD.begin(SS))
    SD.mkdir("/AUDIO/");
  else
  {
    message("Please insert^an^~SD Card.^^Then restart^~DreamMaster");
    while (true) {};
  }
}

boolean notTouched()
{
  return digitalRead(up) && digitalRead(dn) && digitalRead(select);
}

void hasSD()
{
  if (!SD.exists("/AUDIO/"))
    SD.begin(SS);
  while (!SD.exists("/AUDIO/"))
  {
    message("Please insert^an^~SD Card^and^~Try Again.");
    while (notTouched()) {};
    SD.begin(SS);
  }
}

void loop()
{
}

I was only considering hardware buffers, like cd74hc4050 to get CS, SCK, MOSI from 5V levels to 3.3V, and 74hc125 to buffer MISO coming back to the uC.
I've never actually written software to use the SD code, just built them and ran other's code, like fat16lib's test codes or Nick Gammon's Standalone Programmer code. Proper hardware buffering has never prevented code from running.
I don't think that module has any buffering, and the way the resistors are used is questionable.

Hey CrossRoads! Once again, you're a really big help. I didn't know about "hardware buffering", until now.

CrossRoads:
I don't think that module has any buffering, and the way the resistors are used is questionable.

And you're right; my module (shown in post #2 above) uses only resistors with no buffering. Here's the schematic:

And even breakouts that have onboard buffering like this one, tend to not buffer the MISO line, as you can see in the schematic below. Why is that? Doesn't the MISO line need buffering to, to raise it to the VAR's expected 5 volts?

Most of the good SD Card holders seem so pricey, usually $15 to $20. I'd like to buy this one from AdaFruit for $14.95. Shown here:

The price would be fine if only for my own experimentation; but when my project becomes a product, $14.95 would eat too deeply into my profit, repeated on every sale. The parts don't cost much, less than $4.00 total. So instead of the one from AdaFruit, i've ordered a few of the one shown below for $2.75 each:

from DealExtreme and am keeping my fingers crossed. It clearly has the needed buffer chip, though I coundn't find a schematic. It accepts only the smaller card, the MicroSD card, but I can make that work.

I'm still wondering if you have a better solution in mind to be part of my final product's board?

The Catalex micro sd shield you have chosen is low cost, has the logic level shifters. and works well when used alone on the SPI bus. It is superior to the LC studio card.

There was a problem with some earlier versions and multiple devices on the spi bus in that it did not release MISO when chip select is high. Catalex MicroSD Card Adapter do I need to level shift - #4 by fat16lib - Storage - Arduino Forum

If you are thinking of this for production, you might want to verify this.

I have also seen reference to a work around which put a 2K2Ω resistor between MISO on the MicroSD card and MISO on the Arduino, but I don't know enough about the spi bus or the hardware to know if this is credible.

Thanks, cattledog. The SPI bus also operates the LCD display and the RF receiver. So I'll definitely check for the MISO problem!

I can see why the 2K2Ω resistor could work, passing enough signal when needed, and blocking enough signal when not. But the extra drag from the current it passes (and capacitance from semi-isolation) might return me to the intermittency problems I'm trying to escape!

Very glad to know all you said, cattledog. keeping fingers crossed

Cosmic Gold
I have just upgraded to a 1284p board and have started to encounter SPI OLED and SD card issues not disimilar to your experience. I developed some code on an old Adafruit UNO with full size SD Card shield without problem but when I ran it on the 1284 board it worked for while then didn't. On the 1284 I was using a Catalex SDcard shield. I tried two of them, same intermittant results. I then had a problem with a card and suspect it was fake so I changed it. Still intermittant. I then hard wired a Microduino (Which I know works with a ATmega 644) SD shield and it ran like dream. I intend to throw the cheap, but not cheerful SD shields in the bin, and buy Adafruit SD shields despite their high relative price. The few cheap SD cards I have will be going the same way.
I will watch this space.

You're post was a pleasant surprise. It was a surprise because after two weeks of silence, I was just a minute ago thinking of posting here about the SD again. Then you beat me to it.

I assume you must have chosen this SD Card reader for $8.00? It looks like a really good one, classy even. (Pictured below)

Note the chip labeled "Level Shifter 5V -> 3V3" in the image above; I think that is the answer. Your old SD probably had resistors trying to do that job instead of a digital chip, just as mine had. I believe we had EXACTLY the same problems for exactly the same reason, after upgrading to the (mostly wonderful) Atmega1284p AVR. My replacement SD -- described in post #5 above -- hasn't arrived yet. Lets hope I have the good luck with the new voltage shifter that you are having with yours.

It's strange how intermittent the old SD can be. I can go a whole day working with the old SD and not have a problem; then the next day it starts failing. When it does, repeating

b = SD.begin(SS);

does nothing, removing and re-inserting the SD card does nothing, rebooting the AVR does nothing. But unplug the power a second and power it up again, and it takes off like nothing was ever wrong. What does that narrow the problem down to? Well, doesn't really matter if the new SD reader works flawlessly. Hope it arrives soon.

And I'm very glad your answer is working perfectly for you. :wink:

I received my new two-dollar SD Card reader today from DealExtreme, as I described above (with the onboard level-shifter chip). So I installed it right away.

However the new reader failed most of the time!

Fortunately, I could hear strange tones in my speaker when touching the card reader and realized this meant I had parasitic feedback oscillations occurring between the reader and other components.

To remedy the oscillations problem, I put a 0.1mfd capacitor across the power leads (ground and 5V) directly at the base of the card reader, and then added a ferrite bead to it's positive power lead. After that, the oscillations were gone, and the card reader/writer has been working perfectly ever since. :slight_smile:

I had a problem with an SD card in a project, writing unreliable and garbage getting written to the card. Read/write code was identical to a previous project but I was using a Mega 2560 in place of a Nano. After much tinkering with the code, and even a very simple example not working, and replacing the SD card interface, I traced the problem to the ground connection, which was wired back to a LM2596 power supply module via an OLED display. Rewiring the ground direct to the Arduino solved the problem.