Micro-SD-Karten-Modul mit Arduino (SPI): Dateien schreiben, lesen & verwalten

Der Arduino UNO hat gerade einmal 1 KB EEPROM – für echte Datenmengen viel zu wenig. Die Lösung steckt in fast jeder Kameratasche: eine Micro-SD-Karte. Mit dem Micro-SD-Kartenmodul über die SPI-Schnittstelle wird aus deinem Arduino ein Gerät mit quasi unbegrenztem Speicher. In diesem Tutorial lernst du das komplette Datei-Handwerk: Karte erkennen, Dateien anlegen, zeilenweise auslesen, Werte anhängen und ganze Verzeichnisse durchsuchen – die Grundlage für Datenlogger, Konfigurationsdateien und CSV-Exporte, die du am PC weiterverarbeitest.

Warum überhaupt eine SD-Karte?

Sensordaten über Tage sammeln, eine Konfiguration speichern, die den Neustart überlebt, oder Messreihen als CSV exportieren und in Excel auswerten – all das braucht mehr Platz, als der Mikrocontroller selbst bietet. Eine handelsübliche Micro-SD-Karte bringt Gigabytes mit und behält die Daten auch ohne Strom. Und weil die Dateien im FAT-Dateisystem liegen, steckst du die Karte danach einfach in den PC und liest sie wie einen USB-Stick.

ℹ️ SD-Modul vs. EEPROM vs. Cloud: Das interne EEPROM (1 KB beim UNO) ist perfekt für wenige Einstellungen. Die SD-Karte ist der richtige Ort für große, wachsende Datenmengen – lokal und ohne Netz. Willst du Daten stattdessen live ins Smart Home schicken, ist ein ESP32 mit MQTT die Alternative. Beides lässt sich sogar kombinieren.

Wie SPI und das Dateisystem zusammenspielen

Das SD-Modul kommuniziert über SPI – einen schnellen Bus mit vier Leitungen: MOSI (Daten zum Modul), MISO (Daten zurück), SCK (Takt) und CS (Chip Select, die „Sprich-jetzt-mit-dir“-Leitung). Auf dem Arduino UNO liegen MOSI, MISO und SCK fest auf D11, D12 und D13; CS wählst du frei – wir nehmen D10.

Die SD-Bibliothek (bei der Arduino IDE bereits dabei) kümmert sich um alles Weitere: Sie versteht das FAT16/FAT32-Dateisystem, verwaltet Ordner und Dateien und gibt dir vertraute Befehle wie open(), print(), read() und close() – fast wie das Arbeiten mit dem Seriellen Monitor, nur eben auf die Karte.

Das brauchst du

Micro-SD-Kartenmodul (SPI) – nimmt Micro-SD- und SDHC-Karten auf, spricht über SPI
UNO R3 Entwicklungsboard (USB-C) – der Klassiker mit fester SPI-Belegung
Alternativ: Nano V3 (ATmega328) – gleiche Pinbelegung, kompakter für feste Aufbauten
Breadboard 400 Kontakte und Dupont-Jumperkabel – für die sechs Verbindungen
Eine Micro-SD-Karte – am besten 2–32 GB, in FAT32 formatiert

1Verkabelung

Sechs Kabel, dann steht die Verbindung. Achte auf die Spannung: Die meisten Module haben einen eigenen Spannungsregler und laufen an 5 V – prüfe die Beschriftung deines Moduls.

SD-Modul Arduino UNO / Nano Funktion
VCC 5V Versorgung (Modul mit Regler)
GND GND gemeinsame Masse
MISO D12 Daten von der Karte
MOSI D11 Daten zur Karte
SCK D13 Takt
CS D10 Chip Select (frei wählbar)

⚠️ 5 V oder 3,3 V? SD-Karten arbeiten intern mit 3,3 V. Module mit Spannungsregler und Pegelwandler (die meisten mit großer Platine) darfst du an 5 V betreiben. Nackte 3,3-V-Adapter nicht direkt an 5-V-Signale hängen. Wenn die Kartenerkennung wackelt, liegt es oft an der Stromversorgung – die Karte zieht beim Schreiben kurz viel Strom.

2Karte erkennen: der Verbindungstest

Bevor wir schreiben, prüfen wir, ob die Karte überhaupt gefunden wird. Dieser Sketch initialisiert die Karte und meldet Erfolg oder Fehler – der wichtigste erste Schritt bei jedem SD-Projekt:

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

