Sd Card (MMC) initialization error

Hello everyone

I am somewhat new with arduino so excuse any ignorance I might display.

I am trying to interface with an SD card.
Its an old MMC card, 32MB. I also tried with microSD (4GB) card and an SD adaptor but no luck.
My setup is arduino duemilanove, atmega328p.
I am using this scematic http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1206874649.
I try to run the SDinfo example from the Sdfatlib. It fails to initialize both cards displaying this message:

card.init failed
SD errorCode: 0X1
SD errorData: 0X0

After playing around a little, I noticed that if I remove the wire connected to the CS pin of the card at the begining of the initialization
(not too soon, nor too late), then the card is recognized.

I am pretty sure my wiring is correct (although I might be wrong)
I have " const uint8_t SdChipSelect = 10; " and i have CS pin of the SDcard connected to pin 10.
I am powering the card from the 3.3v suply on the arduino

Does anyone have a suggestion? I am sure I am doing something stupid but I have no idea what.

Thanks!

[Edit: The cards both work on my pc]

I have " const uint8_t SdChipSelect = 10; " and i have CS pin of the SDcard connected to pin 10.

Well, that's two of three things you need to do. You also need to set the pin value correctly.

I am sure I am doing something stupid but I have no idea what.

Oooh, oooh. I know. You're not posting any code. That's easy to correct, though.

Well, that's two of three things you need to do. You also need to set the pin value correctly.

Do you mean set pin 10 to Output? If yes then I think the library is taking care of that during initialization

The code of the SDinfo is

/*
 * This sketch attempts to initialize an SD card and analyze its structure.
 */
#include <SdFat.h>
/*
 * SD chip select pin.  Common values are:
 *
 * Arduino Ethernet shield, pin 4.
 * SparkFun SD shield, pin 8.
 * Adafruit SD shields and modules, pin 10.
 * Default SD chip select is the SPI SS pin.
 */
const uint8_t SdChipSelect = SS_PIN;

Sd2Card card;
SdVolume vol;

// serial output steam
ArduinoOutStream cout(Serial);

