Компоненты · 12 мин чтения

Модуль SD-карты для Arduino: регистратор данных в CSV с метками времени от RTC

Модуль SD-карты для Arduino: подключение по SPI, форматирование в FAT32, запись данных датчиков в CSV с метками времени от RTC, SD_MMC на ESP32, Pico и решение ошибки initialization failed.

Модуль SD-карты для Arduino — маленькая недорогая плата, которая позволяет сохранять показания датчиков (температуру, влажность, расстояние или координаты) в виде файлов на карте micro SD. Это самый простой способ собрать регистратор данных, который ведёт измерения днями и даже месяцами без подключённого компьютера: Arduino снимает показания, модуль записывает каждое из них новой строкой в CSV-файл на карте, а потом карта вставляется в компьютер, и данные превращаются в график в Excel. Модуль подключается по SPI и работает всего с несколькими строками кода на библиотеке SD, которая входит в состав Arduino IDE.

В этом руководстве пошагово разберём, как работает модуль, чем отличаются модули на 5 V и 3,3 V, как подключить его по SPI к Arduino Uno, Mega, ESP32 и Raspberry Pi Pico, как отформатировать карту в FAT32, как записывать и читать файлы и как вести CSV-журнал с датой и временем с помощью модуля RTC. Также рассмотрим быстрый интерфейс SD_MMC на ESP32, работу с SD-картой на Pico в MicroPython и способы исправить слишком частую ошибку «initialization failed» (ошибка инициализации).

Модуль карты micro SD для Arduino
Модуль карты micro SD: слот для карты, стабилизатор на 3,3 V, микросхема преобразователя уровней и 6 пинов (GND, VCC, MISO, MOSI, SCK, CS).

Что такое модуль SD-карты и как он работает?

SD-карты работают от 3,3 V и умеют общаться двумя способами: в быстром собственном режиме SD и в более простом режиме SPI. Микроконтроллеры вроде Arduino общаются с картой по SPI. Задача модуля — сделать их электрически совместимыми: стабилизатор понижает 5 V до нужных карте 3,3 V, а микросхема преобразователя уровней (обычно 74LVC125A) переводит 5-вольтовые сигналы Arduino в безопасные для карты 3,3 V. Внутри карта состоит из блоков по 512 байт, а такими понятиями, как файлы, папки и имена файлов, занимается файловая система FAT. Всю тяжёлую работу берёт на себя библиотека SD: остаётся только открыть файл, записать в него и закрыть.

ПараметрЗначение
ИнтерфейсSPI (линии MISO, MOSI, SCK, CS)
Питание (модуль micro SD со стабилизатором)4,5–5,5 V, стабилизатор 3,3 V на плате
Уровень сигналовСовместим с 3,3 V и 5 V (благодаря преобразователю уровней)
Поддерживаемые картыmicro SD (до 2 ГБ) и micro SDHC (4–32 ГБ)
Файловая системаFAT16 или FAT32
ТокНесколько mA в простое, до 100 mA при записи
Имя файла (библиотека SD для Arduino)Формат 8.3: до 8 символов в имени + 3 в расширении

Модули SD-карт на 5 V и 3,3 V: какой выбрать?

Тип модуляПитаниеУровень сигналовПодходит для
Модуль micro SD со стабилизатором (74LVC125A)5 V3,3 V и 5 VUno, Nano, Mega; ESP32 и Pico при питании от 5 V
Полноразмерный модуль SD-карты (пины +5 и +3.3)5 V или 3,3 VУ большинства нет настоящего преобразователя уровнейПлаты на 3,3 V; с 5-вольтовыми сигналами работает ненадёжно
Модуль micro SD без стабилизатора (просто слот)Только 3,3 VТолько 3,3 VESP32, Raspberry Pi Pico
Платы со встроенным слотом (например, ESP32-CAM)От платы3,3 VИспользуются напрямую с SD_MMC