const int CS_PIN = 10;

void setup() {
  Serial.begin(115200);
  while (!Serial) { ; }              // bei Boards mit USB-Chip warten

  Serial.print("Initialisiere SD-Karte... ");
  if (!SD.begin(CS_PIN)) {
    Serial.println("FEHLGESCHLAGEN!");
    Serial.println("Karte, Verkabelung und CS-Pin pruefen.");
    return;                          // hier ist Schluss
  }
  Serial.println("OK - Karte bereit.");
}

void loop() {
  // nichts zu tun
}

Erscheint „OK“, ist die halbe Miete geschafft. Kommt „FEHLGESCHLAGEN“, prüfe zuerst die CS-Leitung an D10 und ob die Karte in FAT32 formatiert ist. Sehr große Karten (128 GB+) macht die alte SD-Bibliothek manchmal Probleme – eine 8- oder 16-GB-Karte läuft am zuverlässigsten.

3Eine Datei schreiben

Jetzt legen wir eine Datei an und schreiben Text hinein. Wichtig ist das Muster öffnen – schreiben – schließen: Erst close() stellt sicher, dass die Daten wirklich auf der Karte landen und nicht im Zwischenspeicher verloren gehen.

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

const int CS_PIN = 10;

void setup() {
  Serial.begin(115200);
  if (!SD.begin(CS_PIN)) {
    Serial.println("SD-Init fehlgeschlagen");
    return;
  }

  // Datei zum Schreiben oeffnen (wird angelegt, wenn nicht vorhanden)
  File datei = SD.open("daten.txt", FILE_WRITE);
  if (datei) {
    datei.println("Hallo von MAKEROO!");
    datei.println("Zeile zwei");
    datei.print("Messwert: ");
    datei.println(42);
    datei.close();                   // erst jetzt sicher gespeichert
    Serial.println("Geschrieben.");
  } else {
    Serial.println("Datei konnte nicht geoeffnet werden");
  }
}

void loop() {}

💡 Der 8.3-Namensfallstrick: Die SD-Bibliothek versteht nur kurze Dateinamen im Format NAME.EXT – maximal 8 Zeichen Name, 3 Zeichen Endung. daten.txt geht, meine_messreihe_2026.txt nicht. Verwende kurze Namen wie log01.csv, dann gibt es keine Überraschungen.

4Eine Datei zeilenweise lesen

Das Gegenstück: die Datei öffnen und ihren Inhalt ausgeben. Mit available() prüfst du, ob noch Zeichen kommen, und liest sie bis zum Ende:

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

const int CS_PIN = 10;

void setup() {
  Serial.begin(115200);
  if (!SD.begin(CS_PIN)) { Serial.println("SD-Init fehlgeschlagen"); return; }

  File datei = SD.open("daten.txt");   // ohne FILE_WRITE = lesen
  if (datei) {
    Serial.println("--- Inhalt von daten.txt ---");
    while (datei.available()) {
      Serial.write(datei.read());       // Zeichen fuer Zeichen
    }
    datei.close();
    Serial.println("\n--- Ende ---");
  } else {
    Serial.println("Datei nicht gefunden");
  }
}

void loop() {}

Willst du einzelne Zeilen statt einzelner Zeichen verarbeiten – etwa um eine CSV-Spalte zu lesen – nutzt du datei.readStringUntil('\n'). Das liefert dir jede Zeile als String, den du dann an den Kommas auftrennst.

5Anhängen: fortlaufendes CSV-Log

Das eigentliche Superkraft-Feature: FILE_WRITE hängt automatisch ans Ende der Datei an, statt sie zu überschreiben. Damit baust du ein Log, das bei jedem Durchlauf eine neue Zeile bekommt – ideal als CSV mit Zeitstempel und Messwert:

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

const int CS_PIN = 10;
unsigned long zaehler = 0;

void schreibeZeile(unsigned long id, int wert) {
  File log = SD.open("log01.csv", FILE_WRITE);
  if (log) {
    log.print(id);
    log.print(",");
    log.print(millis());          // Zeit seit Start in ms
    log.print(",");
    log.println(wert);            // z. B. ein Sensorwert
    log.close();
  }
}

