Problema SDCard ( Shield Ethernet + Mega 1280)

Queridos compañeros…

No suelo escribir en foros porque hoy en día casi la totalidad de los problemas ya los ha tenido otro antes…

El caso es que he buceado a fondo en los foros sobre este problema y aunque dan posibles soluciones, a mi no me han funcionado.

El caso es que me regalaron una ATMega1280 y me gusto el tema, asi que me puse a trastear con ella.
Despues de varios proyectos chorras para jugar me gustó la idea de comprar una shield ethernet con la que conectarme a un servidor para enviar datos. Así que me hice con una.

Vi que traía un puerto para una sd lo cual me gustó.

Cuando me ha llegado lo primero que hice fue probar la ethernet y funcionaba de maravilla, y además casi a la primera (lo mio es mucho de prueba error… uno que es cabezón).
El caso es que despues de estar una hora al menos enredando con el tema ethernet se me ocurrió probar la sd. Vi que admitía varios tamaños (tengo aquí, 1gb, 2gb, 16gb y 32gb) así que eso no era problema, formateo y la meto.
Cargo el programa por defecto de sketch (el de escribir y leer) lo dejo aquí debajo, y grata sorpresa que funciona. O_O

Pues bien, mi siguiente reto era mostrar dos digitos a traves de un par de 74HC595, despues de estar toda una tarde, al final conseguí hacerlo a mi manera. Uso en este caso los Pines digitales 8, 11, 12.

Me propongo lo siguiente, que es que los digitos muestren los datos de un sensor (el que tenía a mano es un DHT11), así que consiguo sin problema mostrar la temperatura y humedad. Uso el Pin digital 2 para obtener los datos del sensor.

Ahora me digo, bueno pues voy a escribir en la sd estos valores y aquí comienza mi tortura. Al juntarlo todo la tarjeta no va. Al cabo de un rato me doy cuenta de que la tarjeta usa los pines 4, 11, 12, 13 (el 13 lo usaba yo también para mostrar un ciclo completo… :frowning: )

Me digo, que fácil, cambio los pines del display y listo… pues no… me tiro un rato hasta que digo, voy a probar la tarjeta sola, sin nada más, con su código solamente… y nada, ya no me ha vuelto a funcionar.

Despues de bucear veo que sd y ethernet “no funcionan” juntas o si lo hacen no es recomendable.

También leí que había que poner en alto el pin 10 cuando se usa la sd para evitar conflicto con la ethernet… cosa a mi tarjeta le da lo mismo.

Lo último que he probado es la ethernet y si que va bien, pero la sd no hay manera.

Despues de este rollo (os lo he contado todo por si sirve de algo) el caso es que aunque no esté pensando en utilizar la sd, me sabe mal no saber que está pasando y porque no puedo volver a utilizar la sd.

Muchas gracias a todos por vuestra ayuda.

Dejo aquí los códigos que he utilizado.

PD. también he probado la librería SDFat sin existo.

Este es el código con el HIGH al pin 10.

/*
  SD card test 
   
This example shows how use the utility libraries on which the'
SD library is based in order to get info about your SD card.
Very useful for testing a card when you're not sure whether its working or not.
  
The circuit:
  * SD card attached to SPI bus as follows:
** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila
** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila
** CS - depends on your SD card shield or module. 
    Pin 4 used here for consistency with other Arduino examples


created  28 Mar 2011
by Limor Fried 
modified 9 Apr 2012
by Tom Igoe
*/
// include the SD library:
#include <SD.h>

// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
const int chipSelect = 4;    

void setup()
{
// Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  // disable w5100 SPI
  pinMode(10,OUTPUT);
  digitalWrite(10,HIGH);

  Serial.print("\nInitializing SD card...");
  // rest of your setup stuff


  // we'll use the initialization code from the utility libraries
  // since we're just testing if the card is working!
  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card is 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."); 
  }

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

  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
    return;
  }


  // print the type and size of the first FAT-type volume
  uint32_t volumesize;
  Serial.print("\nVolume type is FAT");
  Serial.println(volume.fatType(), DEC);
  Serial.println();
  
  volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
  volumesize *= volume.clusterCount();       // we'll have a lot of clusters
  volumesize *= 512;                            // SD card blocks are always 512 bytes
  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);
  
  // list all files in the card with date and size
  root.ls(LS_R | LS_DATE | LS_SIZE);
}


void loop(void) {
  
}

Y el que me funcionó al principio es este:

/*
  SD card read/write

 This example shows how to read and write data to and from an SD card file
 The circuit:
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4

 created   Nov 2010
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe

 This example code is in the public domain.

 */

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

