Access SD Cards from TFT LCD Shield Using Arduino Mega 2560 Soft SPI

Posted by:

Preamble:

Some things to keep in mind when using the SD Library -from official site and SD library

The communication between the microcontroller and the SD card uses SPI, which takes place on digital pins 11, 12, and 13 (on most Arduino boards) or 50, 51, and 52 (Arduino Mega). Additionally, another pin must be used to select the SD card. This can be the hardware SS pin – pin 10 (on most Arduino boards) or pin 53 (on the Mega) – or another pin specified in the call to SD.begin().

Note that even if you don’t use the hardware SS pin, it must be left as an output or the SD library won’t work. Different boards use different pins for this functionality, so be sure you’ve selected the correct pin in SD.begin().

Not all the functions are listed on the main SD library page, because they are part of the library’s utility functions

Issues

SD card uses SPI to transfer data, and Uno D11, D12, D13 as hardware SPI (see below from ceez). That is the reason why Uno works out of box for SD access.

ArduinoUno_R3_Pinouts.png

On the other hand, Mega 2560 SPI takes place on 50, 51 and 52 as shown below:

ArduinoMega2560_pinout.png

The current LCD shield uses 8-bit bus interface (LCD_D0 – LCD_D7) instead of SPI. That is why LCD works but SD card doesn’t.

Solution

One solution is to employ software SPI, modify the SD library to use software SPI on digital pins located at the same place as SPI pins on UNO board, so that same sketch will work both for Uno and Mega boards.

I guess the other option is to rewire and use hardware SPI from Mega. The sketch code needs to change accordingly.

Adafruit SD library is adapted and some instructions from here.

How to get it work with Mega 2560 with softSPI

  1. Download the SD Adafruit library and replace the file in your library

  2. comment out #define USE_SPI_LIB from both Sd2Card.h and Sd2Card.cpp. reference here.

  3. Modify Sd2Card.h to enable the softSPI for Mega 2560

  4. I will do it later, I am watching my stories

    bmp-mega.JPG

  5. All the examples works fine after change chipSelect = 10;

11
  Related Posts

