top of page

Interfacing SD card module with Arduino - Card Info, Read/Write and DATA LOGGER Functions

Updated: Dec 24, 2021


The micro SD Card Module is a simple solution for transferring data to and from a standard SD card. This module has SPI interface which is compatible with any SD card and it uses 5V or 3.3V power supply which is compatible with Arduino UNO/Mega.

Some times we have the need for a way to store data in our projects, and most of the time, the EEPROM which comes readily to mind has a limited storage capacity, and issues with the format and nature of data it can hold. All this and more makes it probably not the best for storing data like text, CSV, audio, video or image files. To get around this we could use an SD card to store the data, and remove the card when we need to view on some other platform etc. That is why today’s project is focusing on how to interface an SD card module with an Arduino.



Secure Digital (SD) is a non-volatile memory card format developed by the SD Card Association (SDA) for use in portable devices like mobile phones, cameras etc. Secure Digital includes four card families as follows-


1. SDSC: Standard Capacity SD. It has storage capacity of 2GB uses FAT- 12 and FAT-16 file systems.


2. SDHC: High Capacity SD. It has storage capacity ranging from 2GB to 32GB uses FAT-32 file system.


3. SDXC: extended Capacity SD. It has storage capacity ranging from 32GB to 2TB uses exFAT file system.


4. SDIO: It combines INPUT/OUTPUT functions with data storage.



File System

SD card is a block-addressable storage device, in which the host device can read or write fixed-size blocks by specifying their block number. Most SD cards are formatted with one or more MBR (Master Boot Record) partitions in which the first partition contains the file system which enables it to work like hard disks.


1. For SDSC card

Capacity smaller than 16 MB- FAT 12

Capacity between 16 MB and 32 MB- FAT 16

Capacity larger than 32 MB- FAT 16B


2. For SDHC cards

Capacity smaller than 7.8 GB- FAT 32

Capacity greater than 7.8 GB- FAT 32


3. For SDXC cards

exFAT

The Arduino Micro SD card Module is an SPI Communication based device. It is compatible with the TF SD cards used in mobile phones and can be used to provide some sort of external storage for micro controller and microprocessor based projects, to store different kind of data types from images to videos. SD cards generally are 3.3v logic level based devices, but with the aid of the Micro SD card module, the signals are converted to 5v via a logic level converter implemented on the SD card Module.


Components required

Arduino Nano - 1 no

Micro SD card Module - 1no

Memory Card 16GB (16GB used in this Project)- 1no

Jumper wires


Circuit diagram


The diagram shows the detail connections of SD module with Arduino.

MOSI (Master Out Slave In) - pin 11

MISO (Master In Slave Out) - pin 12

SCK (Clock)- pin 13

CS (Chip Select) - pin 4

GND-GND

VCC-5v or 3.3v.


The operating voltage of any standard micro SD Cards is 3.3 V. So we cannot directly connect it to circuits that use 5V logic. In fact, any voltages exceeding 3.6V will permanently damage the micro SD card. That’s why; the module has an onboard ultra-low dropout regulator that will convert voltages from 3.3V – 6V down to ~3.3V.

There’s also a 74LVC125A chip on the module which converts the interface logic from 3.3V-5V to 3.3V. This is called logic level shifting. That means you can use this board to interact with both 3.3V and 5V microcontrollers like Arduino.


Arduino Library

Library will be using the inbuilt code provided by Arduino IDE.

The code in the Arduino IDE uses the two library files –

SPI.h

SD.h

These library files direct contain function definitions which are used for SD card read-write operations.


For accessing code in Arduino IDE you can follow the following mention steps-


Copy the code above and paste it into the Arduino IDE, Upload it to your board and you should see something like what is displayed below on your serial monitor.


SD Card Information


// 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

// MKRZero SD: SDCARD_SS_PIN

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 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?");

while (1);

} else {

Serial.println("Wiring is correct and a card is present.");

}


// print the type of card

Serial.println();

Serial.print("Card 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");

while (1);

}


Serial.print("Clusters: ");

Serial.println(volume.clusterCount());

Serial.print("Blocks x Cluster: ");

Serial.println(volume.blocksPerCluster());


Serial.print("Total Blocks: ");

Serial.println(volume.blocksPerCluster() * volume.clusterCount());

Serial.println();


// print the type and size of the first FAT-type volume

uint32_t volumesize;

Serial.print("Volume type is: FAT");

Serial.println(volume.fatType(), DEC);


volumesize = volume.blocksPerCluster(); // clusters are collections of blocks

volumesize *= volume.clusterCount(); // we'll have a lot of clusters

volumesize /= 2; // SD card blocks are always 512 bytes (2 blocks are 1KB)