// global for card erase size
uint32_t eraseSize;
//------------------------------------------------------------------------------
// store error strings in flash
#define sdErrorMsg(msg) sdErrorMsg_P(PSTR(msg));
void sdErrorMsg_P(const char* str) {
  cout << pgm(str) << endl;
  if (card.errorCode()) {
    cout << pstr("SD errorCode: ");
    cout << hex << int(card.errorCode()) << endl;
    cout << pstr("SD errorData: ");
    cout << int(card.errorData()) << dec << endl;
  }
}
//------------------------------------------------------------------------------
uint8_t cidDmp() {
  cid_t cid;
  if (!card.readCID(&cid)) {
    sdErrorMsg("readCID failed");
    return false;
  }
  cout << pstr("\nManufacturer ID: ");
  cout << hex << int(cid.mid) << dec << endl;
  cout << pstr("OEM ID: ") << cid.oid[0] << cid.oid[1] << endl;
  cout << pstr("Product: ");
  for (uint8_t i = 0; i < 5; i++) {
    cout << cid.pnm[i];
  }
  cout << pstr("\nVersion: ");
  cout << int(cid.prv_n) << '.' << int(cid.prv_m) << endl;
  cout << pstr("Serial number: ") << cid.psn << endl;
  cout << pstr("Manufacturing date: ");
  cout << int(cid.mdt_month) << '/';
  cout << (2000 + cid.mdt_year_low + 10 * cid.mdt_year_high) << endl;
  cout << endl;
  return true;
}
//------------------------------------------------------------------------------
uint8_t csdDmp() {
  csd_t csd;
  uint8_t eraseSingleBlock;
  uint32_t cardSize = card.cardSize();
  if (cardSize == 0 || !card.readCSD(&csd)) {
    sdErrorMsg("readCSD failed");
    return false;
  }
  if (csd.v1.csd_ver == 0) {
    eraseSingleBlock = csd.v1.erase_blk_en;
    eraseSize = (csd.v1.sector_size_high << 1) | csd.v1.sector_size_low;
  } else if (csd.v2.csd_ver == 1) {
    eraseSingleBlock = csd.v2.erase_blk_en;
    eraseSize = (csd.v2.sector_size_high << 1) | csd.v2.sector_size_low;
  } else {
    cout << pstr("csd version error\n");
    return false;
  }
  eraseSize++;
  cout << pstr("cardSize: ") << cardSize << pstr(" (512 byte blocks)\n");
  cout << pstr("flashEraseSize: ") << int(eraseSize) << pstr(" blocks\n");
  cout << pstr("eraseSingleBlock: ");
  if (eraseSingleBlock) {
    cout << pstr("true\n");
  } else {
    cout << pstr("false\n");
  }
  return true;
}
//------------------------------------------------------------------------------
// print partition table
uint8_t partDmp() {
  cache_t *p = vol.cacheClear();
  if (!card.readBlock(0, p->data)) {
      sdErrorMsg("read MBR failed");
      return false;
  }
  cout << pstr("\nSD Partition Table\n");
  cout << pstr("part,boot,type,start,length\n");
  for (uint8_t ip = 1; ip < 5; ip++) {
    part_t *pt = &p->mbr.part[ip - 1];
    cout << int(ip) << ',' << hex << int(pt->boot) << ',' << int(pt->type);
    cout << dec << ',' << pt->firstSector <<',' << pt->totalSectors << endl;
  }
  return true;
}
//------------------------------------------------------------------------------
void volDmp() {
  cout << pstr("\nVolume is FAT") << int(vol.fatType()) << endl;
  cout << pstr("blocksPerCluster: ") << int(vol.blocksPerCluster()) << endl;
  cout << pstr("clusterCount: ") << vol.clusterCount() << endl;
  cout << pstr("freeClusters: ") << vol.freeClusterCount() << endl;
  cout << pstr("fatStartBlock: ") << vol.fatStartBlock() << endl;
  cout << pstr("fatCount: ") << int(vol.fatCount()) << endl;
  cout << pstr("blocksPerFat: ") << vol.blocksPerFat() << endl;
  cout << pstr("rootDirStart: ") << vol.rootDirStart() << endl;
  cout << pstr("dataStartBlock: ") << vol.dataStartBlock() << endl;
  if (vol.dataStartBlock() % eraseSize) {
    cout << pstr("Data area is not aligned on flash erase boundaries!\n");
    cout << pstr("Download and use formatter from www.sdcard.org/consumer!\n");
  }
}
//------------------------------------------------------------------------------
void setup() {
  Serial.begin(9600);

  // use uppercase in hex and use 0X base prefix
  cout << uppercase << showbase << endl;
  
  // pstr stores strings in flash to save RAM
  cout << pstr("SdFat version: ") << SD_FAT_VERSION << endl;
}
//------------------------------------------------------------------------------
void loop() {
  // read any existing Serial data
  while (Serial.read() >= 0) {}
  
  // pstr stores strings in flash to save RAM
  cout << pstr("\ntype any character to start\n");
  while (Serial.read() < 0) {}

  uint32_t t = millis();
  // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
  // breadboards.  use SPI_FULL_SPEED for better performance.
  if (!card.init(SPI_HALF_SPEED, SdChipSelect)) {
    sdErrorMsg("\ncard.init failed");
    return;
  }
  t = millis() - t;
  cout << pstr("\ninit time: ") << t << " ms" << endl;
  cout << pstr("\nCard type: ");
  switch (card.type()) {
    case SD_CARD_TYPE_SD1:
      cout << pstr("SD1\n");
      break;

    case SD_CARD_TYPE_SD2:
      cout << pstr("SD2\n");
      break;

    case SD_CARD_TYPE_SDHC:
      cout << pstr("SDHC\n");
      break;

    default:
      cout << pstr("Unknown\n");
  }
  if (!cidDmp()) return;
  if (!csdDmp()) return;
  if (!partDmp()) return;
  if (!vol.init(&card)) {
    sdErrorMsg("\nvol.init failed");
    return;
  }
  volDmp();
}

Do you mean set pin 10 to Output?

No, I mean use digitalWrite() and set it HIGH or LOW as required.

The code of the SDinfo is

It would be better if you posted the minimum code that illustrates the problem. If 40 functions are not called because of an error early on, posting those 40 functions is a waste of time - yours and ours.

No, I mean use digitalWrite() and set it HIGH or LOW as required.

I believe that is also taken care of by the library

This is the function called by the program during initialization as per your request. If everything was funtional it should return true

/**
 * Initialize an SD flash memory card.
 *
 * \param[in] sckRateID SPI clock rate selector. See setSckRate().
 * \param[in] chipSelectPin SD chip select pin number.
 *
 * \return The value one, true, is returned for success and
 * the value zero, false, is returned for failure.  The reason for failure
 * can be determined by calling errorCode() and errorData().
 */
bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
  errorCode_ = type_ = 0;
  chipSelectPin_ = chipSelectPin;
  // 16-bit init start time allows over a minute
  uint16_t t0 = (uint16_t)millis();
  uint32_t arg;

  // set pin modes
  pinMode(chipSelectPin_, OUTPUT);
  chipSelectHigh();
  pinMode(SPI_MISO_PIN, INPUT);
  pinMode(SPI_MOSI_PIN, OUTPUT);
  pinMode(SPI_SCK_PIN, OUTPUT);

#ifndef SOFTWARE_SPI
  // SS must be in output mode even it is not chip select
  pinMode(SS_PIN, OUTPUT);
  // set SS high - may be chip select for another SPI device
#if SET_SPI_SS_HIGH
  digitalWrite(SS_PIN, HIGH);
#endif  // SET_SPI_SS_HIGH
  // set SCK rate for initialization commands
  spiRate_ = SPI_SD_INIT_RATE;
  spiInit(spiRate_);
