Bauteile · 12 Min. Lesezeit

Arduino SD-Kartenmodul: Datenlogger mit CSV, RTC und Fehlerhilfe

Arduino SD-Kartenmodul anschließen: SPI-Pins, FAT32 formatieren, Sensordaten als CSV mit RTC-Zeitstempel loggen, ESP32 SD_MMC, Pico und initialization failed.

Ein Arduino SD-Kartenmodul ist eine kleine, günstige Platine, mit der du Temperatur-, Feuchte-, Abstands- oder Positionswerte deiner Sensoren als Dateien auf einer Micro-SD-Karte speichern kannst. So baust du am einfachsten einen Datenlogger, der tage- oder sogar monatelang ohne angeschlossenen Computer misst: Der Arduino misst, das Modul schreibt jeden Messwert als neue Zeile in eine CSV-Datei auf der Karte, und du steckst die Karte später in den Computer und machst in Excel ein Diagramm daraus. Das Modul wird über SPI angeschlossen und funktioniert mit wenigen Zeilen Code und der SD-Bibliothek, die bereits in der Arduino IDE enthalten ist.

In dieser Anleitung lernst du Schritt für Schritt, wie das Modul funktioniert, worin sich 5-V- und 3,3-V-Module unterscheiden, wie du es per SPI an Arduino Uno, Mega, ESP32 und Raspberry Pi Pico anschließt, die Karte mit FAT32 formatierst, Dateien schreibst und liest und mit einem RTC-Modul ein CSV-Protokoll mit Datum und Uhrzeit führst. Außerdem geht es um die schnelle SD_MMC-Schnittstelle des ESP32, die SD-Karte am Pico mit MicroPython und die Lösungen für den häufigen Fehler "initialization failed".

Arduino Micro-SD-Kartenmodul
Micro-SD-Kartenmodul: Kartenslot, 3,3-V-Spannungsregler, Pegelwandler-IC und 6 Pins (GND, VCC, MISO, MOSI, SCK, CS).

Was ist ein SD-Kartenmodul und wie funktioniert es?

SD-Karten arbeiten mit 3,3 V und können auf zwei Arten kommunizieren: im schnellen SD-Modus und im einfacheren SPI-Modus. Mikrocontroller wie der Arduino sprechen über SPI mit der Karte. Das Modul sorgt für die elektrische Verträglichkeit: Sein Spannungsregler senkt 5 V auf die 3,3 V, die die Karte braucht, und ein Pegelwandler-IC (meist ein 74LVC125A) setzt die 5-V-Signale des Arduino auf 3,3 V um, die die Karte verträgt. Intern besteht die Karte aus Blöcken zu 512 Byte; Dateien, Ordner und Dateinamen verwaltet das FAT-Dateisystem. Die SD-Bibliothek erledigt diese komplizierte Arbeit für dich; du öffnest nur eine Datei, schreibst hinein und schließt sie wieder.

EigenschaftWert
SchnittstelleSPI (MISO, MOSI, SCK, CS)
Versorgung (Micro-SD-Modul mit Regler)4,5–5,5 V, 3,3-V-Regler auf der Platine
Signalpegel3,3 V und 5 V kompatibel (dank Pegelwandler)
Unterstützte KartenMicro SD (bis 2 GB) und Micro SDHC (4–32 GB)
DateisystemFAT16 oder FAT32
StromaufnahmeIm Leerlauf wenige mA, beim Schreiben bis 100 mA
Dateiname (Arduino-SD-Bibliothek)8.3-Format: maximal 8 Zeichen Name + 3 Zeichen Endung

5-V- oder 3,3-V-Modul: Welches solltest du kaufen?

ModultypVersorgungSignalpegelGeeignet für
Micro-SD-Modul mit Regler (74LVC125A)5 V3,3 V und 5 VUno, Nano, Mega; ESP32 und Pico bei 5-V-Versorgung
SD-Kartenmodul in voller Größe (Pins +5 und +3.3)5 V oder 3,3 VMeist kein echter Pegelwandler3,3-V-Boards; mit 5-V-Signalen unzuverlässig
Micro-SD-Modul ohne Regler (nur Slot)Nur 3,3 VNur 3,3 VESP32, Raspberry Pi Pico
Boards mit eingebautem Slot (z. B. ESP32-CAM)Über das Board3,3 VDirekt mit SD_MMC nutzbar

Wenn du einen Arduino Uno, Nano oder Mega verwendest, nimm ein Micro-SD-Modul mit Regler und Pegelwandler wie auf dem Foto und verbinde VCC mit dem 5V-Pin. ESP32 und Pico arbeiten mit 3,3 V; auch hier kannst du dasselbe Modul nutzen, solltest es aber trotzdem mit 5 V versorgen (beim ESP32 über VIN, beim Pico über VBUS, wenn er per USB versorgt wird). Da der Pegelwandler mit 3,3 V läuft, kommt das MISO-Signal ohnehin mit 3,3 V am Mikrocontroller an. Module ohne Regler werden direkt an den 3V3-Pin angeschlossen; musst du so eines mit einem 5-V-Arduino betreiben, setze in die Leitungen MOSI, SCK und CS je einen Spannungsteiler aus 1 kΩ + 2 kΩ oder verwende einen Logikpegelwandler. Die Widerstandswerte kannst du mit dem Spannungsteiler-Rechner prüfen.