File myFile;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }


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

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

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  myFile = SD.open("test.txt", FILE_WRITE);

  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println("testing 1, 2, 3.");
    // close the file:
    myFile.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }

  // re-open the file for reading:
  myFile = SD.open("test.txt");
  if (myFile) {
    Serial.println("test.txt:");

    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      Serial.write(myFile.read());
    }
    // close the file:
    myFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
}

void loop() {
  // nothing happens after setup
}

Los errores que me salen son:

Initializing SD card...initialization failed. Things to check:
* is a card is inserted?
* Is your wiring correct?
* did you change the chipSelect pin to match your shield or module?

y con el original:

Initializing SD card...initialization failed!

Yo la uso para guardar en SD los valores cuando no es satisfactoria la incorporacion a base de datos a traves deEthernet.
Tuve problemas. Al final parece que se han resuelto jugando, cuando se va a acceder a las funciones de SD, con el estado de los pin 10 y 4. Pasando uno a high y otro a low, y haciendo despues un SD.begin.
Luego, antesde salir, cuidado con volver a invertir el estado de 10 y 4 para que no falle Ethernet.
Parece que asi va funcionando, aunque aun tengo que putear un poco mas al sistema a ver si en alguna situacion me falla.

Muchas gracias Chema... pero no me ha funcionado...

El caso es que hoy me han dejado un modulo identico de Ethernet junto con una UNO y en ellas no tengo problemas...

Pero va más allá el tema, le pongo el módulo ethernet prestado a mi Mega y funciona... :o

O sea que he pensado que la ethernet se ha roto (la mia) y justo, la pruebo en la UNO y tampoco va...

Mi pregunta es, puedo haber "roto" la ethernet poniendo el los pines de SD (4, 11, 12) a funcionar el chip 74HC595?

La nueva me funciona sin rollos de poner el pin 10 y 4 patas arriba... :smiley:

Muchas gracias

Hola, tuve exactamente el mismo error usando la librería SimpleSDAudio, resulta que por definición y arquitectura de las placas están definidas así para lectura SD (pins):

SD_CS MOSI MISO SCK SS
mega368P (standard Arduinos) 4 11 12 13 10
mega1280, mega2560 4 51 50 52 53

Donde SD_CS en la mayoría de librerías que he visto se deja cambiar por el pin 10.

Puedes alterar manualmente el código del archivo pins_arduino.h ubicado en
C:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\mega

pero puede que te presente problema con otra aplicaciones…

Que casualidad!! Anoche lo consultaba a Noter por este tema porque es algo que se repite y quería que estableciéramos un protocolo o método para resolver este tema.
Pones una memoria SD y no sabes bien como hacer para que funcione. Se que a muchos no les pasa pero a otros si.
Así que tenemos un problema a resolver y creo que todos deberíamos ver en que condiciones funciona y cuando no.
Con este último comentario respeto ambas posturas (yo estoy en la que no funciona).

Asi que aprovechemos este hilo para analizar todo y seamos detallistas, nada de decir a mi me funciona porque no es el caso.
A titulo solo ilustrativo propongo que establezcamos lo siguiente

  1. La memoria debe formatearse en FAT16 o FAT32?
  2. Que tipos de SD o micro SD podemos usar. Desde ya todas, pero a que velocidad inicializar o no interesa?
  3. En el caso de muchas memorias hay que usar adaptación de niveles o no?
  4. Un código probado bajo las condiciones anteriores que funcione en todos los casos. Usando pin 4 o pin 10.
  5. Ver si se mantiene estable en el tiempo, porque aún resolviendo los puntos 1 a 3, hay quienes mencionan que el sistema inicializa y funciona 4 o 5 segundos o horas y luego se cuelga. Qué cuestiones debemos tener en cuenta? No usar strings por ejemplo?.

Bien, está planteado.
Espero que los que han podido hacerlas funcionar (no es mi caso) den algunas respuestas.
Yo me pongo a investigarlo porque tengo que armar un lote de equipos datalogger y acabo de empezar con este mismo problema. No tengo placa ethernet. Uso un zócalo SD y no puedo hacerlo funcionar.

Bueno. Comienzo a narrar mis experiencias y autoconsejos.
Tengo un módulo tal que así:

