ESP32 Projeleri
#18İleri

SD Kart + Bulut Senkronizasyonlu Kesintisiz Veri Kayıt Sistemi

~2,5 saatSPI haberleşme ve temel HTTP istekleri

Proje Amacı

Sensör verisini sürekli olarak SPI üzerinden bir SD karta yazıp, WiFi bağlantısı müsait olduğunda kaydedilmiş verileri toplu halde buluta senkronize etmeyi öğretir — bağlantı kesilse bile veri kaybı olmadan çalışan, sahadaki gerçek IoT sistemlerinde aranan bir kayıt mimarisidir. ESP32'nin iki çekirdeği, bir tarafta SD karta yazma (SPI, göreceli yavaş) işlemini yaparken diğer tarafta WiFi/HTTP senkronizasyonunu eşzamanlı ve birbirini bloklamadan yürütebilir. Bu mimari Arduino Uno'da kurulamaz: SD kartı SPI ile teorik olarak bağlamak mümkün olsa da WiFi donanımı olmadığından buluta senkronizasyon yapılamaz; ayrıca 2KB RAM, SD dosya sistemi arabellekleriyle birlikte bir ağ yığınını aynı anda çalıştırmaya yetmez.

Gerekli Malzemeler

  • ESP32 DevKit V1 (38 pin)
  • MicroSD kart modülü (SPI arayüzlü)
  • MicroSD kart (FAT32 formatlı)
  • DHT22 sıcaklık/nem sensörü
  • 10kΩ direnç (pull-up)
  • Breadboard
  • Jumper kablolar

Gerekli Kütüphaneler

SD.h + SPI.h (ikisi de ESP32 core ile gelir). DHT sensor library (Adafruit, >= 1.4.4). HTTPClient.h (senkronizasyon için, ESP32 core ile gelir).

Pin Bağlantıları