Der häufigste Fehler ist, ein Micro-SD-Modul mit Regler an 3,3 V zu betreiben. Der AMS1117-Regler auf dem Modul verliert etwa 1 V, sodass an der Karte nur rund 2,3 V ankommen, und sie meldet meist initialization failed. Umgekehrt kann 5 V an den Pins eines Moduls ohne Regler die Karte dauerhaft beschädigen. Lies vor dem Anschließen die Beschriftung auf dem Modul und prüfe, ob ein Regler vorhanden ist.

SD-Kartenmodul anschließen: die SPI-Pins

Modul-PinArduino Uno / NanoArduino MegaESP32Raspberry Pi Pico
GNDGNDGNDGNDGND
VCC5V5VVIN (5 V)VBUS (5 V)
MISOD12D50GPIO 19GP16
MOSID11D51GPIO 23GP19
SCKD13D52GPIO 18GP18
CSD10D53GPIO 5GP17

MISO, MOSI und SCK müssen bei jedem Board an die Hardware-SPI-Pins; CS (Chip Select) kann ein beliebiger Digitalpin sein, solange du dieselbe Nummer im Code an SD.begin() übergibst. Bei fertigen Shields ist CS meist D4 oder D10. Du kannst mehrere Geräte an denselben SPI-Bus hängen: Alle teilen sich MISO, MOSI und SCK, jedes bekommt seinen eigenen CS-Pin. Wie SPI funktioniert, erklären wir ausführlich im Beitrag SPI-Kommunikation. Wo die Pins auf deinem Board liegen, zeigt dir das Pinbelegungs-Tool.

SD-Karte vorbereiten: mit FAT32 formatieren

  • Kartengröße: Nimm eine Micro-SDHC-Karte mit 4 bis 32 GB. Die Arduino-SD-Bibliothek unterstützt SDSC- (bis 2 GB) und SDHC-Karten; SDXC-Karten ab 64 GB sind ab Werk mit exFAT formatiert, und das kann diese Bibliothek nicht lesen.
  • Dateisystem: Formatiere die Karte mit FAT32 (bei Karten bis 2 GB geht auch FAT16). NTFS und exFAT funktionieren nicht.
  • Windows: Klicke im Explorer mit der rechten Maustaste auf die Karte, wähle Formatieren und dann FAT32 als Dateisystem mit der Standard-Größe der Zuordnungseinheiten. Bei Karten über 32 GB bietet Windows kein FAT32 an.
  • macOS: Wähle die Karte im Festplattendienstprogramm aus, klicke auf Löschen und wähle als Format MS-DOS-Dateisystem (FAT) und als Schema Master Boot Record.
  • Am sichersten: Das kostenlose Programm SD Card Formatter der SD Association formatiert die Karte normgerecht und beseitigt die meisten seltsamen Fehler.
  • Nur eine Partition: Die Karte sollte genau eine Partition haben. Karten, die schon in einem Raspberry Pi oder einer Kamera steckten, haben oft noch mehrere; lösche sie vor dem Formatieren.
Die SD-Bibliothek auf dem Arduino Uno kennt nur kurze Dateinamen im 8.3-Format: höchstens 8 Zeichen für den Namen und 3 für die Endung, ohne Leer- oder Sonderzeichen wie Umlaute. DATEN.CSV oder LOG01.TXT funktionieren, ein langer Name wie temperatur-log.csv lässt SD.open() dagegen stillschweigend scheitern. Auf ESP32 und Pico kannst du problemlos lange Dateinamen verwenden.

Erster Test Schritt für Schritt: auf die SD-Karte schreiben und lesen

  1. Stecke die formatierte Karte in das Modul und verbinde das Modul laut Tabelle oben mit dem Arduino.
  2. Die SD-Bibliothek ist in der Arduino IDE enthalten, du musst nichts installieren; am Anfang des Sketches bindest du nur SPI.h und SD.h ein.
  3. Lade den folgenden Code hoch und öffne den Seriellen Monitor mit 9600 Baud.
  4. Siehst du "tamam" (OK) und den Dateiinhalt, sind Karte und Verkabelung in Ordnung. Bei jedem Start wird eine neue Zeile an TEST.TXT angehängt.
  5. Wenn du die Karte herausnimmst und in den Computer steckst, kannst du TEST.TXT mit jedem Texteditor öffnen.
Arduino (C++)
1#include <SPI.h>
2#include <SD.h>
3
4const int CS_PIN = 10;                           // modülün CS pini / module CS pin
5
6void setup() {
7  Serial.begin(9600);
8  Serial.print(F("SD kart baslatiliyor... "));
9  if (!SD.begin(CS_PIN)) {                       // kart başlatılamadı / card init failed
10    Serial.println(F("initialization failed"));
11    while (true);                                // burada dur / stop here
12  }
13  Serial.println(F("tamam"));
14
15  File dosya = SD.open("TEST.TXT", FILE_WRITE);  // yoksa oluşturur, sona ekler / creates it, appends
16  if (dosya) {
17    dosya.println(F("Merhaba BlueGrays!"));
18    dosya.close();                               // tamponu karta yazar / flushes the buffer to the card
19    Serial.println(F("TEST.TXT yazildi"));
20  } else {
21    Serial.println(F("TEST.TXT acilamadi"));     // dosya açılamadı / could not open file
22  }
23
24  dosya = SD.open("TEST.TXT");                   // okumak için aç / open for reading
25  if (dosya) {
26    Serial.print(F("Boyut (bayt): "));
27    Serial.println(dosya.size());
28    while (dosya.available()) {
29      Serial.write(dosya.read());                // içeriği seri porta yaz / print contents to serial
30    }
31    dosya.close();
32  }
33}
34
35void loop() {
36}
FunktionWas sie macht
SD.begin(cs)Initialisiert die Karte; liefert bei Erfolg true
SD.open("NAME.TXT", FILE_WRITE)Öffnet die Datei zum Schreiben; legt sie an, falls sie fehlt, sonst wird ans Ende angehängt
SD.open("NAME.TXT")Öffnet die Datei zum Lesen (FILE_READ)
datei.print() / println()Schreibt Text oder eine Zahl in die Datei
datei.flush()Schreibt den Pufferinhalt auf die Karte, ohne die Datei zu schließen
datei.close()Schreibt die restlichen Daten auf die Karte und schließt die Datei
datei.available() / read()Prüft, ob noch Bytes zu lesen sind / liest ein Byte
SD.exists() / SD.remove() / SD.mkdir()Prüft, ob eine Datei existiert / löscht eine Datei / legt einen Ordner an