Для Arduino Uno, Nano или Mega выбирай модуль micro SD со стабилизатором и преобразователем уровней, как на фото, и подключай VCC к пину 5V. ESP32 и Pico работают от 3,3 V; с ними тоже можно использовать этот модуль, но питать его всё равно нужно от 5 V (VIN на ESP32, VBUS на Pico при питании по USB). Поскольку преобразователь уровней питается от 3,3 V, сигнал MISO, идущий обратно к микроконтроллеру, уже имеет уровень 3,3 V. Модули без стабилизатора подключаются прямо к пину 3V3; если такой модуль приходится использовать с 5-вольтовой Arduino, поставь делитель напряжения 1 kΩ + 2 kΩ на каждую из линий MOSI, SCK и CS или используй преобразователь логических уровней. Номиналы резисторов можно проверить в утилите делителя напряжения.

Самая частая ошибка — питать модуль micro SD со стабилизатором от 3,3 V. Стабилизатор AMS1117 на модуле «съедает» около 1 V, так что до карты доходит лишь примерно 2,3 V, и обычно она выдаёт initialization failed. Обратная ситуация не лучше: 5 V на пинах модуля без стабилизатора могут навсегда повредить карту. Перед подключением прочитай надписи на модуле и проверь, есть ли на нём стабилизатор.

Подключение модуля SD-карты: пины SPI

Пин модуляArduino Uno / NanoArduino MegaESP32Raspberry Pi Pico
GNDGNDGNDGNDGND
VCC5V5VVIN (5 V)VBUS (5 V)
MISOD12D50GPIO 19GP16
MOSID11D51GPIO 23GP19
SCKD13D52GPIO 18GP18
CSD10D53GPIO 5GP17

MISO, MOSI и SCK на любой плате должны идти к аппаратным пинам SPI; CS (выбор микросхемы, chip select) может быть любым цифровым пином, лишь бы в коде в SD.begin() передавался тот же номер. На готовых шилдах CS обычно D4 или D10. К одной шине SPI можно подключить несколько устройств: все они делят MISO, MOSI и SCK, а у каждого свой пин CS. Как устроен SPI, подробно объясняем в статье Интерфейс SPI. Где находятся пины на твоей плате, покажет утилита распиновки.

Подготовка SD-карты: форматирование в FAT32

  • Объём карты: бери карту micro SDHC на 4–32 ГБ. Библиотека SD для Arduino поддерживает карты SDSC (до 2 ГБ) и SDHC; карты SDXC на 64 ГБ и больше продаются отформатированными в exFAT, а эту систему библиотека прочитать не может.
  • Файловая система: отформатируй карту в FAT32 (на картах до 2 ГБ подойдёт и FAT16). NTFS и exFAT работать не будут.
  • Windows: щёлкни по карте правой кнопкой в Проводнике, выбери «Форматировать» (Format), затем укажи файловую систему FAT32 и размер единицы распределения по умолчанию. Для карт больше 32 ГБ Windows не предлагает FAT32.
  • macOS: выбери карту в «Дисковой утилите», нажми «Стереть» (Erase) и укажи формат MS-DOS (FAT) и схему «Основная загрузочная запись» (Master Boot Record).
  • Самый надёжный вариант: бесплатная программа SD Card Formatter от SD Association форматирует карту по официальному стандарту и избавляет от большинства странных ошибок.
  • Один раздел: на карте должен быть только один раздел. На картах, которые раньше стояли в Raspberry Pi или фотоаппарате, может остаться несколько разделов; удали их перед форматированием.
Библиотека SD на Arduino Uno понимает только короткие имена файлов в формате 8.3: имя до 8 символов и расширение до 3, без пробелов, спецсимволов и кириллицы. DATA.CSV или LOG01.TXT подойдут, а с длинным именем вроде temperature-log.csv вызов SD.open() молча завершится неудачей. На ESP32 и Pico длинные имена файлов работают без проблем.

Первый тест по шагам: запись на SD-карту и чтение с неё

  1. Вставь отформатированную карту в модуль и подключи модуль к Arduino по таблице выше.
  2. Библиотека SD входит в Arduino IDE, устанавливать ничего не нужно: достаточно подключить SPI.h и SD.h в начале скетча.
  3. Загрузи код ниже и открой монитор порта на скорости 9600 бод.
  4. Если видны «tamam» (ОК) и содержимое файла, карта и подключение в порядке. При каждом запуске платы в TEST.TXT добавляется новая строка.
  5. Если вынуть карту и вставить её в компьютер, TEST.TXT откроется в любом текстовом редакторе.
