← До всіх проєктів
Сенсори Середній

Логер температури на microSD: DHT22, DS3231 і CSV-файл

ESP32 раз на 5 секунд записує час, температуру й вологість у CSV на карту пам'яті — без Wi-Fi і хмар. Модуль microSD по SPI, бібліотека SD, чому шляхи починаються зі «/», навіщо close() і як відкрити дані в Excel.

Складність
Середній
Час
1 h
Категорія
Сенсори
Оновлено

Про проєкт

Не всі дані треба відправляти в інтернет. Датчик у теплиці, погребі чи дорогою в машині може просто записувати вимірювання на microSD-картку. 8 ГБ вистачить на десятиліття CSV-рядків. Картку потім вставляєте в комп'ютер і відкриваєте в Excel або Google Таблицях. Збираємо логер: DHT22 міряє, DS3231 дає точний час, а кожні 5 секунд у /log.csv додається рядок.

Що знадобиться

  • ESP32 DevKit
  • Модуль microSD (SPI) + картка до 32 ГБ, відформатована у FAT32
  • Датчик DHT22
  • Годинник DS3231 з батарейкою
  • Бібліотеки: SD (входить в arduino-esp32), RTClib, DHT sensor library

Схема

microSD-модуль (апаратний SPI, VSPI):

Модуль ESP32
VCC 5V (синій модуль зі стабілізатором)
GND GND
MISO GPIO19
MOSI GPIO23
SCK GPIO18
CS GPIO5

DS3231: SDA → GPIO21, SCL → GPIO22, VCC → 3V3, GND → GND. DHT22: DATA → GPIO27, VCC → 3V3.

Найпоширеніший синій модуль має стабілізатор AMS1117 і перетворювач рівнів. Від 3.3 В він не працює, живіть його від 5V. Бувають і модулі без стабілізатора: ті, навпаки, живлять лише від 3.3 В.

Правила бібліотеки SD на ESP32

  • Шлях завжди починається зі «/»: "/log.csv". Просто "log.csv" на ESP32 не відкриється.
  • Режими: FILE_READ (за замовчуванням), FILE_WRITE — перезаписує файл з нуля, FILE_APPEND — дописує в кінець. Для логера потрібен саме APPEND.
  • if (f) перевіряє, чи файл відкрився. Картку могли вийняти, файлу може не бути.
  • close() обов'язковий. Картка пише секторами по 512 байт, і поки файл не закрито (або не викликано flush()), дані лежать у буфері. Вимкнули живлення — дані втрачено.
  • Відкривати й закривати файл на кожен запис — нормально для логера раз на кілька секунд. Для сотень записів на секунду тримайте файл відкритим і робіть flush() раз на 1–2 секунди.

Код

// Логер на microSD: DHT22 + годинник DS3231 → /log.csv кожні 5 с
#include <SD.h>
#include <RTClib.h>
#include <DHT.h>

const int SD_CS = 5;
const unsigned long PERIOD_MS = 5000;
RTC_DS3231 rtc;
DHT dht(27, DHT22);
unsigned long lastLog = 0;

// шапку CSV пишемо лише в новий (або щойно видалений) файл
void ensureHeader() {
  if (SD.exists("/log.csv")) return;
  File f = SD.open("/log.csv", FILE_WRITE);
  f.println("time,temperature,humidity");
  f.close();
}

void logLine() {
  float t = dht.readTemperature();
  float h = dht.readHumidity();
  if (isnan(t) || isnan(h)) return;
  DateTime now = rtc.now();
  char line[48];
  snprintf(line, sizeof line, "%04d-%02d-%02d %02d:%02d:%02d,%.1f,%.0f",
           now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second(), t, h);
  ensureHeader();
  File f = SD.open("/log.csv", FILE_APPEND);
  if (!f) {
    Serial.println("Не вдалося відкрити /log.csv");
    return;
  }
  f.println(line);
  f.close();   // лише close() (або flush()) справді записує дані на картку
  Serial.println(line);
}

void setup() {
  Serial.begin(115200);
  dht.begin();
  if (!rtc.begin()) Serial.println("DS3231 не знайдено");
  else if (rtc.lostPower()) rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  if (!SD.begin(SD_CS)) {
    Serial.println("Картка не монтується: перевірте живлення й підключення");
    while (true) delay(1000);
  }
  ensureHeader();
  Serial.println("Запис у /log.csv. Команди: dump — показати файл, clear — видалити");
}

void loop() {
  if (millis() - lastLog >= PERIOD_MS) {
    lastLog = millis();
    logLine();
  }
  if (Serial.available()) {
    String cmd = Serial.readStringUntil('\n');
    cmd.trim();
    if (cmd == "dump") {
      File f = SD.open("/log.csv");
      while (f.available()) Serial.write(f.read());
      f.close();
    } else if (cmd == "clear") {
      SD.remove("/log.csv");
      Serial.println("Файл видалено");
    }
  }
}

Як відкрити в Excel

Файл виглядає так:

time,temperature,humidity
2026-09-30 14:05:00,22.4,55
2026-09-30 14:05:05,22.5,55

Excel з українською локаллю чекає крапку з комою як роздільник і кому в дробових числах. Скористайтеся «Дані → З тексту/CSV» і вкажіть роздільник «кома». У Google Таблицях файл відкривається як є.

Корисно знати

  • Картка не монтується. Спершу живлення модуля, потім формат: FAT32 (картки на 64 ГБ і більше виходять з exFAT, їх треба переформатувати). Дроти SPI — якомога коротші.
  • Струм під час запису стрибає до 80–100 мА. На слабкому живленні запис може перезавантажити ESP32.
  • Ресурс. Кожен сектор витримує тисячі–десятки тисяч перезаписів. Рядок раз на 5 секунд — це роки роботи.
  • Симулятор зберігає файли картки разом із проєктом (до 256 КБ), тож після перезапуску скетча дані залишаються, як на справжній картці.