Гигабайты для журналов, настроек и картинок. Файлы в FAT32 читаются на любом компьютере.
Как работает
Карта работает по SPI: MOSI (данные к карте), MISO (от карты), SCK (такт) и CS (выбор). Библиотека SD (встроена в ядра Arduino и ESP32): SD.begin(CS), SD.open("/log.txt", FILE_APPEND), file.println(...), file.close().
Карта — устройство на 3,3 В. Модули для Arduino имеют стабилизатор и преобразователь уровней, для ESP32 подходят и простые модули без них.
#include <SPI.h>
#include <SD.h>
// Карта SD на аппаратном SPI: 11, 12, 13 и выбор на 10.
//
// Три отличия от ESP32, о которые спотыкаются при переносе.
//
// **Выводы шины другие** и не выбираются: у Uno это 11 и 13, MISO на
// 12. На ESP32 те же роли на 23, 19 и 18.
//
// **Имена файлов только короткие**, восемь знаков плюс три на
// расширение. Библиотека для AVR длинных не знает: SD.open("data.log")
// откроет не то, что вы думаете, а SD.open("измерения.txt") не откроет
// ничего. Только латиница и только 8.3.
//
// **Памяти впритык.** Библиотека держит буфер сектора — 512 байт, ещё
// четверть оперативной памяти платы. Вместе с экраном OLED они на Uno
// уже не помещаются.
//
// На карте в модели уже лежит README.TXT — с него и начнём.
const int CS = 10;
void setup() {
Serial.begin(9600);
delay(200);
if (!SD.begin(CS)) {
Serial.println(F("карта не найдена: проверьте CS, MISO и питание"));
return;
}
Serial.println(F("карта на месте"));
// Что на ней лежит.
File root = SD.open("/");
for (File f = root.openNextFile(); f; f = root.openNextFile()) {
Serial.print(F(" "));
Serial.print(f.name());
Serial.print(F(" "));
Serial.print(f.size());
Serial.println(F(" байт"));
f.close();
}
// Читаем готовый файл.
File readme = SD.open("README.TXT");
if (readme) {
while (readme.available()) Serial.write(readme.read());
readme.close();
}
}
void loop() {
// Дописываем строку в журнал. Файл открывается и закрывается на
// каждую запись намеренно: карту вынимают без предупреждения, а
// закрытый файл переживёт это, незакрытый — нет.
File log = SD.open("LOG.TXT", FILE_WRITE);
if (log) {
log.print(millis() / 1000);
log.println(F(" c работы"));
log.close();
Serial.println(F("строка записана в LOG.TXT"));
} else {
Serial.println(F("не открылся LOG.TXT"));
}
delay(5000);
}
В железе
SPI по умолчанию: ESP32 (VSPI) — SCK GPIO18, MISO GPIO19, MOSI GPIO23, CS GPIO5; Arduino Uno — SCK D13, MISO D12, MOSI D11, CS обычно D10 (или D4).
Частые ошибки
SD.begin() возвращает false — карта в exFAT (карты от 64 ГБ). Форматируйте в FAT32.
Файл пустой — не вызван file.close() или flush(): данные остались в буфере.
Питание просаживается при записи — карта берёт до 100 мА импульсами. Конденсатор 10–100 мкФ у модуля помогает.
Вывод CS другого SPI-устройства не поднят в HIGH — два устройства отвечают одновременно.