C++ (Arduino IDE)
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}
ФункцияЧто делает
SD.begin(cs)Инициализирует карту; при успехе возвращает true
SD.open("NAME.TXT", FILE_WRITE)Открывает файл для записи; если файла нет, создаёт его, если есть — дописывает в конец
SD.open("NAME.TXT")Открывает файл для чтения (FILE_READ)
file.print() / println() (запись)Записывает в файл текст или число
file.flush()Записывает буферизованные данные на карту, не закрывая файл
file.close()Записывает на карту оставшиеся данные и закрывает файл
file.available() / read() (чтение)Проверяет, остались ли байты для чтения / читает один байт
SD.exists() / SD.remove() / SD.mkdir() (файлы и папки)Проверяет, существует ли файл / удаляет файл / создаёт папку

Запись данных датчиков в CSV с метками времени от RTC

Самый практичный формат файла для регистратора данных — CSV (comma-separated values, значения через запятую): каждая строка — одно измерение, каждый столбец — одно значение, а в первой строке стоят заголовки столбцов. Чтобы знать, когда снято каждое показание, в каждую строку стоит добавлять дату и время. millis() показывает только, сколько времени работает Arduino, и обнуляется при каждом перезапуске, поэтому используем модуль RTC (часы реального времени) с батарейкой-таблеткой. RTC продолжает отсчитывать время, даже когда Arduino выключена. DS1307 дешёвый, но может уходить на несколько секунд в сутки, а DS3231 благодаря кварцу с термокомпенсацией уходит всего примерно на минуту в год. Сравниваем их в статье Модули часов RTC.

Модуль часов RTC DS1307
Модуль RTC DS1307 подключается по I2C (SDA, SCL) и продолжает отсчитывать время от батарейки-таблетки, даже когда Arduino выключена.

Схема: модуль SD подключается к пинам SPI по таблице выше, модуль RTC — к шине I2C (на Uno SDA = A4, SCL = A5, VCC = 5V), а пин данных датчика DHT22 — к D2; если датчик без платы-модуля, добавь резистор 10 kΩ между пином данных и VCC. Установи библиотеки RTClib (Adafruit) и DHT sensor library через «Менеджер библиотек» (Library Manager). Подробнее о подключении датчика — в статье Датчики температуры и влажности DHT11 и DHT22.

C++ (Arduino IDE)
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}

Каждые 10 секунд код считывает температуру и влажность, берёт дату и время из RTC и дописывает в конец VERI.CSV строку вида 2026-11-04,14:05:30,23.5,45.2. Поскольку файл закрывается после каждой записи, уже сохранённые данные переживут даже отключение питания. На платах AVR функция sprintf() не поддерживает числа с плавающей точкой (%f), поэтому значения сначала переводятся в текст функцией dtostrf(). Так как для отсчёта времени используется millis() вместо delay(), в loop() можно делать и другие дела. Если время в RTC ещё не задано, часы выставляются на момент компиляции кода. Для DS3231 достаточно написать RTC_DS3231 вместо RTC_DS1307 и проверять lostPower() вместо isrunning().

Сколько места это занимает? Одна строка — около 31 байта. При записи каждые 10 секунд получается 8640 строк в сутки, или около 260 КБ; за год — примерно 95 МБ. Так что при таком темпе карты на 8 ГБ хватит на десятилетия. Настоящее ограничение — не карта, а питание: если проект будет работать от батарей, заранее посчитай, на сколько их хватит, в калькуляторе времени работы от батареи.

Открываем данные с SD-карты в Excel

  1. Отключи питание Arduino, вынь карту из модуля и вставь её в компьютер.
  2. Скопируй VERI.CSV на компьютер: работать с копией безопаснее, чем прямо с картой.
  3. Открой в Excel пустую книгу и выбери файл через Данные › Из текстового/CSV-файла (Data › From Text/CSV).
  4. В окне предпросмотра выбери разделитель «Запятая» и нажми «Загрузить»: столбцы разделятся на дату, время, температуру и влажность.
  5. Выдели столбцы температуры и влажности и добавь линейный график на вкладке Вставка (Insert), чтобы увидеть, как они меняются со временем.