Sensordaten als CSV speichern, mit RTC-Zeitstempel

Das praktischste Dateiformat für einen Datenlogger ist CSV (kommagetrennte Werte): Jede Zeile ist eine Messung, jede Spalte ein Wert, und in der ersten Zeile stehen die Spaltenüberschriften. Damit du weißt, wann gemessen wurde, gehört in jede Zeile Datum und Uhrzeit. millis() liefert nur die Zeit seit dem Einschalten des Arduino und beginnt nach jedem Reset bei null; deshalb verwenden wir ein RTC-Modul (Echtzeituhr) mit Knopfzelle. Die RTC zählt weiter, auch wenn der Arduino ausgeschaltet ist. Der DS1307 ist günstig, kann aber ein paar Sekunden pro Tag abweichen; der DS3231 weicht dank seines temperaturkompensierten Quarzes nur etwa eine Minute pro Jahr ab. Den Vergleich findest du im Beitrag RTC-Uhrenmodule.

DS1307 RTC-Uhrenmodul
Das DS1307-RTC-Modul wird über I2C (SDA, SCL) angeschlossen und hält dank Knopfzelle die Uhrzeit, auch wenn der Arduino aus ist.

Die Schaltung: Das SD-Modul kommt wie in der Tabelle oben an die SPI-Pins, das RTC-Modul an den I2C-Bus (beim Uno SDA = A4, SCL = A5, VCC = 5V) und der Datenpin des DHT22 an D2; bei einem nackten Sensor gehört ein 10-kΩ-Widerstand zwischen Datenpin und VCC. Installiere im Bibliotheksverwalter die Bibliotheken RTClib (Adafruit) und DHT sensor library. Details zum Anschluss des Sensors findest du im Beitrag DHT11- und DHT22-Temperatur- und Feuchtesensor.

Arduino (C++)
1#include <SPI.h>
2#include <SD.h>
3#include <Wire.h>
4#include <RTClib.h>
5#include <DHT.h>
6
7const int CS_PIN = 10;                           // SD modülü CS / SD module CS
8const unsigned long ARALIK = 10000;              // 10 saniyede bir kayıt / log every 10 seconds
9
10RTC_DS1307 rtc;                                  // DS3231 için RTC_DS3231 / RTC_DS3231 for a DS3231
11DHT dht(2, DHT22);                               // veri pini D2, DHT11 de olur / data pin D2, DHT11 also works
12unsigned long sonKayit = 0;
13
14void setup() {
15  Serial.begin(9600);
16  dht.begin();
17  if (!rtc.begin()) {
18    Serial.println(F("RTC bulunamadi"));         // RTC yok / RTC not found
19    while (true);
20  }
21  if (!rtc.isrunning()) {                        // saat hiç kurulmamış / clock never set
22    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));  // derleme anına kur / set to compile time
23  }
24  if (!SD.begin(CS_PIN)) {
25    Serial.println(F("SD kart hatasi"));         // SD başlatılamadı / SD init failed
26    while (true);
27  }
28  if (!SD.exists("VERI.CSV")) {                  // yeni dosyaya başlık satırı / header row for a new file
29    File f = SD.open("VERI.CSV", FILE_WRITE);
30    if (f) {
31      f.println(F("tarih,saat,sicaklik_C,nem_yuzde"));
32      f.close();
33    }
34  }
35}
36
37void loop() {
38  if (millis() - sonKayit < ARALIK) return;      // zamanı gelmedi / not time yet
39  sonKayit = millis();
40
41  float t = dht.readTemperature();
42  float h = dht.readHumidity();
43  if (isnan(t) || isnan(h)) {                    // sensör okunamadı / sensor read failed
44    Serial.println(F("DHT okuma hatasi"));
45    return;
46  }
47
48  DateTime simdi = rtc.now();
49  char ts[8], hs[8], satir[48];
50  dtostrf(t, 1, 1, ts);                          // AVR'de sprintf %f desteklemez / AVR sprintf has no %f
51  dtostrf(h, 1, 1, hs);
52  snprintf(satir, sizeof(satir), "%04d-%02d-%02d,%02d:%02d:%02d,%s,%s",
53           simdi.year(), simdi.month(), simdi.day(),
54           simdi.hour(), simdi.minute(), simdi.second(), ts, hs);
55
56  File f = SD.open("VERI.CSV", FILE_WRITE);      // sona ekle / append
57  if (f) {
58    f.println(satir);
59    f.close();                                   // her kayıtta kapat: güç kesilse de veri kalır / close every time so data survives a power cut
60    Serial.println(satir);
61  } else {
62    Serial.println(F("VERI.CSV acilamadi"));
63  }
64}