Primera parte: conexión.
Se conecta como un dispositivo esclavo SPI, por lo tanto en el caso de mi módulo el pin DI (data in) irá conectado al pin MOSI (Master Out-Slave In) del arduino. El pin DO (data Out) irá al pin MISO (Master In-Slave Out) del arduino, y el pin SCLK irá al pin SCK del arduino. ¿Dónde están ubicados? Podemos ver unos post más arriba el de ArturoTorres3838 que lo indica perfectamente. Como vemos no tiene nada que ver la ubicación de los pines en UNO y MEGA, aunque los tres pines que acabo de citar también están "duplicados" en el conector ICSP (los seis pines que están en medio de la placa), y en este caso la ubicación es idéntica en ambos modelos de arduino, e incluso algunos sólo los tienen disponibles en ese conector, como podemos ver, junto a muchas otras cuestiones interesantes en la propia referencia SPI.
¿Y el pin CS? Pues en teoría puede ir conectado a cualquier pin digital del arduino, siempre que se indique correctamente al iniciar la tarjeta. En muchos shields suele ser un pin fijo, entonces no quedará otra que usar ese.
¿El pin SS (10 en el uno, 53 en el mega) para qué es? Pues puede utilizarse como CS para el módulo SD u otro dispositivo SPI, o puede utilizarse como salida digital, pero NUNCA COMO ENTRADA, pues esto convierte el SPI del arduino en SPI esclavo, en lugar de maestro. A mí personalmente, para evitar la posibilidad me gusta pinchar el CS de la tarjeta o de otro dispositivo SPI, si tengo varios, en ese pin, aunque sólo sea por evitar la posibilidad de no acordarme de que no se puede usar como entrada.

En la imagen podemos ver los cables que van al módulo sd:
GND +5V (cables negro y rojo)

MISO en ICSP (cable amarillo) que va a DO
SCK en ICSP (cabLe azul) que va a SCK
MOSI en ICSP (cable marrón) que va a DI

Pin 53, que va a CS. Como hemos dicho puede ser cualquier pin digital. Yo uso ese para evitar usarlo como entrada por despiste.
[continuará...]

Ya para los artistas de la electrónica (surbyte :wink: ), que intentarán conectar directamente, sin shield, e incluso sin adaptador, la tarjeta SD, comentarles lo poco que puedo respecto a la electrónica. Como ya sabrán, no se puede conectar directamente a los pines de los arduinos que trabajan a 5v, ya que las SD operan en un rango entre 2,7 y 3,6 V. Los que tenemos uno de estos arduinos, debemos lidiar con la transformación de voltaje. Habitualmente se utiliza un divisor resistivo para bajar 5v, CS, MOSI y SCK a los 3 y pico de la SD, y recibimos el pin MISO directamente con los 3 y pico, que se supone que arduino ya interpretará como HIGH.
Inconvenientes:
Las tarjetas SD tienen el acceso SPI como una característica “secundaria”, y los fabricantes dan prioridad a otros modos más rápidos de trabajo. Por lo tanto, no esperemos trabajar a altísimas velocidades.
Necesitaremos que las señales de los cuatro pines SPI sean cuanto más limpias y cuadraditas mejor, pues por mi experiencia es muy fácil dejar la tarjeta ilegible a nada que nos llegue la señal perturbada (habría que formatearla de nuevo). Aquí sería interesante que los que se manejan con osciloscopios nos enseñen sus experiencias.

Segunda parte: programación básica.

Bueno. Ya se supone que tenemos correctamente conectada nuestra SD y sabemos qué pin vamos a utilizar como CS.
Lo primero que recomiendo es abrir el ejemplo CardInfo que viene en el propio IDE y... seleccionar todo y copiarlo a un nuevo sketch. ¿Por qué? Pues porque anoche me tiré un buen rato con el ejemplito, y me fallaba. En el monitor Serial aparecía:

initialization failed. Things to check:
* is a card inserted?
* is your wiring correct?
* did you change the chipSelect pin to match your shield or module?

Lo que ocurría es que (y hablo de mi windows 10) los ejemplos son archivos de sólo lectura, salvo que abras el ide como administrador, por lo que a pesar de que cambiaba el pin CS al pin que estaba usando yo, al compilar y subir me daba una advertencia de esas a las que no se suele hacer caso, pero la consecuencia es que subía al arduino el programa sin las modificaciones que había hecho.

Una vez pegado el código en un nuevo sketch, modificado el CS a nuestro gusto y subido al arduino, me aparece esto en el monitor serial:

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

Aquí los que tienen un buen shield o módulo lo habitual es que tengan ya resultado correcto, pero se ve que a mi módulo chinorri hay que hablarle más lento. modifico pues la siguiente línea:

if (!card.init(SPI_HALF_SPEED, chipSelect)) {

a esto otro:

if (!card.init(SPI_QUARTER_SPEED, chipSelect)) {

Y me aparece correctamente toda la información que se supone que debe aparecer con el ejemplo (tipo de fat, tamaño, listado de archivos...).

[Continuará...]

Llegados al punto en que CardInfo funciona correctamente, y por lo tanto hemos conseguido abrir los tres escalones (card, volumen y directorio raíz) ya nos deberíamos poder embarcar con el resto de ejemplos de la librería, y escribir/leer archivos, con una salvedad. Si en el ejemplo CardInfo habéis tenido que bajar (como yo) la velocidad del SPI, hemos de tener en cuenta que si queremos utilizar directamente el objeto SD (hasta ahora no lo hemos utilizado), deberemos modificar el método begin de la librería (en el archivo SD.cpp), para realizar la misma modificación de SPI_HALF_SPEED a SPI_QUARTER_SPEED, pues de serie viene definido tal que así:

boolean SDClass::begin(uint8_t csPin) {
  /*

    Performs the initialisation required by the sdfatlib library.

    Return true if initialization succeeds, false otherwise.

   */
  return card.init(SPI_QUARTER_SPEED, csPin) &&
         volume.init(card) &&
         root.openRoot(volume);
}

Para los viejunos como yo, veremos que los ejemplos se han simplificado sutilmente, en el sentido de que en versiones antiguas había que definir el pin 10 (53 en el mega) como salida antes de iniciar la SD, por la razón que hemos comentado antes. Además, para trabajar con más de un dispositivo SPI si éste funciona a distinta velocidad, o distinto modo, antes había que tenerlo en cuenta para ajustar los parámetros del SPI cuando pasábamos de utilizar uno a otro dispositivo. Es decir, que parte de la preparación del SPI se hacía en nuestro sketch. Ahora la librería SPI ya se ocupa de poner el pin SS como salida, y además se ha ampliado, con los métodos beginTransaction/endTransaction. Las librerías que hacen uso de la librería SPI moderna utilizando estos métodos deberían poder convivir entre ellas sin problemas, siempre que no utilicen el mismo CS. Por ejemplo ethernet y SD que vienen en los IDE modernos (tal vez no sea mala idea comenzar poniendo en HIGH los CS de todos los dispositivos para evitar que la inicalización del primero pille al segundo "abierto" y se interfieran)
El problema puede venir de librerías externas antiguas de otros dispositivos, por lo que si tenemos problemas con ellas puede que sea necesario modificarlas.

Estimados, ando teniendo problemas para leer una tarjeta SD desde un display chinoco (Full Graphic SMART CONTROLLER). El control de gráficos ya lo tengo bastante avanzado, pero no estoy pudiendo iniciar la comunicación con la tarjeta SD.

Como les decía tengo un arduino MEGA2560 con un shild Ramps 1,4 y sobre este shield tengo conectado el display.

chequié los planos del display y todo parecería estar bien conectado, pines 50,51,52 para SPI y el pin 53 como CS.

El código que quiero utilizar es el del ejemplo de la librería SD CARDINFO

Desde ya les agradezco por tomarse el tiempo de leer esta consulta.

/*
SD card test

This example shows how use the utility libraries on which the’
SD library is based in order to get info about your SD card.
Very useful for testing a card when you’re not sure whether its working or not.

The circuit:

  • SD card attached to SPI bus as follows:
    ** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila
    ** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
    ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila
    ** CS - depends on your SD card shield or module.
    Pin 4 used here for consistency with other Arduino examples

created 28 Mar 2011
by Limor Fried
modified 9 Apr 2012
by Tom Igoe
*/
// include the SD library:
#include <SPI.h>
#include <SD.h>

// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
const int chipSelect = 53;

void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}

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

// we’ll use the initialization code from the utility libraries
// since we’re just testing if the card is working!
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.”);
}

// print the type of card
Serial.print("\nCard type: ");
switch (card.type()) {
case SD_CARD_TYPE_SD1:
Serial.println(“SD1”);
break;
case SD_CARD_TYPE_SD2:
Serial.println(“SD2”);
break;
case SD_CARD_TYPE_SDHC:
Serial.println(“SDHC”);
break;
default:
Serial.println(“Unknown”);
}

// Now we will try to open the ‘volume’/‘partition’ - it should be FAT16 or FAT32
if (!volume.init(card)) {
Serial.println(“Could not find FAT16/FAT32 partition.\nMake sure you’ve formatted the card”);
return;
}

// print the type and size of the first FAT-type volume
uint32_t volumesize;
Serial.print("\nVolume type is FAT");
Serial.println(volume.fatType(), DEC);
Serial.println();

volumesize = volume.blocksPerCluster(); // clusters are collections of blocks
volumesize *= volume.clusterCount(); // we’ll have a lot of clusters
volumesize *= 512; // SD card blocks are always 512 bytes
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);

// list all files in the card with date and size
root.ls(LS_R | LS_DATE | LS_SIZE);
}

void loop(void) {

}