Если в твоём Excel десятичный разделитель — запятая (как в русской, турецкой, немецкой, французской, испанской или итальянской локали), значение вроде 23.5 может не распознаться как число и отобразиться как текст, дата или неверное число. Есть два решения: при импорте нажать «Преобразовать данные» (Transform Data) и перевести столбцы температуры и влажности в десятичные числа с языковым стандартом «английский (США)», либо изменить код, как показано ниже, чтобы он использовал точку с запятой как разделитель и запятую как десятичный знак. Во втором случае достаточно дважды щёлкнуть по файлу, и Excel разделит столбцы автоматически.
C++ (Arduino IDE)
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

Если удобнее передавать показания в Excel в реальном времени, пока Arduino подключена к компьютеру, и не вынимать карту, загляни в методы Data Streamer и PLX-DAQ в статье Передача данных с Arduino в Excel. А вот для проектов, которые работают в поле, вдали от компьютера, SD-карта незаменима.

SD-карта с ESP32 (SPI)

В ядре ESP32 для Arduino есть своя библиотека SD, и работает она почти так же, но с тремя важными отличиями: пути к файлам начинаются с / («/olcumler.csv»), длинные имена файлов разрешены, а FILE_WRITE перезаписывает файл с нуля. Для дописывания нужен FILE_APPEND; если перенести код для Uno без изменений, старые данные будут стираться при каждом запуске платы. Пины SPI по умолчанию: SCK 18, MISO 19 и MOSI 23, а для CS обычно используется GPIO 5. Тип и объём карты тоже можно прочитать одной строкой:

C++ (Arduino IDE)
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}

Код каждые 5 секунд записывает «сырое» значение (0–4095) фоторезистора (LDR), подключённого к GPIO 34. На ESP32 для точного времени даже не нужен модуль RTC: можно подключиться к Wi-Fi, получить время с NTP-сервера и добавлять метку времени в каждую строку через getLocalTime(). Если провода длинные или карта работает ненадёжно, снизь скорость SPI: SD.begin(5, SPI, 1000000) запускает карту на 1 MHz. В регистраторе с батарейным питанием глубокий сон между измерениями увеличивает время работы от батареи в разы.

ESP32 SD_MMC: быстрый интерфейс SD и ESP32-CAM

Помимо SPI, у ESP32 есть контроллер SDMMC, который говорит на собственном быстром протоколе карты. В 4-битном режиме библиотека SD_MMC в несколько раз быстрее SPI, поэтому идеально подходит для больших файлов вроде фотографий или звука. На классической ESP32 пины фиксированы: CLK GPIO 14, CMD GPIO 15, D0 GPIO 2, D1 GPIO 4, D2 GPIO 12, D3 GPIO 13, и этим линиям нужны подтягивающие резисторы 10 kΩ. В 1-битном режиме используются только CLK, CMD и D0; он медленнее, зато освобождает GPIO 4, 12 и 13. Слот micro SD на плате ESP32-CAM подключён именно к этим пинам, а 1-битный режим не даёт вспышке на GPIO 4 мигать при каждом обращении к карте.

C++ (Arduino IDE)
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 — пин конфигурации при старте (strapping): он задаёт напряжение флеш-памяти, пока ESP32 загружается. В 4-битном режиме подтягивающий резистор на линии D2 может вообще не дать некоторым модулям загрузиться; в таком случае используй 1-битный режим. На новых чипах вроде ESP32-S3 пины можно выбрать свободно с помощью SD_MMC.setPins().

SD-карта с Raspberry Pi Pico (MicroPython)

В MicroPython SD-карты обслуживает драйвер sdcard.py из micropython-lib. Если на компьютере есть mpremote, установи драйвер командой mpremote mip install sdcard или скопируй файл на Pico через Thonny. Карта монтируется как папка /sd с помощью os.mount(), а дальше с ней работают обычными файловыми командами Python (open, write). Код ниже считывает встроенный датчик температуры Pico и каждые 10 секунд записывает строку CSV. Если Pico для тебя в новинку, сначала прочитай Что такое 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