Der Code liest alle 10 Sekunden Temperatur und Luftfeuchtigkeit, holt Datum und Uhrzeit von der RTC und hängt eine Zeile wie 2026-11-04,14:05:30,23.5,45.2 an VERI.CSV an. Weil die Datei nach jedem Eintrag geschlossen wird, bleiben die bisherigen Daten selbst bei einem Stromausfall erhalten. Auf AVR-Boards unterstützt sprintf() keine Gleitkommazahlen (%f), deshalb werden die Werte zuerst mit dtostrf() in Text umgewandelt. Da die Wartezeit mit millis() statt delay() gelöst ist, kann loop() nebenbei noch andere Aufgaben erledigen. Wurde die RTC noch nie gestellt, wird sie auf den Zeitpunkt der Kompilierung gesetzt. Bei einer DS3231 schreibst du einfach RTC_DS3231 statt RTC_DS1307 und prüfst lostPower() statt isrunning().

Wie viel Platz braucht das? Eine Zeile hat etwa 31 Byte. Bei einem Eintrag alle 10 Sekunden entstehen 8.640 Zeilen pro Tag, also etwa 260 KB; in einem Jahr sind das ungefähr 95 MB. Eine 8-GB-Karte reicht bei diesem Tempo also jahrzehntelang. Die eigentliche Grenze ist nicht die Karte, sondern die Stromversorgung: Wenn das Projekt mit Batterien laufen soll, berechne vorher mit dem Akkulaufzeit-Rechner, wie lange sie halten.

Daten von der SD-Karte in Excel öffnen

  1. Trenne den Arduino von der Stromversorgung, nimm die Karte aus dem Modul und stecke sie in den Computer.
  2. Kopiere VERI.CSV auf den Computer; mit einer Kopie zu arbeiten ist sicherer als direkt auf der Karte.
  3. Öffne in Excel eine leere Arbeitsmappe und wähle die Datei über Daten > Aus Text/CSV aus.
  4. Wähle im Vorschaufenster Komma als Trennzeichen und klicke auf Laden; die Spalten werden in Datum, Uhrzeit, Temperatur und Luftfeuchtigkeit aufgeteilt.
  5. Markiere die Spalten Temperatur und Luftfeuchtigkeit und füge über die Registerkarte Einfügen ein Liniendiagramm ein, um den Verlauf über die Zeit zu sehen.
Im deutschen Excel ist das Komma das Dezimaltrennzeichen und der Punkt das Datumstrennzeichen. Ein Wert wie 23.5 wird deshalb oft nicht als Zahl erkannt, sondern als Text, als Datum (23. Mai) oder als falsche Zahl angezeigt. Es gibt zwei Lösungen: Beim Import auf Daten transformieren klicken und die Spalten Temperatur und Luftfeuchtigkeit mit dem Gebietsschema Englisch (USA) in Dezimalzahlen umwandeln, oder den Code wie unten so ändern, dass er Semikolon als Trennzeichen und Komma als Dezimalzeichen schreibt. Bei der zweiten Variante genügt ein Doppelklick auf die Datei, und Excel trennt die Spalten von selbst.
Arduino (C++)
1// Excel'de ondalık ayırıcı virgülse / if Excel uses a decimal comma
2// Bu iki fonksiyonu kayıt kodunda loop()'un üstüne ekle / add these two functions above loop() in the logging sketch
3void noktayiVirgulYap(char *s) {
4  for (; *s; s++) {
5    if (*s == '.') *s = ',';                     // 23.5 -> 23,5
6  }
7}
8
9void excelSatiri(char *satir, size_t boyut, const DateTime &simdi, char *ts, char *hs) {
10  noktayiVirgulYap(ts);
11  noktayiVirgulYap(hs);
12  snprintf(satir, boyut, "%04d-%02d-%02d;%02d:%02d:%02d;%s;%s",   // ayırıcı ; / separator ;
13           simdi.year(), simdi.month(), simdi.day(),
14           simdi.hour(), simdi.minute(), simdi.second(), ts, hs);
15}
16
17// loop() içinde snprintf satırının yerine / in loop(), replace the snprintf line with:
18//   excelSatiri(satir, sizeof(satir), simdi, ts, hs);
19// Başlık satırı da / header row too: tarih;saat;sicaklik_C;nem_yuzde

Wenn du die Messwerte lieber live und ohne Karte in Excel übertragen willst, solange der Arduino am Computer hängt, sieh dir die Methoden mit Data Streamer und PLX-DAQ im Beitrag Arduino-Daten an Excel senden an. Für Projekte, die fernab vom Computer draußen laufen, ist die SD-Karte dagegen unverzichtbar.

SD-Karte mit dem ESP32 nutzen (SPI)

Der Arduino-Core des ESP32 bringt eine eigene SD-Bibliothek mit, die fast genauso funktioniert, aber drei wichtige Unterschiede hat: Dateipfade beginnen mit / ("/olcumler.csv"), lange Dateinamen sind erlaubt, und FILE_WRITE überschreibt die Datei komplett. Zum Anhängen musst du FILE_APPEND verwenden; übernimmst du den Uno-Code unverändert, werden deine alten Daten bei jedem Start gelöscht. Die Standard-SPI-Pins sind SCK 18, MISO 19 und MOSI 23, für CS wird meist GPIO 5 verwendet. Kartentyp und Größe lassen sich mit einer Zeile auslesen:

Arduino (C++)
1#include <SPI.h>
2#include <SD.h>
3
4const int CS_PIN = 5;                            // VSPI: SCK 18, MISO 19, MOSI 23 / default VSPI pins
5const char *DOSYA = "/olcumler.csv";             // yol / ile başlar / path starts with /
6
7void setup() {
8  Serial.begin(115200);
9  if (!SD.begin(CS_PIN)) {                       // varsayılan SPI hızı 4 MHz / default SPI clock 4 MHz
10    Serial.println("Card Mount Failed");
11    return;
12  }
13  uint8_t tur = SD.cardType();
14  if (tur == CARD_NONE) {
15    Serial.println("Kart takili degil");         // kart yok / no card inserted
16    return;
17  }
18  Serial.printf("Kart tipi: %s\n", tur == CARD_SDHC ? "SDHC" : (tur == CARD_SD ? "SDSC" : "MMC"));
19  Serial.printf("Boyut: %llu MB\n", SD.cardSize() / (1024 * 1024));
20
21  if (!SD.exists(DOSYA)) {                       // uzun dosya adı serbest / long file names are fine
22    File f = SD.open(DOSYA, FILE_WRITE);         // FILE_WRITE dosyayı sıfırlar / FILE_WRITE truncates
23    if (f) {
24      f.println("sure_s,isik_ham");
25      f.close();
26    }
27  }
28}
29
30void loop() {
31  File f = SD.open(DOSYA, FILE_APPEND);          // ESP32'de sona ekleme / append on ESP32
32  if (f) {
33    f.printf("%lu,%d\n", millis() / 1000, analogRead(34));   // GPIO34'teki LDR / LDR on GPIO34
34    f.close();
35  }
36  delay(5000);
37}

Der Code speichert alle 5 Sekunden den Rohwert (0–4095) eines LDR an GPIO 34. Für die echte Uhrzeit brauchst du beim ESP32 nicht einmal ein RTC-Modul: Er kann sich mit dem WLAN verbinden, die Zeit von einem NTP-Server holen und mit getLocalTime() jede Zeile mit einem Zeitstempel versehen. Bei langen Kabeln oder unzuverlässiger Karte senkst du die SPI-Geschwindigkeit: SD.begin(5, SPI, 1000000) startet die Karte mit 1 MHz. Bei einem batteriebetriebenen Logger verlängert Deep Sleep zwischen den Messungen die Laufzeit um ein Vielfaches.

ESP32 SD_MMC: die schnelle SD-Schnittstelle und die ESP32-CAM

Neben SPI hat der ESP32 auch einen SDMMC-Controller, der das schnelle Protokoll der Karte selbst spricht. Im 4-Bit-Modus ist die SD_MMC-Bibliothek um ein Mehrfaches schneller als SPI und eignet sich ideal für große Dateien wie Fotos oder Audio. Beim klassischen ESP32 sind die Pins fest vorgegeben: CLK GPIO 14, CMD GPIO 15, D0 GPIO 2, D1 GPIO 4, D2 GPIO 12, D3 GPIO 13; diese Leitungen brauchen 10-kΩ-Pull-up-Widerstände. Im 1-Bit-Modus werden nur CLK, CMD und D0 genutzt; das ist langsamer, aber GPIO 4, 12 und 13 werden frei. Der Micro-SD-Slot der ESP32-CAM ist genau mit diesen Pins verbunden, und der 1-Bit-Modus verhindert, dass die Blitz-LED an GPIO 4 bei jedem Kartenzugriff aufblitzt.

Arduino (C++)
1#include "FS.h"
2#include "SD_MMC.h"
3
4void setup() {
5  Serial.begin(115200);
6  // 1-bit mod: yalnız CLK 14, CMD 15, D0 2 / 1-bit mode: only CLK 14, CMD 15, D0 2
7  if (!SD_MMC.begin("/sdcard", true)) {
8    Serial.println("SD_MMC baglanamadi");        // kart bağlanamadı / mount failed
9    return;
10  }
11  Serial.printf("Bos alan: %llu MB\n", (SD_MMC.totalBytes() - SD_MMC.usedBytes()) / (1024 * 1024));
12
13  File f = SD_MMC.open("/gunluk.txt", FILE_APPEND);
14  if (f) {
15    f.println("ESP32-CAM acildi");               // açılış kaydı / boot log line
16    f.close();
17  }
18}
19
20void loop() {
21}
GPIO 12 ist ein Strapping-Pin, der beim Booten des ESP32 die Spannung des Flash-Speichers festlegt. Im 4-Bit-Modus kann der Pull-up-Widerstand an der D2-Leitung dazu führen, dass manche Module gar nicht mehr starten; nutze in diesem Fall den 1-Bit-Modus. Bei neueren Chips wie dem ESP32-S3 kannst du die Pins mit SD_MMC.setPins() frei wählen.

SD-Karte mit dem Raspberry Pi Pico (MicroPython)

In MicroPython übernimmt der Treiber sdcard.py aus micropython-lib die SD-Karte. Wenn du mpremote auf dem Computer hast, installierst du ihn mit mpremote mip install sdcard, oder du kopierst die Datei mit Thonny auf den Pico. Die Karte wird mit os.mount() als Ordner /sd eingebunden und danach mit ganz normalen Python-Dateibefehlen (open, write) benutzt. Der folgende Code liest den eingebauten Temperatursensor des Pico und schreibt alle 10 Sekunden eine CSV-Zeile. Wenn der Pico neu für dich ist, lies zuerst Was ist der Raspberry Pi Pico?.

