Skip to content
Buy 10+ on select items — save 10% auto-applied
Free US shipping on orders $35+
Order by 3pm ET — ships same-day from the US
Skip to main content

ESP32 SD Card: Local CSV Data Logging Setup | ShillehTek

July 10, 2026 3 views

ESP32 SD Card: Local CSV Data Logging Setup | ShillehTek
Project

Build an ESP32 SD card CSV data logger with optional DS3231 timestamps for reliable offline sensor logging when WiFi drops, using ShillehTek parts.

30 min Beginner to Intermediate5 parts
ESP32 development board used as an SD card CSV data logger

Project Overview

ESP32 + SD card data logger: Build an ESP32 data logger that writes sensor readings to a microSD card as CSV, optionally adding DS3231 RTC timestamps so your logs stay readable even without internet.

Cloud logging is great until WiFi drops, your MQTT broker restarts, or you deploy somewhere with no connectivity. An ESP32 with a microSD card gives you reliable local logging that keeps writing through network hiccups.

This guide wires an SD card module to an ESP32, writes CSV data, shows how to add timestamps using a DS3231 RTC, and covers file size and speed tradeoffs for higher-rate logging.

  • Time: 30 to 60 minutes
  • Skill level: Beginner to Intermediate
  • What you will build: An ESP32 that appends timestamped sensor data into CSV files on a microSD card.

Parts List

From ShillehTek

External

  • MicroSD card module (SPI interface, 5V-tolerant preferred).
  • microSD card (up to 32 GB, FAT32 format; basic Class 10 is fine).
  • DS3231 RTC module (optional but recommended for real timestamps).

Note: Many SD modules are not truly 3.3V-safe on all pins. Confirm whether your SD module expects 3.3V or can accept 5V on VCC, and always share GND with the ESP32.

Step-by-Step Guide

Step 1 - Decide when local logging beats cloud logging

Goal: Understand why writing to microSD is a strong default for sensor deployments.

What to do: Use local CSV logs when you need data to survive outages and be easy to retrieve later.

SD card module wired to an ESP32 using SPI jumper wires
  • Survives WiFi outages: data keeps writing regardless.
  • Higher sample rate: SD logging can handle much higher rates than typical cloud endpoints.
  • No cloud dependency: works where there is no internet.
  • No monthly fee: large microSD cards can store extremely long time series at low sample rates.
  • Data ownership: remove the card and open the CSV locally.

Expected result: You have a clear reason to log locally, either as your primary method or as a fallback when cloud connectivity fails.

Step 2 - Wire the SD card module and optional DS3231 RTC

Goal: Connect the SD card module via SPI and (optionally) connect the DS3231 via I2C for timestamps.

What to do: Wire the SD module to the ESP32 SPI pins, then wire DS3231 to ESP32 I2C pins if you want real date and time.

Wiring map:

SD Card Module    ESP32
VCC               --> 5V (some modules need 3.3V, check yours)
GND               --> GND
CS                --> GPIO5
SCK               --> GPIO18
MOSI              --> GPIO23
MISO              --> GPIO19

DS3231 RTC (optional but recommended)
VCC               --> 3.3V
GND               --> GND
SDA               --> GPIO21
SCL               --> GPIO22

Expected result: Your ESP32 can talk to the SD card over SPI. If installed, the DS3231 can provide a stable time source over I2C.

Step 3 - Upload a basic CSV logger sketch

Goal: Create a CSV file on the SD card, write a header once, and append sensor rows.

What to do: Use the SD library to initialize the card, create /log.csv if it does not exist, then append rows on a fixed interval.

Code:

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

DHT dht(4, DHT22);
const int SD_CS = 5;
const char* LOG_FILE = "/log.csv";

void setup() {
  Serial.begin(115200);
  dht.begin();
  if (!SD.begin(SD_CS)) {
    Serial.println("SD failed");
    while (1);
  }
  // Write header if file doesn't exist
  if (!SD.exists(LOG_FILE)) {
    File f = SD.open(LOG_FILE, FILE_WRITE);
    f.println("millis,temp_c,humidity_pct");
    f.close();
  }
}

void loop() {
  float t = dht.readTemperature();
  float h = dht.readHumidity();
  File f = SD.open(LOG_FILE, FILE_APPEND);
  f.print(millis());
  f.print(","); f.print(t, 1);
  f.print(","); f.println(h, 1);
  f.close();
  delay(5000);
}

Expected result: The SD card contains log.csv with a header and new rows appended every 5 seconds.

Step 4 - Add real timestamps using a DS3231

Goal: Replace relative time (millis()) with human-readable timestamps.

What to do: Read the current time from the DS3231 and prepend it to each CSV row.

ESP32 SD card data logger build with DS3231 RTC providing timestamps

Code:

#include <RTClib.h>
RTC_DS3231 rtc;

void logRow(float t, float h) {
  DateTime now = rtc.now();
  char buf[24];
  sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d",
          now.year(), now.month(), now.day(),
          now.hour(), now.minute(), now.second());
  File f = SD.open(LOG_FILE, FILE_APPEND);
  f.print(buf); f.print(",");
  f.print(t, 1); f.print(",");
  f.println(h, 1);
  f.close();
}

Expected result: Each CSV row contains a real timestamp that is readable in Excel or pandas without conversion.

Step 5 - Rotate daily files on boot

Goal: Avoid extremely large CSV files that can become slow to open or process.

What to do: Generate a filename based on the current date and write logs into one file per day.

Code:

char filename[24];
DateTime now = rtc.now();
sprintf(filename, "/log_%04d%02d%02d.csv",
        now.year(), now.month(), now.day());

Expected result: Your logger writes to files like /log_20260710.csv, keeping each file smaller and easier to manage.

Step 6 - Increase throughput for high-rate logging

Goal: Improve performance when logging at 100+ samples per second.

What to do: Keep the file open and flush periodically instead of opening and closing the file every sample.

Code:

File logFile;
void setup() {
  // ...
  logFile = SD.open("/fast.csv", FILE_APPEND);
}
void loop() {
  logFile.print(micros());
  logFile.print(",");
  logFile.println(analogRead(A0));
  static int count = 0;
  if (++count % 100 == 0) logFile.flush();   // flush every 100 rows
}

Expected result: Higher sustained logging rates because SD writes are block-based and frequent flushes waste space and time.

Step 7 - Apply the logger to real deployments

Goal: Map this build to practical sensor logging scenarios.

What to do: Use the same SD CSV approach with the sensor you care about, then retrieve the card periodically for analysis.

ESP32 SD card data logger used in a field deployment for offline sensor data collection
  • Weather station in a remote field - no WiFi needed.
  • Vehicle GPS and accelerometer black box - second-by-second driving data.
  • Beehive weight and temperature - log long term, then retrieve the card.
  • Fermentation temperature curve - brewing, kombucha, sourdough starter tracking.
  • Fridge or freezer defrost cycle profiling - identify a failing seal.
  • Bird box camera trigger log - timestamp motion events.

Expected result: You can deploy sensors anywhere and still get complete time series data, even when connectivity is unreliable or unavailable.

Conclusion

An ESP32 with an SD card module and optional DS3231 RTC gives you a durable CSV data logger that keeps working when WiFi fails. You can remove the card and analyze the file in Excel or pandas with no cloud dependencies.

Inspiration credit: SD Card Datalogging With the DHT22 Temp Humidity Sensor on Instructables.

Want the exact parts used in this build? Grab them from ShillehTek.com. If you want help customizing this project or building something for your product, check out our IoT consulting services.