У Pico нет часов с батарейным питанием: при подключении к Thonny её часы автоматически выставляются по компьютеру, а при автономной работе отсчёт начинается с 1 января 2021 года. Для точных меток времени можно добавить модуль DS3231 или на Pico W получать время из интернета по NTP. Если карта не вставлена или подключение неверное, драйвер выдаёт OSError: no SD card (карта не найдена). Если программировать Pico в Arduino IDE (ядро arduino-pico), подойдёт тот же подход с библиотекой SD: пины SPI0 по умолчанию совпадают с таблицей, а для CS достаточно написать SD.begin(17).

Как не потерять данные: питание, частота записи и ресурс карты

  • Без close() или flush() на карту ничего не попадает: библиотека сначала собирает данные в 512-байтном буфере. Если файл всё время открыт, вызывай flush() каждые несколько строк.
  • Не вынимай карту во время записи: если выдернуть карту или отключить питание посреди записи, файловая система может повредиться. Хорошая привычка — кнопка, которая останавливает запись, и светодиод, который показывает, что запись идёт.
  • Обеспечь стабильное питание: при записи карта потребляет до 100 mA. Конденсатор 10–100 µF между VCC и GND модуля уменьшает просадки напряжения и случайные ошибки записи.
  • Не открывай и не закрывай файл слишком часто: если снимать десятки показаний в секунду, открывать и закрывать файл ради каждой строки слишком медленно; накапливай показания в ОЗУ и записывай пачками по 10–20 строк.
  • Ресурс карты: SD-карта внутри распределяет запись по разным ячейкам (выравнивание износа, wear leveling), поэтому регистратор, который пишет несколько строк в минуту, годами не износит карту. И всё же выбирай карту известного производителя.
  • Дели данные на файлы: отдельный файл на каждый день (например, 20261104.CSV) сохраняет файлы небольшими, а если что-то пойдёт не так, теряются данные только за этот день.

Идеи проектов с модулем SD-карты

  • Регистратор метеостанции: записывай температуру, влажность и давление каждый час с помощью BME280 и строй график за целый сезон.
  • Журнал полива растений: записывай показания датчика влажности почвы и моменты включения насоса, чтобы изучить свой режим полива.
  • Регистратор GPS-маршрута: сохраняй маршрут велопрогулки или похода в CSV с помощью NEO-6M GPS, а потом показывай его на карте.
  • Журнал прохода по картам: записывай в файл каждую карту, считанную RFID RC522, вместе с датой и временем.
  • Учёт энергопотребления: измеряй и записывай ток, который устройство потребляет в течение дня, с помощью датчика тока ACS712.
  • MP3-плеер: DFPlayer Mini воспроизводит аудиофайлы со своего слота micro SD, а Arduino только отправляет команды.

Частые ошибки и их решение

СимптомВероятная причинаРешение
«initialization failed» (ошибка инициализации)Карта не вставлена, подключение неверное или пин CS не совпадает с кодомПроверь, что MISO, MOSI и SCK подключены к аппаратным пинам SPI, а номер CS в SD.begin() указан верно
«initialization failed» (подключение верное)Модуль со стабилизатором питается от 3,3 V или питание слабоеПитай модуль от 5 V, укороти провода, добавь конденсатор между VCC и GND
«Could not find FAT16/FAT32 partition» (раздел FAT16/FAT32 не найден)Карта отформатирована в exFAT или NTFS; карта SDXC на 64 ГБ и большеОтформатируй в FAT32 карту объёмом до 32 ГБ
Файл не открывается («error opening»)Имя файла нарушает правило 8.3 или предыдущий файл не закрытИспользуй короткое имя вроде VERI.CSV и закрывай каждый файл через close()
Файл пустой или в нём нет последних строкПитание пропало до вызова close() или flush()Закрывай файл после каждой записи или регулярно вызывай flush()
SD-карта перестаёт работать после добавления другого SPI-устройстваCS другого устройства «висит в воздухе» или модуль не отпускает линию MISOВ начале setup() установи все пины CS в OUTPUT и HIGH; при необходимости используй модуль, который отпускает MISO
Uno зависает или ведёт себя странноНе хватает ОЗУ: библиотека SD занимает около 650 байт, а буфер OLED-дисплея 1 КБОборачивай текст в F(); при необходимости переходи на Mega или ESP32
На ESP32 старые данные стираются при каждой загрузкеФайл открывается с FILE_WRITEИспользуй FILE_APPEND, чтобы дописывать в конец
«Card Mount Failed» (не удалось смонтировать карту) на ESP32Питание, подключение, высокая скорость SPI или нет подтяжек при SD_MMCСнизь скорость SPI до 1 MHz; с SD_MMC попробуй 1-битный режим
Быстрее всего найти проблему помогает пример Файл › Примеры › SD › CardInfo (File › Examples) в Arduino IDE. Если он показывает тип карты (SD1, SD2 или SDHC), но не находит раздел, дело в форматировании; если не показывает даже тип карты, проверь подключение и питание.