MicroPython
1from machine import Pin, SPI, ADC
2import os, time
3import sdcard                                    # micropython-lib sürücüsü / micropython-lib driver
4
5spi = SPI(0, baudrate=1000000, sck=Pin(18), mosi=Pin(19), miso=Pin(16))
6sd = sdcard.SDCard(spi, Pin(17, Pin.OUT))        # CS = GP17; kart yoksa OSError / OSError if no card
7os.mount(os.VfsFat(sd), "/sd")                   # kart artık /sd klasörü / the card is now the /sd folder
8
9sensor = ADC(4)                                  # dahili sıcaklık sensörü / internal temperature sensor
10DOSYA = "/sd/pico_log.csv"
11
12if "pico_log.csv" not in os.listdir("/sd"):      # yeni dosyaya başlık / header for a new file
13    with open(DOSYA, "w") as f:
14        f.write("tarih,saat,sicaklik_C\n")
15
16while True:
17    v = sensor.read_u16() * 3.3 / 65535
18    t = 27 - (v - 0.706) / 0.001721              # RP2040 veri sayfası formülü / RP2040 datasheet formula
19    y, ay, g, sa, dk, sn = time.localtime()[:6]
20    with open(DOSYA, "a") as f:                  # "a" = sona ekle / append
21        f.write("{:04d}-{:02d}-{:02d},{:02d}:{:02d}:{:02d},{:.1f}\n".format(y, ay, g, sa, dk, sn, t))
22    print(sa, dk, sn, t)
23    time.sleep(10)                               # 10 saniye bekle / wait 10 seconds

Der Pico hat keine batteriegepufferte Uhr: Ist er mit Thonny verbunden, wird seine Uhr automatisch vom Computer gestellt, läuft er allein, beginnt sie am 1. Januar 2021. Für genaue Zeitstempel kannst du ein DS3231-Modul ergänzen oder beim Pico W die Zeit per NTP aus dem Internet holen. Steckt keine Karte oder stimmt die Verkabelung nicht, meldet der Treiber OSError: no SD card. Programmierst du den Pico mit der Arduino IDE (arduino-pico-Core), kannst du dasselbe Vorgehen mit der SD-Bibliothek nutzen; die Standard-SPI0-Pins entsprechen der Tabelle, und für CS schreibst du einfach SD.begin(17).

Datenverlust vermeiden: Stromversorgung, Schreibhäufigkeit und Lebensdauer der Karte

  • Ohne close() oder flush() landet nichts auf der Karte: Die Bibliothek sammelt die Daten zuerst in einem 512-Byte-Puffer. Hältst du die Datei dauerhaft offen, rufe alle paar Zeilen flush() auf.
  • Karte nicht während des Schreibens entfernen: Wird die Karte beim Schreiben gezogen oder der Strom unterbrochen, kann das Dateisystem beschädigt werden. Ein Taster zum Beenden der Aufzeichnung und eine LED, die eine laufende Aufzeichnung anzeigt, sind eine gute Angewohnheit.
  • Für stabile Versorgung sorgen: Beim Schreiben zieht die Karte bis zu 100 mA. Ein Kondensator mit 10–100 µF zwischen VCC und GND des Moduls verringert Spannungseinbrüche und zufällige Schreibfehler.
  • Nicht zu oft öffnen und schließen: Bei Dutzenden Messungen pro Sekunde ist Öffnen und Schließen für jede Zeile zu langsam; sammle die Werte im RAM und schreibe sie in Blöcken von 10–20 Zeilen.
  • Lebensdauer der Karte: SD-Karten verteilen Schreibvorgänge intern auf verschiedene Zellen (Wear Leveling); ein Logger mit ein paar Zeilen pro Minute nutzt die Karte jahrelang nicht ab. Nimm trotzdem eine Karte eines bekannten Herstellers.
  • Dateien aufteilen: Eine eigene Datei pro Tag (z. B. 20261104.CSV) hält die Dateien klein, und bei einem Problem verlierst du nur die Daten dieses Tages.

Projektideen mit dem SD-Kartenmodul

  • Wetterstation mit Logger: Zeichne mit einem BME280 stündlich Temperatur, Luftfeuchtigkeit und Luftdruck auf und erstelle ein Diagramm über eine ganze Jahreszeit.
  • Bewässerungsprotokoll: Speichere die Werte eines Bodenfeuchtesensors und die Laufzeiten der Pumpe, um dein Gießverhalten auszuwerten.
  • GPS-Routenlogger: Speichere deine Rad- oder Wanderroute mit einem NEO-6M-GPS als CSV und zeige sie danach auf einer Karte an.
  • Zutrittsprotokoll mit Karten: Schreibe jede mit einem RFID RC522 gelesene Karte mit Datum und Uhrzeit in eine Datei.
  • Energieverbrauch messen: Miss und protokolliere mit einem ACS712-Stromsensor, wie viel Strom ein Gerät über den Tag zieht.
  • MP3-Player: Der DFPlayer Mini spielt Audiodateien von seinem eigenen Micro-SD-Slot ab; der Arduino schickt nur Befehle.

Typische Fehler und ihre Lösungen

