Ever wanted to log real-time sensor data with your Arduino?
Think of a weather station recording temperature and humidity every 10 seconds, or a smart irrigation system storing soil moisture levels throughout the day. Pretty soon, you’ll realize Arduino’s built-in memory just isn’t enough.
So what’s the solution?
👉 A Micro SD card module—the same tiny storage cards you use in cameras and phones. With this simple module, your Arduino projects get access to megabytes (even gigabytes!) of external storage. Perfect for projects that need data logging, tracking, or saving files.
In this guide, we’ll walk you through how to interface a Micro SD card module with Arduino step by step.
Micro SD Card Module Hardware Overview
A Micro SD card module is more than just a card slot. It includes:
Micro SD Card Socket – Where you insert the card. Most modules have clear markings to avoid wrong insertion.
3.3V LDO Voltage Regulator – Since SD cards work at 3.3V, the regulator safely steps down Arduino’s 5V to 3.3V. This prevents damage while keeping voltage stable.
Logic Level Shifter (74LVC125A) – Acts as a translator that converts Arduino’s 5V logic signals to 3.3V for the SD card, ensuring safe and reliable communication.
Micro SD Card Module Pinout
Here’s the pin configuration you’ll use while wiring it with Arduino:
GND → Connect to Arduino GND
VCC → Connect to 5V pin on Arduino
MISO (Master In Slave Out) → Sends data from SD card to Arduino
MOSI (Master Out Slave In) → Sends data from Arduino to SD card
SCK (Serial Clock) → Provides clock pulses from Arduino
CS (Chip Select / Slave Select) → Activates or deactivates the module on the SPI bus
Interfacing Micro SD Card Module with Arduino
Now that you understand the module and its pins, let’s put it into action. We’ll interface the Micro SD card module with Arduino UNO and use an I2C LCD to display information.
Hardware Requirements
- Arduino UNO R3
- LCD 16x2 (with I2C)
- Micro SD Card Module
- Micro SD Card
- Jumper Wires
- USB Cable Type A to B
- 12V Adapter
Wiring Connections
The Micro SD card module communicates with Arduino using the SPI protocol. This means it relies on dedicated SPI pins—MOSI, MISO, SCK, and CS—to exchange data. While SD cards can also work over SDIO (Secure Digital Input Output), this tutorial focuses only on the SPI-based interface.
Along with these communication pins, the module also needs power connections:
VCC (5V) – to power the module
GND – to complete the circuit
Wiring Between Arduino UNO and SD Card Reader
Connecting the I2C LCD with Arduino
Wiring the I2C LCD to Arduino is straightforward.
Connect VCC and GND of the LCD to the respective VCC and GND pins on the Arduino.
The two communication lines are:
SCL (Clock) → Connects to Arduino’s SCL pin (Analog pin A5)
SDA (Data) → Connects to Arduino’s SDA pin (Analog pin A4)
On the LCD’s back panel, these SCL and SDA pins are also marked and internally connected to A5 and A4 of the Arduino. In the provided wiring diagram, the pink wire is used for SCL and the blue wire for SDA.
⚠️ Important Note: Ensure that the A0, A1, and A2 address jumpers on the I2C LCD are not shorted. This is necessary because in the code we’ll be using the I2C address 0x27, which only works when these jumpers remain open.
Arduino Code for checking Micro SD card Information
/*
Code to get info about SD card and for testing if its working or not
by platwithcircuit.com
*/
#include <SPI.h>
// include SPI library header
#include <SD.h>
// include the SD library header
#include <LiquidCrystal_I2C.h>
// include I2C LCD library header
// set up variables using the SD utility library functions
Sd2Card card;
SdVolume volume;
SdFile root;
// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);
const int chipSelect = 10;
void setup() {
// initialize the LCD
lcd.init();
// Turn ON the Backlight
lcd.backlight();
// Clear the display buffer
lcd.clear();
// Print a message to the LCD
lcd.setCursor(0, 0);
lcd.print("Initializing");
lcd.setCursor(0, 1);
lcd.print("SD Card...");
// Open serial communications and wait for port to open
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect
}
Serial.print("\nInitializing SD card...");
delay(1000);
// 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?");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Initialization");
lcd.setCursor(0, 1);
lcd.print("Failed");
while (1)
;
} else {
Serial.println("Wiring is correct and a card is present.");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Initialization");
lcd.setCursor(0, 1);
lcd.print("Successfull");
delay(2000);
}
// print the type of card
Serial.println();
Serial.print("Card type: ");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Card Type:");
lcd.setCursor(0, 1);
switch (card.type()) {
case SD_CARD_TYPE_SD1:
Serial.println("SD1");
lcd.print("SD1");
break;
case SD_CARD_TYPE_SD2:
Serial.println("SD2");
lcd.print("SD2");
break;
case SD_CARD_TYPE_SDHC:
Serial.println("SDHC");
lcd.print("SDHC");
break;
default:
Serial.println("Unknown");
lcd.print("Unknown");
}
delay(2000);
// 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());
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Clusters:");
lcd.setCursor(0, 1);
lcd.print(volume.clusterCount());
delay(2000);
Serial.print("Blocks per Cluster: ");
Serial.println(volume.blocksPerCluster());
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Block per Clster");
lcd.setCursor(0, 1);
lcd.print(volume.blocksPerCluster());
delay(2000);
Serial.print("Total Blocks: ");
Serial.println(volume.blocksPerCluster() * volume.clusterCount());
Serial.println();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Total Blocks:");
lcd.setCursor(0, 1);
lcd.print(volume.blocksPerCluster() * volume.clusterCount());
delay(2000);
// 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);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Volume type is:");
lcd.setCursor(0, 1);
lcd.print("FAT");
lcd.print(volume.fatType(), DEC);
delay(2000);
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);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Volume size (KB):");
lcd.setCursor(0, 1);
lcd.print(volumesize);
delay(2000);
Serial.print("Volume size (MB): ");
volumesize /= 1024;
Serial.println(volumesize);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Volume size (MB):");
lcd.setCursor(0, 1);
lcd.print(volumesize);
delay(2000);
Serial.print("Volume size (GB): ");
Serial.println((float)volumesize / 1024.0);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Volume size (GB):");
lcd.setCursor(0, 1);
lcd.print((float)volumesize / 1024.0);
delay(2000);
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) {
}
Checkout this article to learn how to: Read-Write Data on Micro SD Card
Top comments (0)