Модуль SD-карты превращает проект, который только измеряет, в устройство, которое ведёт записи, а несколько дней реальных данных расскажут гораздо больше, чем одно показание. В приложении BlueGrays есть регистратор температуры на ESP32 с DHT22, DS1307 RTC, micro SD и OLED, цифровые часы на основе RTC и проекты для измерения температуры и влажности — всё с пошаговыми схемами подключения и кодом.

Частые вопросы

Карту какого объёма может использовать Arduino?

Стандартная библиотека SD для Arduino поддерживает карты SDSC и SDHC, отформатированные в FAT16 или FAT32, то есть карты до 32 ГБ. Карты SDXC на 64 ГБ и больше поставляются с exFAT, и эта библиотека их не читает. Для регистратора данных карты на 4–16 ГБ более чем достаточно.

Почему SD-карта выдаёт «initialization failed»?

Самые частые причины: неверный пин CS, MISO, MOSI или SCK не подключены к аппаратным пинам SPI, карта отформатирована не в FAT32 или модуль со стабилизатором питается от 3,3 V. Сначала запусти пример CardInfo, затем попробуй провода покороче и питание модуля от 5 V.

Работает ли модуль SD-карты от 3,3 V?

Модули без стабилизатора работают прямо от 3,3 V и подходят для ESP32 или Pico. Модулям micro SD со стабилизатором и преобразователем уровней нужно 4,5–5,5 V; при питании от 3,3 V карте не хватает напряжения. Такие модули можно питать от VIN на ESP32 или VBUS на Pico.

Как открыть CSV-файл Arduino с SD-карты в Excel?

Скопируй файл на компьютер и импортируй его в Excel через «Данные › Из текстового/CSV-файла», выбрав разделитель «Запятая». Если в твоём Excel десятичный разделитель — запятая, числа могут выглядеть неправильно; тогда преобразуй столбцы с языковым стандартом «английский (США)» или используй в коде точку с запятой как разделитель.

Как часто Arduino может записывать на SD-карту?

Несколько строк в секунду — не проблема, но открывать и закрывать файл ради каждой строки долго. Для быстрых измерений накапливай данные в ОЗУ и записывай пачками или держи файл открытым и регулярно вызывай flush(). При медленном темпе, например одна запись в минуту, самый надёжный способ — каждый раз открыть, записать и закрыть.

Можно ли одновременно использовать модуль SD-карты с RFID или TFT-дисплеем?

Да. Устройства SPI делят линии MISO, MOSI и SCK, а каждое использует свой пин CS. При проблемах установи все пины CS в OUTPUT и HIGH в начале setup(). Преобразователь уровней на некоторых дешёвых модулях micro SD никогда не отпускает линию MISO; в таком случае используй модуль, который её отпускает, или вторую шину SPI на ESP32.

Все проекты
Температура и влажность с DHT11
#55Средний

Температура и влажность с DHT11

Насколько тепло в твоей комнате и влажный ли воздух или сухой? Датчик DHT11 измеряет температуру и влажность, а Arduino выводит значения на двухстрочный LCD-экран и обновляет их каждые пару секунд. Ес

