ESP32 , przykład użycia karty SD aruino
Kluczowe punkty
Praktyczne zastosowania
––––––––––––––––––––––––––––––––––––––––––––
Przykład 1: SPI + SD.h (uniwersalny, zalecany na start)
#include <FS.h>
#include <SD.h>
#include <SPI.h>
// Domyślne piny VSPI w ESP32:
static constexpr int PIN_CS = 5; // można zmienić
static constexpr int PIN_SCK = 18;
static constexpr int PIN_MISO= 19;
static constexpr int PIN_MOSI= 23;
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
Serial.printf("Listing: %s\n", dirname);
File root = fs.open(dirname);
if(!root || !root.isDirectory()){
Serial.println("- failed to open dir");
return;
}
File file = root.openNextFile();
while(file){
if(file.isDirectory()){
Serial.print(" DIR : "); Serial.println(file.name());
if(levels){ listDir(fs, file.name(), levels - 1); }
} else {
Serial.print(" FILE: "); Serial.print(file.name());
Serial.print(" SIZE: "); Serial.println(file.size());
}
file = root.openNextFile();
}
}
void writeFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Writing file: %s\n", path);
File file = fs.open(path, FILE_WRITE);
if(!file){ Serial.println("- failed to open file"); return; }
if(file.print(message)) Serial.println("- file written");
else Serial.println("- write failed");
file.close();
}
void appendFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Appending to: %s\n", path);
File file = fs.open(path, FILE_APPEND);
if(!file){ Serial.println("- failed to open file"); return; }
if(file.print(message)) Serial.println("- message appended");
else Serial.println("- append failed");
file.close();
}
void readFile(fs::FS &fs, const char * path){
Serial.printf("Reading file: %s\n", path);
File file = fs.open(path);
if(!file){ Serial.println("- failed to open file"); return; }
while(file.available()) Serial.write(file.read());
Serial.println();
file.close();
}
void setup(){
Serial.begin(115200);
delay(200);
// Jeśli zmieniasz piny, jawnie zainicjalizuj SPI:
SPI.begin(PIN_SCK, PIN_MISO, PIN_MOSI, PIN_CS);
// Bezpieczna częstotliwość startowa 4 MHz (opcjonalnie):
if(!SD.begin(PIN_CS, SPI, 4000000)){
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD.cardType();
if(cardType == CARD_NONE){ Serial.println("No SD card attached"); return; }
Serial.print("Card type: ");
if(cardType == CARD_MMC) Serial.println("MMC");
else if(cardType == CARD_SD) Serial.println("SDSC");
else if(cardType == CARD_SDHC) Serial.println("SDHC/SDXC");
else Serial.println("UNKNOWN");
Serial.printf("Card size: %llu MB\n", SD.cardSize() / (1024ULL*1024ULL));
listDir(SD, "/", 1);
writeFile(SD, "/test.txt", "Hello ESP32 + SD!\n");
appendFile(SD, "/test.txt", "Second line.\n");
readFile(SD, "/test.txt");
}
void loop(){}
Przykład 2: SD_MMC (ESP32‑CAM i projekty wymagające większej przepustowości)
#include <FS.h>
#include <SD_MMC.h>
// Uwaga: w ESP32‑CAM piny SD_MMC są już predefiniowane na płytce.
// Tryb 1‑bit ułatwia okablowanie w innych projektach.
void setup(){
Serial.begin(115200);
delay(200);
// true = 1‑bit mode (D0,CMD,CLK). Dla ESP32‑CAM często używa się 4‑bit (false),
// ale 1‑bit bywa stabilniejszy na długich ścieżkach/przewodach.
if(!SD_MMC.begin("/sdcard", /*mode1bit=*/true)){
Serial.println("SD_MMC Mount Failed");
return;
}
uint8_t cardType = SD_MMC.cardType();
if(cardType == CARD_NONE){ Serial.println("No SD card"); return; }
Serial.printf("Card size: %llu MB\n", SD_MMC.cardSize() / (1024ULL*1024ULL));
File f = SD_MMC.open("/log.csv", FILE_APPEND);
if(!f){ Serial.println("Open fail"); return; }
f.println("ts, value");
f.close();
}
void loop(){}
Przykład 3: Logger danych (CSV) co 5 s, z ochroną przed utratą danych
#include <FS.h>
#include <SD.h>
#include <SPI.h>
static constexpr int CS = 5;
static constexpr int ADC_PIN = 34;
static constexpr uint32_t LOG_INTERVAL_MS = 5000;
unsigned long lastLog = 0;
void setup(){
Serial.begin(115200);
SPI.begin(18,19,23,CS);
if(!SD.begin(CS, SPI, 4000000)){
Serial.println("SD fail");
while(1) delay(1000);
}
pinMode(ADC_PIN, INPUT);
// Nagłówek tylko gdy plik pusty/nie istnieje
File f = SD.open("/data.csv", FILE_READ);
bool needHeader = !f || (f.size()==0);
if(f) f.close();
f = SD.open("/data.csv", FILE_APPEND);
if(needHeader) f.println("ms,adc,voltage_V");
f.close();
}
void loop(){
unsigned long now = millis();
if(now - lastLog >= LOG_INTERVAL_MS){
lastLog = now;
int raw = analogRead(ADC_PIN);
float v = raw * (3.3f / 4095.0f);
// Minimalne okno krytyczne — otwieraj/ zapisuj/ zamykaj
File f = SD.open("/data.csv", FILE_APPEND);
if(f){
f.printf("%lu,%d,%.3f\n", now, raw, v);
f.flush(); // wymuś zapis do FAT (redukcja ryzyka utraty)
f.close();
Serial.println("logged");
} else {
Serial.println("log fail");
}
}
}
Powodzenia! Jeśli podasz konkretną płytkę (np. model DevKit, ESP32‑CAM, moduł SD), dobiorę pewne piny/prędkości i schemat podłączenia „1:1”.