Bileşen PiniBağlantı
SD CS
GPIO5
SD SCK
GPIO18
SD MISO
GPIO19
SD MOSI
GPIO23
SD VCC
5V (VIN)
SD GND
GND
DHT22 VCC
3V3
DHT22 GND
GND
DHT22 DATA (10kΩ pull-up ile 3V3'e)
GPIO27

Devre Şeması

ESP32 Kodu

esp32-18-sd-kart-bulut-senkronizasyonlu-kesintisiz-veri-kayit-sistemi.ino
1#include <SPI.h>
2#include <SD.h>
3#include <WiFi.h>
4#include <HTTPClient.h>
5#include <DHT.h>
6
7#define DHTPIN 27
8#define DHTTYPE DHT22
9#define SD_CS 5
10#define GUNLUK_DOSYA "/veri_gunlugu.csv"
11
12DHT dht(DHTPIN, DHTTYPE);
13const char* ssid = "WIFI_ADINIZ";
14const char* password = "WIFI_SIFRENIZ";
15const char* sunucuUrl = "https://ornek-sunucu.com/api/veri";
16
17void kaydiYazSD(float sicaklik, float nem) {
18 File dosya = SD.open(GUNLUK_DOSYA, FILE_APPEND);
19 if (dosya) {
20 dosya.printf("%lu,%.1f,%.1f,0\n", millis(), sicaklik, nem); // son alan: 0=senkronize edilmedi
21 dosya.close();
22 } else {
23 Serial.println("SD karta yazılamadı!");
24 }
25}
26
27void bulutaSenkronizeEt() {
28 if (WiFi.status() != WL_CONNECTED) return; // bağlantı yoksa dene bile, sıradaki döngüde tekrar denenir
29
30 File okuma = SD.open(GUNLUK_DOSYA, FILE_READ);
31 if (!okuma) return;
32
33 int gonderilen = 0;
34 while (okuma.available()) {
35 String satir = okuma.readStringUntil('\n');
36 if (satir.indexOf(",0") == satir.length() - 2) { // sonu ",0" ile bitenler henüz gönderilmemiş
37 HTTPClient http;
38 http.begin(sunucuUrl);
39 http.addHeader("Content-Type", "text/csv");
40 int kod = http.POST(satir);
41 if (kod == 200) gonderilen++;
42 http.end();
43 }
44 }
45 okuma.close();
46 if (gonderilen > 0) Serial.printf("%d kayıt buluta senkronize edildi.\n", gonderilen);
47 // NOT: Üretim kodunda gönderilen satırları "1" olarak işaretlemek için
48 // dosyanın yeniden yazılması (veya ayrı bir "senkronize edildi" indeks
49 // dosyası tutulması) gerekir — bu iskelet basitlik için atlanmıştır.
50}
51
52void setup() {
53 Serial.begin(115200);
54 dht.begin();
55
56 if (!SD.begin(SD_CS)) {
57 Serial.println("SD kart bulunamadı! Kayıt bu oturumda YAPILAMAYACAK.");
58 } else {
59 Serial.println("SD kart hazır.");
60 }
61
62 WiFi.begin(ssid, password);
63 unsigned long baslangic = millis();
64 while (WiFi.status() != WL_CONNECTED && millis() - baslangic < 8000) delay(300);
65 Serial.println(WiFi.status() == WL_CONNECTED ? "WiFi bağlı." : "WiFi yok, sadece yerel kayıt yapılacak.");
66}
67
68void loop() {
69 float sicaklik = dht.readTemperature();
70 float nem = dht.readHumidity();
71 if (!isnan(sicaklik) && !isnan(nem)) {
72 kaydiYazSD(sicaklik, nem); // ÖNCE her zaman yerel SD karta yaz (asla veri kaybetme)
73 Serial.printf("Kaydedildi: %.1fC, %%%.1f\n", sicaklik, nem);
74 }
75
76 bulutaSenkronizeEt(); // SONRA fırsat varsa buluta gönder
77 delay(5000);
78}

Çalışma Açıklaması

Mimarinin kritik prensibi 'önce yerel diske yaz, sonra fırsat buldukça buluta gönder' sırasıdır — asla tersi olmamalıdır, aksi halde WiFi kesintisinde veri tamamen kaybolur. Bu iskelet kod basitlik için gönderilen kayıtları dosyada işaretlemiyor (yorum satırında belirtildiği gibi); üretimde tekrar gönderimi önlemek için bu mutlaka eklenmelidir, aksi halde aynı veri buluta birden fazla kez gönderilebilir.

Test Bilgisi

WiFi router'ı kapatıp kodu çalıştırın; Seri Monitör'de 'WiFi yok, sadece yerel kayıt yapılacak' mesajını ve düzenli SD kayıt loglarını görün. SD kartı çıkarıp bilgisayarda /veri_gunlugu.csv dosyasını açıp verilerin doğru biçimde (zaman,sıcaklık,nem,0) yazıldığını doğrulayın. Router'ı tekrar açın; birkaç saniye içinde 'buluta senkronize edildi' mesajının göründüğünü doğrulayın (gerçek bir test sunucusu adresi girmeniz gerekir) — bu, kesinti sırasında verinin kaybolmadığının somut kanıtıdır.

Olası Sorunlar ve Çözümleri

'SD kart bulunamadı' hatası: SD modülünün 3.3V yerine yanlışlıkla 5V mantık seviyesiyle çalışan bir klon olup olmadığını kontrol edin (çoğu modülün kendi gerilim regülatörü/seviye çevirici vardır ama ucuz klonlarda olmayabilir, ESP32 pinlerini 3.3V mantık dışına maruz bırakmak pinlere kalıcı zarar verebilir). Kayıtlar SD karta yazılıyor ama hiç senkronize olmuyorsa: sunucuUrl adresinin gerçek ve erişilebilir olduğunu, HTTPS kullanılıyorsa proje #02'deki gibi sertifika doğrulaması gerekip gerekmediğini kontrol edin. SD yazma işlemi zamanla yavaşlıyorsa: dosya çok büyümüş olabilir, periyodik olarak eski ve senkronize edilmiş kayıtları temizleyen bir 'log rotation' mekanizması ekleyin.

Alternatif Çözümler

Düz CSV yerine her satırı ayrı bir JSON nesnesi (NDJSON formatı) olarak yazmak, bulut tarafında ayrıştırmayı kolaylaştırır. WiFi yerine veya yanında proje #02'deki TLS korumalı MQTT ile senkronizasyon yapılarak veri iletimi de şifrelenebilir. Tek bir SD kart yerine, kart dolduğunda otomatik olarak en eski senkronize edilmiş kayıtları silen döngüsel (circular buffer) bir dosya yönetimi eklenerek kart kapasitesi sınırsız gibi kullanılabilir.

Bu projenin kodunu AI ile özelleştir

Farklı pin, ek özellik ya da başka bir sensör mü istiyorsun?

Benzer Projeler

İleri

FreeRTOS Dual-Core Görev Paylaşımlı Veri Toplama

xTaskCreatePinnedToCore() ile iki farklı sensör okuma görevini ESP32'nin iki fiziksel çekirdeğine (Core 0 ve Core 1) sabitleyerek tamamen paralel çalıştırmayı öğretir — biri yavaş ve bloklayıcı DHT22'yi okurken diğeri hızlı analog LDR okumaya kesintisiz devam eder, ikisi birbirini beklemez. ESP32, iki bağımsız Xtensa LX6 çekirdeğine sahiptir; Arduino sketch'i normalde sadece Core 1'de çalışır, Core 0 ise bilinçli olarak görev atanarak devreye alınabilir. Bu paralellik Arduino Uno'da kurulamaz: ATmega328P tek çekirdekli 8-bit bir mikrodenetleyicidir, ikinci bir çekirdeğe görev atamak donanımsal olarak mümkün değildir ve kart FreeRTOS gibi bir RTOS da çalıştıramaz.

İleri

Firebase Cloud Functions ile Sunucusuz Otomasyon Mantığı

ESP32'nin sadece ham sensör verisini (ışık seviyesi) HTTPS ile Firebase Realtime Database'e yazıp, 'ışık şu eşiğin altına düşerse röleyi aç' gibi karar mantığını cihaz üzerinde değil, bulutta çalışan bir Firebase Cloud Function'da (sunucusuz/serverless) tutmayı öğretir — cihaz koduna hiç dokunmadan bulut tarafındaki otomasyon kuralını değiştirebilme esnekliği sunar. ESP32'nin donanımsal kripto hızlandırması ve yeterli RAM'i, Firebase'in gerektirdiği TLS/HTTPS bağlantısını ve JSON işlemeyi sorunsuz yürütür. Bu tür bir bulut entegrasyonu Arduino Uno'da kurulamaz: WiFi yoktur; olsaydı bile TLS handshake için gereken kripto işlemi ve JSON ayrıştırma belleği 2KB SRAM'e hiç sığmaz.

İleri

ESPAsyncWebServer ile Bloklamayan Çoklu İstemci REST API

Birden fazla tarayıcı veya istemcinin aynı anda, birbirini bloklamadan bağlanıp iki rölenin durumunu okuyup değiştirebildiği asenkron (event-driven) bir REST API sunmayı öğretir — akıllı ev panelleri ve endüstriyel kontrol arayüzlerinde tercih edilen mimarinin küçük ölçekli bir örneğidir. ESPAsyncWebServer, gelen her isteği ayrı ayrı bekletmeden (non-blocking) LwIP ağ yığınıyla doğrudan çalışır; bunun için ESP32'nin ikinci çekirdeği ve yeterli RAM'i (520KB SRAM) devreye girer. Bu mimari Arduino Uno'da kurulamaz: WiFi donanımı yoktur; harici bir WiFi shield eklense bile klasik senkron 'WiFiServer' modeli her isteği sırayla işler ve 2KB RAM, birden fazla eşzamanlı bağlantı arabelleğini aynı anda tutmaya yetmez.