SymptomMögliche UrsacheLösung
"initialization failed"Keine Karte eingesteckt, falsche Verkabelung oder CS-Pin passt nicht zum CodePrüfe, ob MISO, MOSI und SCK an den Hardware-SPI-Pins liegen und die CS-Nummer in SD.begin() stimmt
"initialization failed" (Verkabelung stimmt)Modul mit Regler an 3,3 V betrieben oder schwache VersorgungModul mit 5 V versorgen, Kabel kürzen, Kondensator zwischen VCC und GND setzen
"Could not find FAT16/FAT32 partition"Karte ist mit exFAT oder NTFS formatiert; SDXC-Karte ab 64 GBEine Karte bis 32 GB mit FAT32 formatieren
Datei lässt sich nicht öffnen ("error opening")Dateiname verletzt die 8.3-Regel oder vorherige Datei wurde nicht geschlossenKurzen Namen wie VERI.CSV verwenden und jede Datei mit close() schließen
Datei ist leer oder die letzten Zeilen fehlenStrom wurde vor close() oder flush() unterbrochenDatei nach jedem Eintrag schließen oder regelmäßig flush() aufrufen
SD-Karte geht nicht mehr, sobald ein weiteres SPI-Gerät dazukommtCS des anderen Geräts hängt offen oder das Modul gibt die MISO-Leitung nicht freiAlle CS-Pins am Anfang von setup() auf OUTPUT und HIGH setzen; notfalls ein Modul verwenden, das MISO freigibt
Der Uno hängt sich auf oder verhält sich seltsamZu wenig RAM: Die SD-Bibliothek braucht etwa 650 Byte, der Puffer eines OLED-Displays 1 KBTexte mit F() schreiben; notfalls auf Mega oder ESP32 umsteigen
Beim ESP32 werden alte Daten bei jedem Start gelöschtDatei wird mit FILE_WRITE geöffnetZum Anhängen FILE_APPEND verwenden
"Card Mount Failed" beim ESP32Versorgung, Verkabelung, zu hohe SPI-Geschwindigkeit oder fehlende Pull-ups bei SD_MMCSPI-Takt auf 1 MHz senken; bei SD_MMC den 1-Bit-Modus testen
Am schnellsten findest du die Ursache mit dem Beispiel Datei > Beispiele > SD > CardInfo in der Arduino IDE. Zeigt es den Kartentyp (SD1, SD2 oder SDHC), findet aber keine Partition, liegt es an der Formatierung; kann es nicht einmal den Kartentyp anzeigen, prüfe Verkabelung und Stromversorgung.

Ein SD-Kartenmodul macht aus einem Projekt, das nur misst, ein Gerät, das Buch führt, und ein paar Tage echter Messdaten verraten viel mehr als ein einzelner Momentwert. In der BlueGrays-App findest du den ESP32-Temperaturlogger mit DHT22, DS1307-RTC, Micro-SD und OLED, Digitaluhren mit RTC sowie Temperatur- und Feuchtigkeitsprojekte, jeweils mit Schaltplänen und Code Schritt für Schritt.

Häufige Fragen

Wie groß darf die SD-Karte für den Arduino sein?

Die Standard-SD-Bibliothek des Arduino unterstützt SDSC- und SDHC-Karten mit FAT16 oder FAT32, also Karten bis 32 GB. SDXC-Karten ab 64 GB sind mit exFAT formatiert und lassen sich mit dieser Bibliothek nicht lesen. Für einen Datenlogger reicht eine Karte mit 4–16 GB mehr als aus.

Warum meldet die SD-Karte "initialization failed"?

Die häufigsten Ursachen sind ein falscher CS-Pin, MISO, MOSI oder SCK nicht an den Hardware-SPI-Pins, eine nicht mit FAT32 formatierte Karte und ein Modul mit Regler, das an 3,3 V hängt. Führe zuerst das Beispiel CardInfo aus und probiere dann kürzere Kabel und eine 5-V-Versorgung des Moduls.

Funktioniert ein SD-Kartenmodul mit 3,3 V?

Module ohne Regler laufen direkt mit 3,3 V und passen zu ESP32 oder Pico. Micro-SD-Module mit Regler und Pegelwandler brauchen dagegen 4,5–5,5 V; an 3,3 V bekommt die Karte zu wenig Spannung. Diese Module versorgst du beim ESP32 über VIN und beim Pico über VBUS.

Wie öffne ich die CSV-Datei vom Arduino in Excel?

Kopiere die Datei auf den Computer und importiere sie in Excel über Daten > Aus Text/CSV mit Komma als Trennzeichen. Da das deutsche Excel das Komma als Dezimaltrennzeichen nutzt, können Zahlen falsch erscheinen; wandle die Spalten dann mit dem Gebietsschema Englisch (USA) um oder verwende im Code Semikolon als Trennzeichen.

Wie oft kann der Arduino auf die SD-Karte schreiben?

Ein paar Zeilen pro Sekunde sind kein Problem, aber das Öffnen und Schließen der Datei für jede Zeile kostet Zeit. Bei schnellen Messungen sammelst du die Daten im RAM und schreibst sie blockweise, oder du lässt die Datei offen und rufst regelmäßig flush() auf. Bei langsamen Intervallen wie einem Eintrag pro Minute ist Öffnen-Schreiben-Schließen jedes Mal die sicherste Methode.

Kann ich ein SD-Kartenmodul zusammen mit RFID oder einem TFT-Display nutzen?

Ja, SPI-Geräte teilen sich die Leitungen MISO, MOSI und SCK, und jedes hat einen eigenen CS-Pin. Gibt es Probleme, setze alle CS-Pins am Anfang von setup() auf OUTPUT und HIGH. Der Pegelwandler mancher billiger Micro-SD-Module gibt die MISO-Leitung nie frei; nimm dann ein Modul, das sie freigibt, oder beim ESP32 einen zweiten SPI-Bus.

Alle Projekte ansehen
Temperatur und Luftfeuchtigkeit mit DHT11
#55Mittel

Temperatur und Luftfeuchtigkeit mit DHT11