4.7(47)
73
Регистратор температуры на ESP32 (DHT22 + DS1307 RTC + microSD + OLED)
#144Продвинутый
Premium

Регистратор температуры на ESP32 (DHT22 + DS1307 RTC + microSD + OLED)

Собери на ESP32 регистратор температуры с отметками времени! Каждую минуту читай температуру и влажность с DHT22, бери реальное время из DS1307 RTC и записывай всё на карту microSD в формате CSV. OLED показывает текущую температуру (крупным шрифтом), влажность в процентах, время и счётчик записей. Файл /temp_log.csv на SD-карте открывается в Excel, Google Sheets или Python pandas — идеально для теплиц, комнат, лабораторий и хранения продуктов.

4.7(7)
12
Цифровые часы на ESP32 и DS1307 RTC (I2C + LCD)
#120Средний
Premium

Цифровые часы на ESP32 и DS1307 RTC (I2C + LCD)

В этом проекте время и дата из модуля часов реального времени (RTC) DS1307 выводятся на I2C LCD-экран 16x2. DS1307 — RTC с резервной батарейкой, который хранит время даже при выключенной ESP32. Оба модуля делят одну шину I2C (SDA/SCL), и ты узнаёшь, как управлять несколькими устройствами всего по двум сигнальным проводам. Проект даёт практические знания о протоколе I2C, работе модуля RTC и динамическом выводе данных на LCD-экран.

4.6(26)
40
Температура и влажность с DHT22 на ESP32 (с LCD-дисплеем)
#117Средний

Температура и влажность с DHT22 на ESP32 (с LCD-дисплеем)

Этот проект измеряет температуру и влажность воздуха датчиком DHT22 и в реальном времени показывает данные на I2C LCD 16x2. Данные читаются с датчика по однопроводному протоколу через библиотеку Adafruit DHT. Проект служит основой для IoT-метеостанций, умного дома или систем мониторинга среды в теплицах. Связь с DHT22 идёт через пин GPIO 4 у ESP32.

4.8(38)
56
Глубокий сон ESP32: экономия батареи (OLED + счётчик в RTC RAM)
#135Продвинутый
Premium

Глубокий сон ESP32: экономия батареи (OLED + счётчик в RTC RAM)

Режим глубокого сна (Deep Sleep) у ESP32 снижает потребление до ~10 µA, выключая процессор и большую часть периферии, — это важно для IoT-устройств на батарейках. В этом проекте используются три источника пробуждения: таймер (15 секунд), внешний пин (EXT0 — кнопка GPIO 33) и касание (T0/GPIO 4). Переменные с RTC_DATA_ATTR сохраняются во время глубокого сна — счётчики загрузок, пробуждений по таймеру и по кнопке ведутся непрерывно.

4.3(10)
16
Точное время из интернета через NTP на ESP32
#128Продвинутый
Premium

Точное время из интернета через NTP на ESP32

ESP32 подключается к Wi-Fi и получает точное время с точностью до миллисекунд от серверов NTP (Network Time Protocol). Благодаря функции configTzTime() автоматически применяется часовой пояс Турции (TRT, UTC+3), а в странах с летним временем переходы обрабатываются автоматически по строке POSIX TZ. Время выводится в монитор порта и на необязательный I2C LCD. configTzTime() запускает службу SNTP, которая периодически пересинхронизирует часы.

4.5(13)
21
Часы, календарь и метеостанция на матрице (MAX7219, DS1307)
#85Средний
Premium

Часы, календарь и метеостанция на матрице (MAX7219, DS1307)

Табло с бегущей строкой для стола или стены, которое по очереди показывает время, дату и погоду в комнате. На светодиодном дисплее 8x32 сначала видна температура в градусах Цельсия и Фаренгейта, затем

5.0(50)
66
Часы на DS1302 RTC с LCD-дисплеем
#46Средний
Premium

Часы на DS1302 RTC с LCD-дисплеем

Маленькие настольные часы, которые помнят время даже при отключении питания. Модуль часов DS1302 считает время благодаря своей крошечной батарейке; каждую секунду Arduino читает его и выводит время и

4.7(41)
51