Helpful information about getting the SD card reader working on the thing plus C6

SD Card on SparkFun Thing Plus ESP32-C6 — Lessons Learned

Date: 2026-06-12
Project: CoffeeKeeper


The Short Version

The ESP32-C6 does NOT auto-assign SPI pins like older ESP32 boards.
You must explicitly declare all 4 SPI pins AND pass the SPI object to SD.begin().
Cards >32GB must be formatted FAT32 using the SD Association Formatter tool or diskpart.


Lesson 1 — Pin Mapping (CRITICAL)

The ESP32-C6 chip does not automatically assign standard SPI pins.
Always declare all 4 pins explicitly. The SparkFun Thing Plus ESP32-C6
routes the microSD slot to these internal pins:

#define SD_CS    18   // Chip Select
#define SD_SCK   19   // Clock
#define SD_MOSI  20   // PICO on schematic (Controller Out, Peripheral In)
#define SD_MISO  21   // POCI on schematic (Controller In, Peripheral Out)
#define SD_DET   22   // Card Detect — LOW = card inserted

Warning on schematic naming: The SparkFun schematic labels MOSI as “PICO”
and MISO as “POCI” — this is the PERIPHERAL perspective, opposite of what
you might expect from the controller perspective. Don’t get confused:

  • PICO (IO20) = MOSI from ESP32’s perspective
  • POCI (IO21) = MISO from ESP32’s perspective

Lesson 2 — Include Order and Style (CRITICAL)

Use quotes not angle brackets, and put FS.h first:

// CORRECT — use quotes, FS first
#include "FS.h"
#include "SD.h"
#include "SPI.h"

// WRONG — angle brackets cause issues on C6
#include <SD.h>
#include <SPI.h>
#include <FS.h>

Lesson 3 — Pass SPI Object to SD.begin() (CRITICAL)

The default SD library on C6 does not auto-configure the SPI bus.
You MUST pass the SPI object explicitly to SD.begin():

// CORRECT
SPI.begin(SD_SCK, SD_MISO, SD_MOSI, SD_CS);
if (!SD.begin(SD_CS, SPI)) {
    Serial.println("Card Mount Failed!");
}

// WRONG — fails silently on C6
SPI.begin(SD_SCK, SD_MISO, SD_MOSI, SD_CS);
if (!SD.begin(SD_CS)) {   // missing SPI object!
    Serial.println("Card Mount Failed!");
}

Lesson 4 — Power Rail Settling Delay

The 3.3V rail on the ESP32-C6 sometimes needs time to stabilize
after boot before the SD card will respond. Add a delay before SPI.begin():

delay(2000);  // wait for 3.3V rail to settle
SPI.begin(SD_SCK, SD_MISO, SD_MOSI, SD_CS);

Lesson 5 — Retry Loop (IMPORTANT)

SD.begin() can fail intermittently on the C6 even with correct pins.
Always use a retry loop with SD.end() between attempts:

bool sdOnline = false;
SPI.begin(SD_SCK, SD_MISO, SD_MOSI, SD_CS);

for (int attempt = 1; attempt <= 3 && !sdOnline; attempt++) {
    if (attempt > 1) {
        Serial.printf("[RETRY] SD attempt %d/3\n", attempt);
        SD.end();
        delay(500);
        SPI.begin(SD_SCK, SD_MISO, SD_MOSI, SD_CS);
    }
    if (SD.begin(SD_CS, SPI)) {
        uint8_t cardType = SD.cardType();
        if (cardType != CARD_NONE) {
            sdOnline = true;
            Serial.println("[OK] SD card ready");
        }
    }
}
if (!sdOnline) {
    Serial.println("[ERROR] SD failed after 3 attempts");
}

Lesson 6 — FAT32 Formatting for Large Cards (CRITICAL)

Cards larger than 32GB ship formatted as exFAT by default.
The ESP32 SD library does NOT support exFAT — it will fail silently.

Always format SD cards as FAT32 before use.

Option A — SD Association Formatter (recommended for ≤32GB)

Download: SD Memory Card Formatter for Windows/Mac - SD Association
Note: For cards >32GB this tool also formats as exFAT — use diskpart instead.

Option B — Windows diskpart (works for any size)

Run Command Prompt as Administrator:

diskpart
list disk                    ← find your SD card disk number
select disk X                ← replace X with SD card number (BE CAREFUL)
list partition
select partition 1
format fs=fat32 quick
exit

How to verify

After formatting, check Windows Explorer — right-click the card → Properties.
File system should show FAT32, not exFAT.


Lesson 7 — Card Detect Pin

The Thing Plus C6 has a card detect pin on IO22.
LOW = card inserted, HIGH = no card.
Check this first to confirm physical seating before debugging software:

pinMode(SD_DET, INPUT_PULLUP);
if (digitalRead(SD_DET) == HIGH) {
    Serial.println("[WARN] SD card not detected — check seating");
}

Lesson 8 — Filename Length (FAT32 Limit)

FAT32 supports long filenames (up to 255 characters) but keep filenames
short and simple to avoid edge cases. Always prefix with / for root directory.
Avoid special characters.

// GOOD — short, simple, starts with /
String name = "/BME_data_12345.json";

// RISKY — long names can cause open() to fail
String name = "BME_Log_empty_baseline_Board_683422375_P0_4046_F0.json";

Working Minimal Example

Verified working on SparkFun Thing Plus ESP32-C6:

#include "FS.h"
#include "SD.h"
#include "SPI.h"

#define SD_CS    18
#define SD_SCK   19
#define SD_MOSI  20
#define SD_MISO  21
#define SD_DET   22

void setup() {
    Serial.begin(115200);
    delay(2000);  // power rail settling

    // Check card detect
    pinMode(SD_DET, INPUT_PULLUP);
    if (digitalRead(SD_DET) == HIGH) {
        Serial.println("No card detected!");
        return;
    }

    // Init SPI and SD
    SPI.begin(SD_SCK, SD_MISO, SD_MOSI, SD_CS);
    if (!SD.begin(SD_CS, SPI)) {
        Serial.println("SD mount failed!");
        return;
    }

    Serial.print("Card type: ");
    Serial.println(SD.cardType());  // 2 = SDHC

    // Write a test file
    File f = SD.open("/test.txt", FILE_WRITE);
    if (f) {
        f.println("Hello from ESP32-C6!");
        f.close();
        Serial.println("Write OK");
    }
}

void loop() {}

Quick Diagnostic Checklist

When SD fails, go through in order:

  • Is card physically inserted? Check SD_DET pin (should be LOW)
  • Is card formatted FAT32? (not exFAT — check with diskpart or Properties)
  • Are all 4 SPI pins explicitly declared? (CS=18, SCK=19, MOSI=20, MISO=21)
  • Is SPI object passed to SD.begin(SD_CS, SPI)?
  • Is include order correct? (“FS.h” first, then “SD.h”, then “SPI.h”)
  • Is there a delay(2000) before SPI.begin() for power rail settling?
  • Is there a retry loop with SD.end() between attempts?
  • Is the filename short and starting with “/”?

Key References

  • SparkFun Thing Plus ESP32-C6 Schematic: IO18=CS, IO19=SCK, IO20=MOSI, IO21=MISO, IO22=SD_DET
  • SD Association Formatter: SD Memory Card Formatter for Windows/Mac - SD Association
  • Verified working ESP32 core version: 3.3.10
  • FAT32 max card size without special tools: 32GB (use diskpart for larger)

Thanks for sharing. By the way, did you ever try to use the SD card holder of the ESP32-CAM?