Wie warm ist dein Zimmer, und ist die Luft feucht oder trocken? Der DHT11-Sensor misst Temperatur und Luftfeuchtigkeit, und der Arduino schreibt die Werte auf ein zweizeiliges LCD und aktualisiert sie

4.7(47)
64
ESP32 Temperatur-Datenlogger (DHT22 + DS1307 RTC + microSD + OLED)
#144Fortgeschritten
Premium

ESP32 Temperatur-Datenlogger (DHT22 + DS1307 RTC + microSD + OLED)

Baue einen zeitgestempelten Temperaturlogger mit ESP32! Lese Temperatur/Feuchtigkeit vom DHT22 jede Minute, hole die aktuelle Zeit vom DS1307 RTC und protokolliere auf microSD-Karte als CSV. Das OLED zeigt live Temperatur (große Schrift), Luftfeuchtigkeit, Zeitstempel und Logzähler. Die `/temp_log.csv`-Datei auf der SD-Karte öffnet sich in Excel, Google Sheets oder Python pandas zur Analyse — perfekt für Gewächshausüberwachung, Raumtemperaturverfolgung, Laboraufzeichnung, Lebensmittellageru

4.7(7)
12
Digitale Uhr mit ESP32 und RTC DS1307 (I2C + LCD)
#120Mittel
Premium

Digitale Uhr mit ESP32 und RTC DS1307 (I2C + LCD)

In diesem Projekt zeigen wir Uhrzeit und Datum auf einem 16x2-I2C-LCD-Display mithilfe des DS1307-Echtzeituhrmoduls (RTC) an. Das DS1307 ist ein batteriegestütztes RTC, das die Uhrzeit auch dann beibehält, wenn das ESP32 ausgeschaltet ist. Beide Module teilen sich denselben I2C-Bus (SDA/SCL), sodass wir mit nur zwei Signalkabeln die Steuerung mehrerer Geräte erlernen. So lernen Sie das I2C-Protokoll und die Funktionsweise von RTC-Modulen in der Praxis kennen.

4.6(26)
40
ESP32 DHT22 Temperatur und Luftfeuchtigkeit (mit LCD-Display)
#117Mittel

ESP32 DHT22 Temperatur und Luftfeuchtigkeit (mit LCD-Display)

Bei diesem Projekt werden die Umgebungstemperatur und die Luftfeuchtigkeit mit einem DHT22-Sensor gemessen und in Echtzeit auf einem 16x2 I2C-LCD angezeigt. Mithilfe der Adafruit-DHT-Bibliothek werden die Daten über das One-Wire-Protokoll vom Sensor ausgelesen. Dieses Projekt bildet die Grundlage für IoT-Wetterstationen, Smart-Home-Automatisierung oder Umgebungsüberwachungssysteme in Gewächshäusern. Die Kommunikation mit dem DHT22 erfolgt über den GPIO-4-Pin des ESP32.

4.8(38)
54
ESP32 Deep Sleep – Batteriesparmodus (OLED + RTC-RAM-Zähler)
#135Fortgeschritten
Premium

ESP32 Deep Sleep – Batteriesparmodus (OLED + RTC-RAM-Zähler)

Der Deep-Sleep-Modus des ESP32 senkt den Stromverbrauch auf etwa 10 µA, indem er die CPU und die meisten Peripheriegeräte abschaltet, und ist für batteriebetriebene IoT-Geräte von entscheidender Bedeutung. In diesem Projekt verwenden wir drei verschiedene Weckquellen: den Timer (15 s), einen externen Pin (EXT0 – Taste GPIO 33) und die Berührungserkennung (T0/GPIO 4). Mit `RTC_DATA_ATTR` markierte Variablen bleiben während des Deep-Sleep-Modus erhalten – der Boot-Zähler, der Timer-Wake-Zähler und

4.3(10)
16
ESP32: Echtzeit aus dem Internet per NTP
#128Fortgeschritten
Premium

ESP32: Echtzeit aus dem Internet per NTP

Der ESP32 verbindet sich mit dem WLAN und ruft die Echtzeit mit Millisekunden-Genauigkeit von NTP-Servern (Network Time Protocol) ab. Dank `configTzTime()` wird die türkische Zeitzone (TRT, UTC+3) automatisch angewendet, und der DST-Wechsel wird per POSIX-TZ-String verwaltet. Die Uhrzeit wird auf dem Serial Monitor und einem optionalen I2C-LCD ausgegeben. `configTzTime()` startet den SNTP-Dienst; bei verfügbarem Netzwerkzugang erfolgt regelmäßig eine erneute Synchronisierung, und zwischen den Sy

4.5(13)
21
Punktmatrix-Uhr, Kalender und Wetterstation (MAX7219, DS1307)
#85Mittel
Premium

Punktmatrix-Uhr, Kalender und Wetterstation (MAX7219, DS1307)

Eine Laufschrift-Tafel für Tisch oder Wand, die abwechselnd Uhrzeit, Datum und das Raumklima zeigt. Auf dem 8x32-LED-Display erscheint zuerst die Temperatur in Celsius und Fahrenheit, dann die Luftfeu

5.0(50)
66
DS1302 RTC-Uhr mit LCD-Anzeige
#46Mittel
Premium

DS1302 RTC-Uhr mit LCD-Anzeige

Eine kleine Tischuhr, die die Zeit auch bei Stromausfall nicht vergisst. Das Uhrmodul DS1302 hält die Zeit mit seiner eigenen kleinen Batterie; jede Sekunde liest der Arduino sie aus und schreibt Uhrz

4.7(41)
51