void setup() {
  Serial.begin(115200);
  if (!SD.begin(CS_PIN)) { Serial.println("SD-Init fehlgeschlagen"); return; }

  // Kopfzeile nur einmal schreiben, wenn Datei neu ist
  if (!SD.exists("log01.csv")) {
    File log = SD.open("log01.csv", FILE_WRITE);
    log.println("id,zeit_ms,wert");
    log.close();
  }
}

void loop() {
  int wert = analogRead(A0);        // Beispielmesswert
  schreibeZeile(zaehler++, wert);
  Serial.print("Zeile geschrieben: ");
  Serial.println(zaehler);
  delay(5000);                      // alle 5 Sekunden
}

ℹ️ Fertiges Logger-Projekt gesucht? Wenn du dieses Prinzip mit echten Sensoren und Zeitstempel per Echtzeituhr kombinieren willst, zeigt der Guide zum Arduino-Datenlogger den kompletten Aufbau. Einen echten Zeitstempel statt millis() liefert dir das DS3231-RTC-Modul.

6Verzeichnis auflisten & Dateien verwalten

Zum Abschluss die Dateiverwaltung: Ordner durchlaufen, Dateigrößen anzeigen und Dateien löschen. So behältst du den Überblick, was auf der Karte liegt:

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

const int CS_PIN = 10;

void listeVerzeichnis(File dir) {
  while (true) {
    File eintrag = dir.openNextFile();
    if (!eintrag) break;              // keine weiteren Dateien
    Serial.print(eintrag.name());
    if (eintrag.isDirectory()) {
      Serial.println("/  (Ordner)");
    } else {
      Serial.print("\t");
      Serial.print(eintrag.size());
      Serial.println(" Bytes");
    }
    eintrag.close();
  }
}

void setup() {
  Serial.begin(115200);
  if (!SD.begin(CS_PIN)) { Serial.println("SD-Init fehlgeschlagen"); return; }

  Serial.println("Dateien auf der Karte:");
  File root = SD.open("/");
  listeVerzeichnis(root);
  root.close();

  // Beispiel: eine Datei loeschen
  if (SD.exists("alt.txt")) {
    SD.remove("alt.txt");
    Serial.println("alt.txt geloescht");
  }
}

void loop() {}

Mit SD.mkdir("logs") legst du außerdem Unterordner an und schreibst dann in "logs/log01.csv" – so bleibt die Karte auch bei vielen Dateien aufgeräumt.

Troubleshooting

⚠️ SD.begin() schlägt immer fehl: Häufigste Ursachen – falscher CS-Pin im Code, Karte nicht in FAT32 formatiert, oder MOSI/MISO vertauscht. Formatiere die Karte am PC neu (FAT32) und prüfe die vier SPI-Leitungen.

⚠️ Datei bleibt leer: Fast immer fehlt das close(). Ohne Schließen bleiben die Daten im Puffer und gehen beim Reset verloren.

⚠️ Dateiname wird ignoriert: Zu lang für das 8.3-Format. Kurzen Namen wie log01.csv verwenden.

⚠️ Karte wird sporadisch nicht erkannt: Stromversorgung zu schwach. Das Modul an eine stabile 5-V-Quelle hängen, kurze Kabel verwenden, ggf. einen Stützkondensator (100 µF) an VCC/GND setzen.

⚠️ Umlaute erscheinen als Kauderwelsch: Schreibe Logs in reinem ASCII (ae, oe, ue) – dann öffnet sich die CSV überall sauber.

🚀 Dein SD-Speicher-Starterpaket

Alle Bauteile für den Dateizugriff im Shop:

Fazit

Mit dem Micro-SD-Modul und der SD-Bibliothek gibst du deinem Arduino praktisch unbegrenzten, dauerhaften Speicher. Du hast die Karte erkannt, Dateien geschrieben und gelesen, ein fortlaufendes CSV-Log aufgebaut und gelernt, Verzeichnisse zu durchsuchen und Dateien zu verwalten – alles über die vertrauten open/print/read/close-Befehle.

Damit steht das Fundament für echte Projekte: Datenlogger für Wetter oder Energie, Konfigurationsdateien, die den Neustart überleben, oder Messreihen, die du am PC in Excel auswertest. Kombiniere die Karte mit einem RTC-Modul für Zeitstempel – und dein Arduino führt Buch, ganz von selbst. Viel Spass beim Speichern!

Zurück zum Blog