Serial.print("Volume size (Kb): ");

Serial.println(volumesize);

Serial.print("Volume size (Mb): ");

volumesize /= 1024;

Serial.println(volumesize);

Serial.print("Volume size (Gb): ");

Serial.println((float)volumesize / 1024.0);


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) {

}


Serial monitor

After a successful upload, open the Serial Monitor at a baud rate of 9600. see the result on

Serial monitor.



SD Card Read/Write


Code Explanation:

The sketch starts with including the built in SD library and the SPI library which allows us to easily communicate with the SD card over SPI interface.


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


After the libraries have been included, the next thing we do is declare the Arduino pin to which the chipSelect (CS) pin of the SD card module is connected. The CS pin is the only one that is not really fixed as any of the Arduino digital pin. We don’t need to declare other SPI pins since we are using hardware SPI interface and these pins are already declared in the SPI library. After declaring the pin, we then create an object myFile, which will be used later on to store data on the SD card.


const int chipSelect = 10; File myFile;


Next, in the setup() section: We start the serial communication for showing the results on the serial monitor. Now, using the SD.begin() function we will initialize the SD card and if initialization is successful the “if” statement becomes true and the String “initialization done.” gets printed on the serial monitor, else the string “initialization failed!” gets printed and the program terminates.


Serial.begin(9600); Serial.print("Initializing SD card..."); if (!SD.begin()) { Serial.println("initialization failed!"); return; } Serial.println("initialization done.");


Next, the SD.open() function will open the file named “test.txt”. In our case, as such file is not present, it’ll be created. The other parameter FILE_WRITE opens the file in read-write mode.


myFile = SD.open("test.txt", FILE_WRITE);


Once the file is opened, we will print the “Writing to test.txt…” message on the serial monitor and then using the myFile.println() function we will write the text “testing 1, 2, 3.” into the file. After that we need to use close() function to ensure that the data written to the file is saved.


if (myFile) { Serial.print("Writing to test.txt..."); myFile.println("testing 1, 2, 3."); myFile.close(); Serial.println("done."); } else { Serial.println("error opening test.txt"); }


Now let’s read the same file to check if the write operation was successful.To do that, we will use the same function, SD.open() , but this time as the file “test.txt” has already been created, the function will just open the file. Then using the myFile.read() function we will read from the file and print it on the serial monitor. The read() function actually reads just one character at a time, so therefore we need to use the “while” loop and the function myFile.available() to read all characters in file. At the end we need to close the file.


myFile = SD.open("test.txt"); if (myFile) { Serial.println("test.txt:"); while (myFile.available()) { Serial.write(myFile.read()); } myFile.close(); } else { Serial.println("error opening test.txt"); }


Since this is just a demo sketch to demonstrate how to read and write files, there is no point to run the code multiple times so all the code was placed in the setup() function which runs just once, instead of putting it in a loop() function which runs over and over again.


void loop() { }


Serial monitor

After a successful upload, open the Serial Monitor at a baud rate of 9600. see the result on

Serial monitor.


SD Card DATA LOGGER


#include <SPI.h>

#include <SD.h>


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 native USB port only

}



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


// see if the card is present and can be initialized:

if (!SD.begin(chipSelect)) {

Serial.println("Card failed, or not present");

// don't do anything more:

while (1);

}

Serial.println("card initialized.");

}


void loop() {

// make a string for assembling the data to log:

String dataString = "";


// read three sensors and append to the string:

for (int analogPin = 0; analogPin < 3; analogPin++) {

int sensor = analogRead(analogPin);

dataString += String(sensor);

if (analogPin < 2) {

dataString += ",";

}

}


// open the file. note that only one file can be open at a time,

// so you have to close this one before opening another.

File dataFile = SD.open("datalog.txt", FILE_WRITE);


// if the file is available, write to it:

if (dataFile) {

dataFile.println(dataString);

dataFile.close();

// print to the serial port too:

Serial.println(dataString);

}

// if the file isn't open, pop up an error:

else {

Serial.println("error opening datalog.txt");

}

}


Serial monitor

After a successful upload, open the Serial Monitor at a baud rate of 9600. see the result on

Serial monitor.


Note

  • You can use print() and println() functions just like Serial objects, to write strings, variables, etc

  • Read() only returns a character at a time. It does not read a full line or a number!

  • The SD card library does not support ‘long filenames’. Instead, it uses the 3 format for file names, so keep file names short! For example datalog.txt is fine.

  • Also keep in mind that file names do not have ‘case’ sensitivity, so datalog.txt is the same file as DataLog.Txt is the same file as DATALOG.TXT



145 views0 comments
bottom of page