Problème lecteur carte SD sur Mega 2560 encore et encore ...

Bonsoir à tous,

J'ai tout lu et son contraire sur la connexion d'un module carte SD (je ne parle pas d'un shield) sur un Mega 2560. J'ai fini par cette configuration de câblage, basée sur le Pinout officiel du Mega 2560 :

Fonction

MISO 50 SCK 52 MOSI 51 CS 4

J'ai testé 2 modules : 1 en Micro SD avec cartes SDHC 4Go et 16Go 1 en SD normal avec vieille carte SD 512Mo toutes formatées en FAT32

J'ai uploadé le code suivant : (voir post suivant, car en Quick Edit, je ne trouve pas les balises...)

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

void setup() {
  Serial.begin(9600);
  pinMode(53,OUTPUT);
  pinMode(4,OUTPUT);
  digitalWrite(4,LOW);
  
 if (!SD.begin(4)) {
    Serial.println("Erreur de demarrage!");
    return;
  }
  Serial.println("Carte SD prête.");
}

void loop() {

}

Je reçois bien entendu systématiquement Erreur de démarrage"…
Une idée ?

et c’est alimenté comment? avez vous joint les GND des 2 cartes ?

sur une mega le SS slave est 53, pourquoi ne pas l’utiliser directement et virer de votre code

  pinMode(53,OUTPUT);
  pinMode(4,OUTPUT);
  digitalWrite(4,LOW);

et juste faire un

 if (!SD.begin()) {
    Serial.println("Erreur de demarrage!");
    return;
  }

de manière générale il vaut mieux utiliser la librairie SdFat qui est plus à jour

J-M-L: de manière générale il vaut mieux utiliser la librairie SdFat qui est plus à jour

Bonjour et je m' excuse pour le HS ...

Pourquoi les bibliotheques plus evoluées et donc plus a meme de supporter les nouveaux materiels et qui je suppose restent retro compatible ne sont pas directement integrées dans l ' IDE ( comme les standards ) ? ( dans le ca present SD.h )

bonne question :slight_smile:

l’environnement étant ouvert il y a de nombreux amateurs qui développent des librairies.

La librairie SD de l’IDE est celle qui vient de l’auteur de SdFat, ils le disent au début

The SD library allows for reading from and writing to SD cards, e.g. on the Arduino Ethernet Shield. It is built on sdfatlib by William Greiman

et comme il l’améliore de manière non synchronisé avec l’IDE, vaut mieux directement aller prendre sa librairie SdFat la plus à jour à mon sens

Quand vous la téléchargez, vous verrez dans le répertoire extras un fichier SdFat.html, ouvrez le dans votre navigateur web pour voir toute la doc

Voici un exemple de code qui liste les fichiers et répertoires contenus sur la carte SD

/*
  Listfiles

  This example shows how print out the files in a
  directory on a SD card

  The circuit:
   SD card attached to SPI bus as follows:
 ** MOSI - pin 11 on UNO
 ** MISO - pin 12 on UNO
 ** CLK  - pin 13 on UNO
 ** CS   - pin 10 on UNO

   SD card attached to SPI bus as follows:
 ** MOSI - pin 51 on MEGA
 ** MISO - pin 50 on MEGA
 ** CLK  - pin 52 on MEGA
 ** CS   - pin 53 on MEGA
 * 
 * POWER of course and GROUND needs to be joined
*/

#include <SPI.h>
#include "SdFat.h"
// SD card chip select pin.
const uint8_t SD_CHIP_SELECT = SS;
SdFat sd;

// fonction récursive
void afficherContenuRepertoire(FatFile* repertoire, byte tabulation)
{
  FatFile file;
  char nomDeFichier[20]; // prévoir au moins 13 charactères

  repertoire->rewind(); // on se met en début de répertoire

  while (file.openNext(repertoire, O_READ)) { // on parcourt le répertoire en cours

    if (!file.isHidden()) { // si ce n'est pas un élément caché on l'affiche

      file.getName(nomDeFichier, sizeof(nomDeFichier)); // on récupère le nom de fichier

      // on décalle l'affichage en fonction de la profondeur de répertoires
      for (uint8_t i = 0; i < tabulation; i++) Serial.print(F("\t"));

      //et on affiche le nom en cours
      Serial.print(nomDeFichier);

      // si c'est un répertoire, on appele récursivement la même fonctoin
      if (file.isDir()) {
        Serial.println(F("/")); // comme c'est un répertoire on met un / au bout du nom et on passe à la ligne
        afficherContenuRepertoire(&file, tabulation + 1); //on affiche le contenu de ce répertoire
      } else {
        // ce n'était pas un répertoire, on affiche la taille du fichier
        Serial.print("\t"); Serial.print (file.fileSize()); Serial.println(F(" octets"));
      }
    } // fin de si élément caché
    file.close();
  } // fin de while
}

//-------------------------------------------------------

void setup() {
  Serial.begin(115200);
  if (!sd.begin(SD_CHIP_SELECT, SPI_HALF_SPEED)) {
    Serial.println(F("erreur de begin\n"));
    return;
  }

  // on se met à la racine
  sd.chdir("/");

  // on afficher récurcivement depuis la racine
  afficherContenuRepertoire(sd.vwd(), 0);
}


//-------------------------------------------------------
void loop() {}

Merci à tous pour vos éclairages qui m’ont permis de progresser.
Je reste cependant perplexe devant les différences de résultat d’un simple test d’affichage de type de carte et de nature de formatage :
Voici un sketch basé sur la librairie SD.h avec mes commentaires d’avancement :

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

Sd2Card card;
SdVolume volume;
SdFile root;

const int chipSelect = 53;

void setup() {

 Serial.begin(9600);
 while (!Serial) {
   ; }

 Serial.print("\nInitializing SD card...");

 if (!card.init(SPI_HALF_SPEED, chipSelect)) {
   Serial.println("initialization failed. Things to check:");
   Serial.println("* is a card inserted?");
   Serial.println("* is your wiring correct?");
   Serial.println("* did you change the chipSelect pin to match your shield or module?");
   return;
 } else {
   Serial.println("Wiring is correct and a card is present.");
 }// C'est mon cas, j'arrive à cette confirmation de câblage correct et de carte trouvée

 // print the type of card
 Serial.print("\nCard type: ");
 switch (card.type()) {
   case SD_CARD_TYPE_SD1:
     Serial.println("SD1"); // la carte est bien reconnue en SD1
     break;
   case SD_CARD_TYPE_SD2:
     Serial.println("SD2");
     break;
   case SD_CARD_TYPE_SDHC:
     Serial.println("SDHC");
     break;
   default:
     Serial.println("Unknown");
 }

 if (!volume.init(card)) {
   Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
   return;
 } // j'obtiens ce message, alors que ma carte SD 256Mo est formatée en FAT16
   // avec SD Card Formatter

 uint32_t volumesize;
 Serial.print("\nVolume type is FAT");
 Serial.println(volume.fatType(), DEC);
 Serial.println();

 volumesize = volume.blocksPerCluster();   
 volumesize *= volume.clusterCount();      
 volumesize *= 512;                         
 Serial.print("Volume size (bytes): ");
 Serial.println(volumesize);
 Serial.print("Volume size (Kbytes): ");
 volumesize /= 1024;
 Serial.println(volumesize);
 Serial.print("Volume size (Mbytes): ");
 volumesize /= 1024;
 Serial.println(volumesize);


 Serial.println("\nFiles found on the card (name, date and size in bytes): ");
 root.openRoot(volume);

 root.ls(LS_R | LS_DATE | LS_SIZE);
}


void loop(void) {

}

Voici ce que j’obtiens sur le moniteur série :

Initializing SD card...Wiring is correct and a card is present.

Card type: SD1
Could not find FAT16/FAT32 partition.
Make sure you've formatted the card

Voici maintenant un autre sketch basé sur la librairie SDFat.h “QuickStart” dans les exemples :

/ Quick hardware test for SPI card access.
//
#include <SPI.h>
#include "SdFat.h"
//
// Test with reduced SPI speed for breadboards.  SD_SCK_MHZ(4) will select 
// the highest speed supported by the board that is not over 4 MHz.
// Change SPI_SPEED to SD_SCK_MHZ(50) for best performance.
#define SPI_SPEED SD_SCK_MHZ(4)
//------------------------------------------
// File system object.
SdFat sd;

// Serial streams
ArduinoOutStream cout(Serial);

// input buffer for line
char cinBuf[40];
ArduinoInStream cin(Serial, cinBuf, sizeof(cinBuf));

// SD card chip select
int chipSelect;

void cardOrSpeed() {
  cout << F("Try another SD card or reduce the SPI bus speed.\n");
  cout << F("Edit SPI_SPEED in this program to change it.\n");
}

void reformatMsg() {
  cout << F("Try reformatting the card.  For best results use\n");
  cout << F("the SdFormatter program in SdFat/examples or download\n");
  cout << F("and use SDFormatter from www.sdcard.org/downloads.\n");
}

void setup() {
  Serial.begin(9600);
  //pinMode(10,OUTPUT);
  //digitalWrite(10,HIGH);
  
  // Wait for USB Serial 
  while (!Serial) {
    SysCall::yield();
  }
  cout << F("\nSPI pins:\n");
  cout << F("MISO: ") << int(MISO) << endl;
  cout << F("MOSI: ") << int(MOSI) << endl;
  cout << F("SCK:  ") << int(SCK) << endl;
  cout << F("SS:   ") << int(SS) << endl;

  if (DISABLE_CHIP_SELECT < 0) {
    cout << F(
           "\nBe sure to edit DISABLE_CHIP_SELECT if you have\n"
           "a second SPI device.  For example, with the Ethernet\n"
           "shield, DISABLE_CHIP_SELECT should be set to 10\n"
           "to disable the Ethernet controller.\n");
  }
  cout << F(
         "\nSD chip select is the key hardware option.\n"
         "Common values are:\n"
         "Arduino Ethernet shield, pin 4\n"
         "Sparkfun SD shield, pin 8\n"
         "Adafruit SD shields and modules, pin 10\n");
}

bool firstTry = true;
void loop() {
  // Read any existing Serial data.
  do {
    delay(10);
  } while (Serial.available() && Serial.read() >= 0);

  if (!firstTry) {
    cout << F("\nRestarting\n");
  }
  firstTry = false;

  cout << F("\nEnter the chip select pin number: ");
  while (!Serial.available()) {
    SysCall::yield();
  }
  cin.readline();
  if (cin >> chipSelect) {
    cout << chipSelect << endl;
  } else {
    cout << F("\nInvalid pin number\n");
    return;
  }
  if (DISABLE_CHIP_SELECT < 0) {
    cout << F(
           "\nAssuming the SD is the only SPI device.\n"
           "Edit DISABLE_CHIP_SELECT to disable another device.\n");
  } else {
    cout << F("\nDisabling SPI device on pin ");
    cout << int(DISABLE_CHIP_SELECT) << endl;
    pinMode(DISABLE_CHIP_SELECT, OUTPUT);
    digitalWrite(DISABLE_CHIP_SELECT, HIGH);
  }
  if (!sd.begin(chipSelect, SPI_SPEED)) {
    if (sd.card()->errorCode()) {
      cout << F(
             "\nSD initialization failed.\n"
             "Do not reformat the card!\n"
             "Is the card correctly inserted?\n"
             "Is chipSelect set to the correct value?\n"
             "Does another SPI device need to be disabled?\n"
             "Is there a wiring/soldering problem?\n");
      cout << F("\nerrorCode: ") << hex << showbase;
      cout << int(sd.card()->errorCode());
      cout << F(", errorData: ") << int(sd.card()->errorData());
      cout << dec << noshowbase << endl;
      return;
    }
    cout << F("\nCard successfully initialized.\n");
    if (sd.vol()->fatType() == 0) {
      cout << F("Can't find a valid FAT16/FAT32 partition.\n");
      reformatMsg();
      return;
    }
    if (!sd.vwd()->isOpen()) {
      cout << F("Can't open root directory.\n");
      reformatMsg();
      return;
    }
    cout << F("Can't determine error type\n");
    return;
  }
  cout << F("\nCard successfully initialized.\n");
  cout << endl;

  uint32_t size = sd.card()->cardSize();
  if (size == 0) {
    cout << F("Can't determine the card size.\n");
    cardOrSpeed();
    return;
  }
  uint32_t sizeMB = 0.000512 * size + 0.5;
  cout << F("Card size: ") << sizeMB;
  cout << F(" MB (MB = 1,000,000 bytes)\n");
  cout << endl;
  cout << F("Volume is FAT") << int(sd.vol()->fatType());
  cout << F(", Cluster size (bytes): ") << 512L * sd.vol()->blocksPerCluster();
  cout << endl << endl;

  cout << F("Files found (date time size name):\n");
  sd.ls(LS_R | LS_DATE | LS_SIZE);

  if ((sizeMB > 1100 && sd.vol()->blocksPerCluster() < 64)
      || (sizeMB < 2200 && sd.vol()->fatType() == 32)) {
    cout << F("\nThis card should be reformatted for best performance.\n");
    cout << F("Use a cluster size of 32 KB for cards larger than 1 GB.\n");
    cout << F("Only cards larger than 2 GB should be formatted FAT32.\n");
    reformatMsg();
    return;
  }
  // Read any extra Serial data.
  do {
    delay(10);
  } while (Serial.available() && Serial.read() >= 0);
  cout << F("\nSuccess!  Type any character to restart.\n");
  while (!Serial.available()) {
    SysCall::yield();
  }
}

et voici le retour (même hardware) :

SPI pins:
MISO: 50
MOSI: 51
SCK:  52
SS:   53

Be sure to edit DISABLE_CHIP_SELECT if you have
a second SPI device.  For example, with the Ethernet
shield, DISABLE_CHIP_SELECT should be set to 10
to disable the Ethernet controller.

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: 53

Assuming the SD is the only SPI device.
Edit DISABLE_CHIP_SELECT to disable another device.

Card successfully initialized.

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

Volume is FAT16, Cluster size (bytes): 16384

Files found (date time size name):

Success!  Type any character to restart.

J'avoue ne pas saisir les subtilités qui conduisent à des résultats autant opposés ...

Quand ce sera fait, je m'attaquerai à la résolution du problème suivant :

Faire marcher un sketch exemple de création / écriture et re-lecture de fichier, qui à ce jour ne fait que créer le fichier mais n'arrive pas à écrire dedans ..., pas plus qu'à le lire...

Pas d'avis, les gens ?

tu as un cours basique tres simple et tres bien fait , ecrit par nanomaitre sur le site de [u]openclassroom[/u] qui t ' indiqueras la maniere de proceder afin de lire et ecrire sur ta SD .

ecrire sur une SD avec une mega, c'est toujours un peu compliqué... avec une uno ça fonctionne bien plus facilement. je ne sais pas pourquoi par contre

cela dit la différence entre tes deux cas c'est peut-être que dans le second(celui qui fonctionne) une vitesse réduite est employée.

essaye d'employer la vitesse réduite aussi dans le premier cas pour voir ?

merci JML pour la reponse claire et concise .