One of the most powerful capabilities you can add to any Arduino project is persistent data storage, and Arduino SD card logging is the most accessible way to do it. By connecting a MicroSD card module to your Arduino, you can record sensor readings, timestamps, GPS coordinates, and system events to files that survive power cycles and can be opened directly in Excel, Python, or any data analysis tool. This complete guide covers everything from wiring the SD card module to writing efficient, reliable CSV data loggers with timestamps from an RTC module.
Table of Contents
- Types of SD Card Modules
- Wiring the SD Card Module to Arduino
- Using the Arduino SD Library
- Writing and Appending to Files
- Building a CSV Sensor Data Logger
- Adding Timestamps with an RTC Module
- Tips for Reliable SD Card Logging
- Frequently Asked Questions
Types of SD Card Modules
Several variants of SD card modules are available for Arduino projects:
- Standard MicroSD Module: The most common — a small breakout board with a MicroSD slot, SPI interface, and a 3.3V/5V level shifter. Works with both 5V Arduinos and 3.3V boards. Supports cards up to 32 GB (FAT32 formatted).
- SD Card Shield: Stacks directly on top of an Arduino Uno with no jumper wires required. Often includes a DS1307 or DS3231 RTC on the same board for combined logging convenience.
- Data Logging Shield: Adafruit and similar manufacturers offer logging shields with SD + RTC + prototyping area on a single PCB.
- Module in Multifunctional Shields: Some Arduino multifunctional shields include SD card slots along with displays and other peripherals.
For most projects, the standalone MicroSD breakout module is the most flexible and affordable option. Use MicroSD cards of 4 GB or 8 GB formatted as FAT16 or FAT32 for best compatibility with the Arduino SD library.
Wiring the SD Card Module to Arduino
The SD card module communicates via SPI (Serial Peripheral Interface), which requires four data lines plus power and ground. On Arduino Uno/Nano, the hardware SPI pins are:
| SD Module Pin | Arduino Uno/Nano | Arduino Mega |
|---|---|---|
| VCC | 5V | 5V |
| GND | GND | GND |
| MISO | Pin 12 | Pin 50 |
| MOSI | Pin 11 | Pin 51 |
| SCK | Pin 13 | Pin 52 |
| CS (Chip Select) | Pin 10 (configurable) | Pin 53 (configurable) |
The CS (Chip Select) pin can be any digital output pin — pin 10 is the conventional default for Uno. If you use SPI with other devices (like a display), each device gets its own CS pin; only one should be driven LOW at a time.
Important note: Even if you are not using the hardware SPI SS pin (pin 10 on Uno) for CS, you MUST configure it as an OUTPUT in your sketch. If it is left as an INPUT and pulled low by external circuitry, the Arduino switches to SPI slave mode and the SD library will fail silently.
Using the Arduino SD Library
The SD library is included with the Arduino IDE — no separate installation is needed. Here is a minimal sketch to verify your SD card is detected and formatted correctly:
#include <SPI.h>
#include <SD.h>
const int SD_CS_PIN = 10; // Chip Select pin
void setup() {
Serial.begin(9600);
Serial.print("Initializing SD card...");
if (!SD.begin(SD_CS_PIN)) {
Serial.println("FAILED! Check wiring and card format.");
while (1);
}
Serial.println("SD card OK.");
// List root directory
File root = SD.open("/");
while (true) {
File entry = root.openNextFile();
if (!entry) break;
Serial.print(entry.name());
if (entry.isDirectory()) Serial.println(" [DIR]");
else {
Serial.print(" "); Serial.println(entry.size());
}
entry.close();
}
}
void loop() {}
If SD.begin() fails, common causes are: wrong CS pin, no card inserted, card formatted as NTFS or exFAT (must be FAT16/FAT32), or corrupted card. Try reformatting the card using the SD Association’s official formatter tool.
Writing and Appending to Files
The SD library supports creating, writing, reading, and deleting files. The most common operation for data logging is opening a file for append (adding data without erasing existing content):
void writeToSD(String filename, String data) {
File dataFile = SD.open(filename, FILE_WRITE); // Opens for append
if (dataFile) {
dataFile.println(data);
dataFile.close();
} else {
Serial.println("Error opening file!");
}
}
Key points about SD file operations:
FILE_WRITEopens for writing at the end of the file (append mode).- Always call
dataFile.close()after writing. This flushes the buffer and updates the FAT directory entry. If you skip close() and power is lost, you may lose the last few entries or the entire file. - Filenames must follow 8.3 format (max 8 characters + 3-character extension, e.g., DATA0001.CSV). Longer names will be truncated silently.
- The SD library is not re-entrant — avoid calling SD functions from interrupts.
Building a CSV Sensor Data Logger
A CSV (Comma-Separated Values) file is the ideal format for sensor logging — it opens directly in Microsoft Excel, LibreOffice Calc, and Python’s pandas library without any conversion. Here is a complete logger that reads an LM35 temperature sensor and writes timestamped CSV data:
#include <SPI.h>
#include <SD.h>
const int SD_CS = 10;
const int TEMP_PIN = A0;
const char* FILENAME = "TEMP.CSV";
unsigned long logInterval = 5000; // Log every 5 seconds
unsigned long lastLog = 0;
void setup() {
Serial.begin(9600);
pinMode(10, OUTPUT); // SS pin always OUTPUT
if (!SD.begin(SD_CS)) {
Serial.println("SD init failed!");
while (1);
}
// Write CSV header if file is new
if (!SD.exists(FILENAME)) {
File f = SD.open(FILENAME, FILE_WRITE);
f.println("Millis,Temperature_C");
f.close();
}
Serial.println("Logging started.");
}
void loop() {
unsigned long now = millis();
if (now - lastLog >= logInterval) {
lastLog = now;
int raw = analogRead(TEMP_PIN);
float tempC = raw * (5000.0 / 1023.0) / 10.0; // LM35: 10mV/°C
File f = SD.open(FILENAME, FILE_WRITE);
if (f) {
f.print(now);
f.print(",");
f.println(tempC, 2);
f.close();
Serial.print("Logged: "); Serial.println(tempC);
}
}
}
This sketch logs the Arduino’s elapsed milliseconds and temperature every 5 seconds. To analyse the data, copy the SD card to your PC and open the CSV in Excel — instant time-series chart.
Adding Timestamps with an RTC Module
Using millis() for timestamps is fine for relative time, but for real-world logging you need actual calendar timestamps. Combining the DS3231 RTC with the SD card module creates a powerful, accurate data logger:
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <RTClib.h>
RTC_DS3231 rtc;
const int SD_CS = 10;
void setup() {
Serial.begin(9600);
Wire.begin();
rtc.begin();
if (!SD.begin(SD_CS)) { while (1); }
// Write header
File f = SD.open("LOG.CSV", FILE_WRITE);
if (f.size() == 0) {
f.println("Timestamp,Temperature_C,Humidity");
}
f.close();
}
String getTimestamp() {
DateTime now = rtc.now();
char buf[20];
sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d",
now.year(), now.month(), now.day(),
now.hour(), now.minute(), now.second());
return String(buf);
}
void loop() {
File f = SD.open("LOG.CSV", FILE_WRITE);
if (f) {
f.print(getTimestamp());
f.print(",");
f.print(25.4, 1); // Replace with actual sensor read
f.print(",");
f.println(63.2, 1);
f.close();
}
delay(60000); // Log every minute
}
The I2C bus (DS3231) and SPI bus (SD card) operate independently, so there is no conflict between them. Connect DS3231’s SDA to A4, SCL to A5, and SD card to pins 10–13 as normal — both work simultaneously.
Tips for Reliable SD Card Logging
SD card data loggers in real deployments face challenges that simple desktop prototypes don’t. Here are battle-tested tips for reliable long-term logging:
1. Handle Power Failures Gracefully
Use a watchdog timer to reset the Arduino if it hangs. On power loss, any unflushed data in the SD buffer is lost. Add a capacitor (470 µF, 6.3V) across the power supply to bridge brief power interruptions during the critical write-close sequence.
2. Rotate Log Files Daily
Instead of one giant file, create a new file each day named by date (e.g., 20260311.CSV). This limits file size, makes data management easier, and reduces the risk of losing everything if one file corrupts.
String getDailyFilename() {
DateTime now = rtc.now();
char buf[13];
sprintf(buf, "%04d%02d%02d.CSV", now.year(), now.month(), now.day());
return String(buf);
}
3. Choose the Right SD Card
Industrial MicroSD cards (rated for -40°C to +85°C) are more reliable than consumer cards for harsh environments. Class 4 or Class 6 cards actually perform better in low-level random-write scenarios than faster UHS-I cards, which sometimes throttle write speed for small blocks.
4. Minimise Write Frequency
Each open-write-close cycle wears the card’s flash memory. Buffer multiple readings in SRAM, then write them all at once every few minutes rather than writing one line per second. This extends card life from months to years.
5. Check for Card Presence
Some SD modules have a card-detect switch pin. If yours doesn’t, check SD.begin() success periodically and implement error recovery in your main loop rather than halting with while(1).
Frequently Asked Questions
Why does SD.begin() always return false?
The most common causes are: wrong CS pin number in code, incorrect SPI wiring (especially MISO/MOSI swapped), card formatted as exFAT instead of FAT32, card capacity over 32 GB (not supported by SD library), or missing 10 kΩ pull-up on MISO. Try reformatting with the SD Association formatter, and double-check all wiring with a multimeter.
Can I use an SD card module with SPI display at the same time?
Yes. Both devices share the same MOSI, MISO, and SCK lines. Each device has its own CS pin — drive only one CS LOW at a time. Set each CS HIGH before initialising the other device. In code, the SPI library handles bus sharing automatically when you control CS manually or through their respective libraries.
What is the maximum file size I can create on an Arduino SD card?
FAT16 supports up to 4 GB per file. FAT32 supports up to 4 GB per file as well (technically 4 GB – 1 byte). For most data logging applications, the file will be thousands of CSV lines totalling a few megabytes — well within limits. Practically speaking, you’ll fill the card before hitting file size limits.
My SD logger stops writing after a few hours. Why?
Common causes: (1) The SD card filled up — check available space. (2) A file open error wasn’t handled and the sketch got stuck. (3) Electrical noise on the SPI bus caused card initialisation to fail. (4) SRAM exhaustion from building long String objects — use character arrays and sprintf() instead. Add Serial.println() debugging to identify which condition is occurring.
Can I read SD card files from an Arduino and display them on a screen?
Yes. Use SD.open("FILE.CSV") without the FILE_WRITE flag to open in read mode. Use file.read() or file.readStringUntil('n') to read line by line. Parse the CSV fields and display them on a TFT or OLED screen. This enables Arduino-based standalone data viewers without a PC.
Arduino SD card logging transforms your sensor projects into professional-grade data collection systems. With accurate timestamps from a DS3231 RTC, efficient CSV formatting, and reliable write practices, you can build loggers that run unattended for months and produce data ready for direct analysis.
Build your data logger today. Browse our complete range of Arduino boards, sensors, and modules at Zbotic — competitively priced with fast shipping across India.
Add comment