Thư viện SD.h: đọc/ghi file CSV trên Arduino
SD.h là thư viện chính thức để Arduino đọc/ghi thẻ microSD qua SPI — biến board thành datalogger thực thụ. Bài này hướng dẫn API đầy đủ, format thẻ đúng, và pattern ghi CSV cho cảm biến.
1. Module SD card
Phổ biến nhất: Module microSD SPI giá ~25k. Chân:
- VCC: 5V (module có regulator xuống 3.3V cho SD).
- GND: GND chung.
- MOSI / MISO / SCK: bus SPI chuẩn (D11/D12/D13 trên Uno).
- CS: chân chọn — bất kỳ digital, thường D10 hoặc D4.
Một số module không có level shifter — chỉ chạy ổn với MCU 3.3V (ESP32). Trên Arduino Uno (5V) đôi khi hư SD card sau vài lần ghi.
2. Format thẻ SD
Format FAT32, dung lượng tối đa 32GB (SD và SDHC). SDXC 64GB+ dùng exFAT — thư viện SD.h không hỗ trợ. Dùng SdFat (xem mục cuối) hoặc format lại làm FAT32.
Cluster size 16KB hoặc 32KB là OK. Để mặc định khi format trên Windows.
3. Cài thư viện
SD.h đã có sẵn trong Arduino IDE — không cần cài. Trên ESP32, dùng SD.h đi kèm Arduino-ESP32 (đường dẫn hơi khác).
4. Khởi tạo và kiểm tra
#include
#include
const int CS = 10;
void setup() {
Serial.begin(115200);
if (!SD.begin(CS)) {
Serial.println("SD init FAIL");
while (1);
}
Serial.println("SD OK");
}
Trên ESP32 dùng dải nhanh hơn: SD.begin(CS, SPI, 40000000) — 40 MHz.
5. Ghi file (overwrite)
File f = SD.open("/data.txt", FILE_WRITE);
if (f) {
f.println("Hello SD");
f.printf("Temp: %.1f\n", 25.3);
f.close(); // QUAN TRỌNG — không close, data không flush
}
FILE_WRITE mở để append (ghi tiếp cuối file). Không có mode "truncate" — phải SD.remove(path) trước.
6. Đọc file
File f = SD.open("/data.txt");
if (f) {
while (f.available()) {
char c = f.read();
Serial.write(c);
}
f.close();
}
Đọc theo dòng:
while (f.available()) {
String line = f.readStringUntil('\n');
// process line
}
7. Datalogger CSV — pattern chuẩn
void logRow(float t, float h) {
File f = SD.open("/log.csv", FILE_WRITE);
if (!f) return;
f.print(millis());
f.print(',');
f.print(t, 2);
f.print(',');
f.println(h, 2);
f.close();
}
Mở Excel/Google Sheets import file CSV → có chart ngay. Lần đầu, ghi thêm header:
if (!SD.exists("/log.csv")) {
File f = SD.open("/log.csv", FILE_WRITE);
f.println("time_ms,temp,hum");
f.close();
}
8. Liệt kê file trong thư mục
void listDir(const char* path) {
File root = SD.open(path);
while (true) {
File entry = root.openNextFile();
if (!entry) break;
Serial.print(entry.name());
if (entry.isDirectory()) Serial.println("/");
else { Serial.print(" "); Serial.println(entry.size()); }
entry.close();
}
root.close();
}
9. Tạo và xoá
SD.mkdir("/logs");
SD.rmdir("/old");
SD.remove("/data.txt");
bool exists = SD.exists("/config.json");
10. Hiệu năng — close() là chìa khoá
SD card có flash wear-leveling và buffer write. Để ghi an toàn:
- Đừng giữ file mở quá lâu — mất điện = mất data trong buffer.
- Close ngay sau mỗi lần ghi quan trọng.
- Nếu ghi liên tục (100 Hz): mở 1 lần, flush mỗi N dòng, close khi đủ.
static File f;
static uint32_t lastFlush = 0;
void log(float v) {
if (!f) f = SD.open("/fast.csv", FILE_WRITE);
f.println(v);
if (millis() - lastFlush > 1000) {
f.flush();
lastFlush = millis();
}
}
11. SD.h vs SdFat — khi nào dùng
SdFat (Bill Greiman) mạnh hơn SD.h: hỗ trợ exFAT, ghi nhanh hơn, ít RAM. Dùng cho:
- Thẻ > 32GB (exFAT).
- Tốc độ ghi > 100 KB/s (data logger high-speed).
- Audio playback từ SD.
Cú pháp tương tự, drop-in replacement.
12. Lỗi thường gặp
- SD.begin() fail: sai chân CS, dây dài, module 3.3V trên Uno 5V không có level shifter.
- Ghi nhưng file rỗng: quên
close()hoặc mất điện trước flush. - File name truncate: SD.h cũ chỉ hỗ trợ 8.3 (vd
LOG.CSV). SD.h mới support long filename. - SD card chết: thẻ Trung Quốc rẻ — sau ~10k chu kỳ ghi. Mua thẻ tốt (SanDisk, Samsung) chạy được hàng triệu lần.
Liên quan
Xem dự án Datalogger DHT22 ghi SD card theo thời gian. Đọc bài SPI trên Arduino: SPI.h căn bản nếu chưa hiểu SPI.