#endif  // SOFTWARE_SPI

  // must supply min of 74 clock cycles with CS high.
 
 for (uint8_t i = 0; i < 10; i++) spiSend(0XFF);

  // command to go idle in SPI mode
  while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) {
    if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
      error(SD_CARD_ERROR_CMD0);
      goto fail;
    }
  }
  // check SD version
  if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) {
    type(SD_CARD_TYPE_SD1);
  } else {
    // only need last byte of r7 response
    for (uint8_t i = 0; i < 4; i++) status_ = spiRec();
    if (status_ != 0XAA) {
      error(SD_CARD_ERROR_CMD8);
      goto fail;
    }
    type(SD_CARD_TYPE_SD2);
  }
  // initialize card and send host supports SDHC if SD2
  arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0;

  while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) {
    // check for timeout
    if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
      error(SD_CARD_ERROR_ACMD41);
      goto fail;
    }
  }
  // if SD2 read OCR register to check for SDHC card
  if (type() == SD_CARD_TYPE_SD2) {
    if (cardCommand(CMD58, 0)) {
      error(SD_CARD_ERROR_CMD58);
      goto fail;
    }
    if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC);
    // discard rest of ocr - contains allowed voltage range
    for (uint8_t i = 0; i < 3; i++) spiRec();
  }
  chipSelectHigh();

#ifndef SOFTWARE_SPI
  return setSckRate(sckRateID);
#else  // SOFTWARE_SPI
  return true;
#endif  // SOFTWARE_SPI

 fail:
  chipSelectHigh();
  return false;
}

I am sure I am doing something stupid but I have no idea what.

Oooh, oooh. I know. You're not posting any code. That's easy to correct, though.

It would be better if you posted the minimum code that illustrates the problem. If 40 functions are not called because of an error early on, posting those 40 functions is a waste of time - yours and ours.

Mmmm, I should say that you come of a little rude and patronizing, and that I am new to both arduino and to this forums and some mistakes and omissions are to be expected. But I am probably wrong and you are being perfectly polite. So I will chalk it up to my poor understanding of english.

SdFat and the Arduino wrapper library, SD.h, do not support MMC cards.

Thank you for the information. I will try to find an SD card. Is there a library that does support MMC?

I thought MMC and microSD were basically compatible? Anyway it clearly sometimes inits.

I think it might be worth pulling up the CS pin to 3V3 with a resistor and using a 1N4148 diode between it and the Arduino so that the Arduino can only pull it down to 0V.

That way the CS will be HIGH (inactive) by default at power-up. At the moment with the resistor divider the circuit powers up with CS active until the Arduino does the approriate setup. Just a hunch

No MMC cards will init with SdFat. I check for the SD card type and MMC cards fail the test.

Hello Everyone,

Recently I was trying to use SD library and I found the following observations.

  1. I tried three different micro sd cards: Sony 8GB, SanDisk 2GB and Nokia (as printed) 512MB
  2. All three micro sd cards are working with Sony SD Adapter.
  3. But not with other two sd adapters.

I used QuickStart Example code from sdfat library on greiman (greiman) / Repositories · GitHub.

I am using a Nanode board so the Disabling SPI device is on pin 8.

Serial output is as follows.

SPI pins:
MOSI: 11
MISO: 12
SCK: 13

SD chip select is the key hardware option.
Common values are:
Arduino Ethernet shield, pin 4
Sparkfun SD shield, pin 8
Adafruit SD shields and modules, pin 10

Enter the chip select pin number: 4

Disabling SPI device on pin 8

SD initialization failed.
Do not reformat the card!
Is the card correctly inserted?
Is chipSelect set to the correct value?
Does another SPI device need to be disabled?
Is there a wiring/soldering problem?
errorCode: 0x1, errorData: 0x0

Restarting

Enter the chip select pin number: 4

Disabling SPI device on pin 8

SD initialization failed.
Do not reformat the card!
Is the card correctly inserted?
Is chipSelect set to the correct value?
Does another SPI device need to be disabled?
Is there a wiring/soldering problem?
errorCode: 0x1, errorData: 0x0

Restarting

Enter the chip select pin number: 4

Disabling SPI device on pin 8

Card successfully initialized.

Card size: 507 MB (MB = 1,000,000 bytes)

Volume is FAT16, Cluster size (bytes): 16384

Files found (name date time size):

Success! Type any character to restart.

I hope that this info will help someone who is facing the same issue.

gparali:
Mmmm, I should say that you come of a little rude and patronizing, and that I am new to both arduino and to this forums and some mistakes and omissions are to be expected. But I am probably wrong and you are being perfectly polite. So I will chalk it up to my poor understanding of english.

No, it is not your understanding of English, you understood just fine, patronizing and rude is common to us noobs that make the mistake of asking noob questions. Your mistake was thinking you were in the right place to ask noob questions.

Regards,

Graham