Comments

  1. Ceez  November 7, 2015

    Very nice work!

    reply
    • Ceez  November 7, 2015

      Did you try?

      #define USE_SPI_LIB // leave it un-commented
      #define MEGA_SOFT_SPI 1

      From what I understand when read the file sd2card.h and sd2card.cpp, it should work just with

      #define MEGA_SOFT_SPI 1
      reply
      • mistan  November 7, 2015

        Hi Ceez,

        I am getting following error message if leave {php}#define USE_SPI_LIB{/php} un-commented.

        Arduino: 1.6.5 (Linux), Board: "Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"
        
        /usr/share/arduino/libraries/SD/utility/Sd2Card.cpp: In member function 'uint8_t Sd2Card::setSckRate(uint8_t)':
        /usr/share/arduino/libraries/SD/utility/Sd2Card.cpp:585:3: error: 'SPI' was not declared in this scope
           SPI.setClockDivider(v);
           ^
        Error compiling.
        
          This report would have more information with
          "Show verbose output during compilation"
          enabled in File > Preferences.
        
        #define USE_SPI_LIB // leave it un-commented
        #define MEGA_SOFT_SPI 1

        As you said, it should work; However, it was stated in this issue that there may be bug in cpp file.

        Thanks for your wonderful work.
        Tony

        reply
  2. Sebastian Silva  November 25, 2016

    Hi I have to connect an arduino 2560 with a sd card module, I made the modifications that you indicate in steps 2 and 3. I additionally made this modification to the Sd2Card.h

    #else // SOFTWARE_SPI
    // define software SPI pins so Mega can use unmodified GPS Shield
    /** SPI chip select pin */
    uint8_t const SD_CHIP_SELECT_PIN = 53;
    /** SPI Master Out Slave In pin */
    uint8_t const SPI_MOSI_PIN = 51;
    /** SPI Master In Slave Out pin */
    uint8_t const SPI_MISO_PIN = 50;
    /** SPI Clock pin */
    uint8_t const SPI_SCK_PIN = 52;
    #endif // SOFTWARE_SPI

    but it doesn’t work what am I doing wrong?

    My code is the next one:
    #include
    #include

    /*
    * MISO - 50 - 12
    * SCK - 52 - 13
    * MOSI - 51 - 11
    * CS - 53 - 10
    */
    const int chipSelect = 10;
    int contador = 0;
    int i = 0;

    void setup() {
    // put your setup code here, to run once:
    Serial.begin(115200);
    Serial.print("Inicializando sd card...");
    pinMode(chipSelect,OUTPUT);
    delay(2000);
    if (!SD.begin(chipSelect))
    {
    Serial.print("fallo lectura de tarjeta");
    delay(2000);
    return;
    }
    Serial.print("SD card inicializada ok");
    delay(2000);

    }

    void loop() {
    // put your main code here, to run repeatedly:
    for(i=0; i<100; i++)
    {
    contador ++;
    sdcard();
    delay(1000);
    }
    }

    void sdcard() {
    String dataString = "";
    dataString += String("Contador");
    dataString +=",";
    dataString += String(contador);
    dataString +=",";
    File dafile = SD.open("datalog.txt",FILE_WRITE);
    if (dafile) {
    dafile.print(",");
    dafile.println(dataString);
    dafile.close();
    Serial.println(dataString);
    }
    else {
    Serial.println("error al abrir datalog.txt");
    }
    }

    Please help me.
    Regards,
    Sebastian

    reply
    • Sebastian Silva  November 25, 2016

      Sorry I used the code tags incorrectly

      The first code is:

      #else // SOFTWARE_SPI
      // define software SPI pins so Mega can use unmodified GPS Shield
      /** SPI chip select pin */
      uint8_t const SD_CHIP_SELECT_PIN = 53;
      /** SPI Master Out Slave In pin */
      uint8_t const SPI_MOSI_PIN = 51;
      /** SPI Master In Slave Out pin */
      uint8_t const SPI_MISO_PIN = 50;
      /** SPI Clock pin */
      uint8_t const SPI_SCK_PIN = 52;
      #endif // SOFTWARE_SPI

      The second one:

      #include
      #include

      /*
      * MISO – 50 – 12
      * SCK – 52 – 13
      * MOSI – 51 – 11
      * CS – 53 – 10
      */
      const int chipSelect = 10;
      int contador = 0;
      int i = 0;

      void setup() {
      // put your setup code here, to run once:
      Serial.begin(115200);
      Serial.print(“Inicializando sd card…”);
      pinMode(chipSelect,OUTPUT);
      delay(2000);
      if (!SD.begin(chipSelect))
      {
      Serial.print(“fallo lectura de tarjeta”);
      delay(2000);
      return;
      }
      Serial.print(“SD card inicializada ok”);
      delay(2000);

      }

      void loop() {
      // put your main code here, to run repeatedly:
      for(i=0; i<100; i++)
      {
      contador ++;
      sdcard();
      delay(1000);
      }
      }

      void sdcard() {
      String dataString = "";
      dataString += String("Contador");
      dataString +=",";
      dataString += String(contador);
      dataString +=",";
      File dafile = SD.open("datalog.txt",FILE_WRITE);
      if (dafile) {
      dafile.print(",");
      dafile.println(dataString);
      dafile.close();
      Serial.println(dataString);
      }
      else {
      Serial.println("error al abrir datalog.txt");
      }
      }

      reply
  3. ishimatsu  November 2, 2017

    It works for me.
    Thank you great info

    reply
  4. Anonymous  May 13, 2018

    I get this error: not so sure why

    /Users/(my name)/Documents/Arduino/libraries/SD/src/SD.cpp: In member function ‘boolean SDLib::SDClass::begin(uint32_t, uint8_t)’:
    /Users/(my name)/Documents/Arduino/libraries/SD/src/SD.cpp:356:15: error: ‘class Sd2Card’ has no member named ‘setSpiClock’
    card.setSpiClock(clock) &&
    ^
    Multiple libraries were found for “SD.h”
    Used: /Users/(my name)/Documents/Arduino/libraries/SD
    Not used: /private/var/folders/gr/3bm3p5g96cnfcmphdqf16mq80000gn/T/AppTranslocation/EBD61266-0230-4D2F-B8D4-13FAF611B0BA/d/Arduino.app/Contents/Java/libraries/SD
    exit status 1
    Error compiling for board Arduino/Genuino Mega or Mega 2560.

    reply
  5. KamenoPixel  July 18, 2019

    Great stuff … works for me…

    For the first step , download the lib SD-MASTER and move the original SD out of the library folder. Confirm at compile that Arduino IDE use the SD-MASTER folder and follow the other steps

    reply
    • Mohammed  September 2, 2020

      It work fine, but you need to to include ” #include ” in Sd2Card.h file and you will find everything OK.

      Also note that:
      Firstly, delete the original SD folder or move it out of the library folder, after that, download the lib SD-MASTER (https://github.com/adafruit/SD) and rename it to SD and move it to the library folder.

      reply
  6. Mohammed  September 2, 2020

    Your comment is awaiting moderation.
    It work fine, but you need to to include ” #include ” in Sd2Card.h file and you will find everything OK.

    Also note that:
    Firstly, delete the original SD folder or move it out of the library folder, after that, download the lib SD-MASTER (https://github.com/adafruit/SD) and rename it to SD and move it to the library folder.

    reply
  7. Mohammed  September 2, 2020

    It work fine, but you need to to include include SPI.h in Sd2Card.h file and you will find everything OK.

    Also note that:
    Firstly, delete the original SD folder or move it out of the library folder, after that, download the lib SD-MASTER (https://github.com/adafruit/SD) and rename it to SD and move it to the library folder.

    reply

Leave a Reply to mistan
click here to cancel reply