ESP32-CAM ile Uzaktan İzleme Sistemi Kurulumu
ESP32-CAM Nedir ve Neden Tercih Edilmeli?
ESP32-CAM, Espressif Systems tarafından üretilen ESP32-S çipini temel alan, üzerinde entegre kamera modülü (OV2640) bulunan kompakt bir geliştirme kartıdır. Wi-Fi ve Bluetooth desteği sayesinde IoT projelerinde sıklıkla tercih edilen bu kart, düşük maliyeti ve yüksek esnekliğiyle ev güvenliği, tarımsal izleme, endüstriyel denetim gibi pek çok alanda kullanılabilir.
Geleneksel IP kamera sistemlerine kıyasla ESP32-CAM'in öne çıkan avantajları şunlardır:
- Düşük maliyet: Ortalama 5-10 dolar arasında temin edilebilir
- Kompakt boyut: 27mm x 40.5mm gibi küçük bir form faktörü
- Wi-Fi desteği: 802.11 b/g/n ile kablosuz bağlantı
- MicroSD kart desteği: Yerel kayıt imkânı
- Dahili LED flaş: Düşük ışık koşullarında aydınlatma
- Esnek programlama: Arduino IDE veya PlatformIO ile kolayca programlanabilir
Gerekli Malzemeler
Uzaktan izleme sisteminizi kurmak için aşağıdaki malzemelere ihtiyacınız olacak:
- ESP32-CAM modülü (AI-Thinker modeli en yaygın olanıdır)
- FTDI USB-TTL dönüştürücü (programlama için, 3.3V destekli)
- Jumper kablolar (dişi-dişi, en az 5 adet)
- Mikro USB kablosu (FTDI için)
- 5V güç kaynağı (en az 500mA, tercihen 1A)
- MicroSD kart (isteğe bağlı, yerel kayıt için)
- 3D baskılı veya hazır muhafaza kutusu (isteğe bağlı)
Donanım Bağlantıları
ESP32-CAM modülünde dahili bir USB port bulunmadığından, programlama için bir FTDI dönüştürücü kullanmanız gerekir. Bağlantıları aşağıdaki şekilde yapın:
- FTDI GND → ESP32-CAM GND
- FTDI VCC (5V) → ESP32-CAM 5V
- FTDI TX → ESP32-CAM U0R (RX)
- FTDI RX → ESP32-CAM U0T (TX)
- ESP32-CAM IO0 → ESP32-CAM GND (sadece programlama sırasında)
Önemli: IO0 pinini GND'ye bağlamak, kartı programlama (flash) moduna geçirir. Programlama tamamlandıktan sonra bu bağlantıyı mutlaka çıkarın ve kartı yeniden başlatın. Aksi takdirde kart normal çalışma moduna geçemez.
Arduino IDE Kurulumu
ESP32-CAM'i programlamak için Arduino IDE'yi hazırlamamız gerekir. Aşağıdaki adımları izleyin:
- Arduino IDE'yi indirin ve kurun (1.8.x veya 2.x sürümü)
- Dosya → Tercihler menüsüne gidin
- Ek Kart Yöneticisi URL'leri alanına şu adresi ekleyin:
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
- Araçlar → Kart → Kart Yöneticisi'ni açın ve esp32 paketini arayıp kurun
- Kart olarak AI Thinker ESP32-CAM'i seçin
- Upload Speed'i 115200 olarak ayarlayın
Web Sunuculu Kamera Yazılımı
Aşağıdaki kod, ESP32-CAM üzerinde bir web sunucu oluşturarak tarayıcı üzerinden canlı görüntü akışı sağlar. Bu temel kod üzerine hareket algılama, anlık görüntü yakalama ve bildirim gibi özellikler eklenebilir.
#include "esp_camera.h"
#include <WiFi.h>
#include "esp_http_server.h"
// Wi-Fi bilgilerinizi buraya girin
const char* ssid = "WIFI_ADINIZ";
const char* password = "WIFI_SIFRENIZ";
// AI-Thinker ESP32-CAM pin tanımlamaları
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
// LED flaş pini
#define FLASH_GPIO_NUM 4
httpd_handle_t stream_httpd = NULL;
// MJPEG akış boundary tanımı
#define PART_BOUNDARY "123456789000000000000987654321"
static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";
static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n";
// Akış handler fonksiyonu
static esp_err_t stream_handler(httpd_req_t *req) {
camera_fb_t *fb = NULL;
esp_err_t res = ESP_OK;
char part_buf[64];
res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE);
if (res != ESP_OK) return res;
while (true) {
fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Kamera goruntusu alinamadi");
res = ESP_FAIL;
} else {
size_t hlen = snprintf(part_buf, 64, _STREAM_PART, fb->len);
res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY,
strlen(_STREAM_BOUNDARY));
if (res == ESP_OK) {
res = httpd_resp_send_chunk(req, part_buf, hlen);
}
if (res == ESP_OK) {
res = httpd_resp_send_chunk(req, (const char *)fb->buf,
fb->len);
}
esp_camera_fb_return(fb);
}
if (res != ESP_OK) break;
}
return res;
}
// Ana sayfa handler fonksiyonu
static esp_err_t index_handler(httpd_req_t *req) {
const char html[] = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
<title>ESP32-CAM Izleme</title>
<style>
body { font-family: Arial; text-align: center;
background: #1a1a2e; color: #eee; }
img { max-width: 100%; border: 2px solid #0f3460; }
h1 { color: #e94560; }
.container { max-width: 800px; margin: 0 auto;
padding: 20px; }
.btn { background: #0f3460; color: white; border: none;
padding: 10px 20px; margin: 5px; cursor: pointer;
border-radius: 5px; font-size: 16px; }
.btn:hover { background: #e94560; }
</style>
</head>
<body>
<div class="container">
<h1>ESP32-CAM Uzaktan Izleme</h1>
<img src="/stream" id="stream">
<br><br>
<button class="btn"
onclick="fetch('/flash?state=toggle')">
Flash LED
</button>
</div>
</body>
</html>
)rawliteral";
httpd_resp_set_type(req, "text/html");
return httpd_resp_send(req, html, strlen(html));
}
// Flash LED kontrolü
static esp_err_t flash_handler(httpd_req_t *req) {
static bool flashState = false;
flashState = !flashState;
digitalWrite(FLASH_GPIO_NUM, flashState ? HIGH : LOW);
httpd_resp_set_type(req, "text/plain");
return httpd_resp_send(req, flashState ? "ON" : "OFF", -1);
}
void startServer() {
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.server_port = 80;
httpd_uri_t index_uri = {
.uri = "/",
.method = HTTP_GET,
.handler = index_handler,
.user_ctx = NULL
};
httpd_uri_t stream_uri = {
.uri = "/stream",
.method = HTTP_GET,
.handler = stream_handler,
.user_ctx = NULL
};
httpd_uri_t flash_uri = {
.uri = "/flash",
.method = HTTP_GET,
.handler = flash_handler,
.user_ctx = NULL
};
if (httpd_start(&stream_httpd, &config) == ESP_OK) {
httpd_register_uri_handler(stream_httpd, &index_uri);
httpd_register_uri_handler(stream_httpd, &stream_uri);
httpd_register_uri_handler(stream_httpd, &flash_uri);
}
}
void setup() {
Serial.begin(115200);
Serial.println();
// Flash LED pin ayarı
pinMode(FLASH_GPIO_NUM, OUTPUT);
digitalWrite(FLASH_GPIO_NUM, LOW);
// Kamera yapılandırması
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.pixel_format = PIXFORMAT_JPEG;
// PSRAM varsa yüksek çözünürlük kullan
if (psramFound()) {
config.frame_size = FRAMESIZE_UXGA;
config.jpeg_quality = 10;
config.fb_count = 2;
Serial.println("PSRAM bulundu, yuksek cozunurluk aktif");
} else {
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 12;
config.fb_count = 1;
Serial.println("PSRAM bulunamadi, dusuk cozunurluk aktif");
}
// Kamerayı başlat
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Kamera baslatilamadi, hata: 0x%x\n", err);
return;
}
// Kamera sensör ayarları
sensor_t *s = esp_camera_sensor_get();
s->set_brightness(s, 1);
s->set_contrast(s, 1);
s->set_saturation(s, 0);
s->set_whitebal(s, 1);
s->set_awb_gain(s, 1);
s->set_wb_mode(s, 0);
// Wi-Fi bağlantısı
WiFi.begin(ssid, password);
WiFi.setSleep(false);
Serial.print("WiFi'ye baglaniliyor");
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 30) {
delay(500);
Serial.print(".");
attempts++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println();
Serial.println("WiFi baglantisi basarili!");
Serial.print("Kamera adresi: http://");
Serial.println(WiFi.localIP());
startServer();
} else {
Serial.println();
Serial.println("WiFi baglantisi basarisiz!");
ESP.restart();
}
}
void loop() {
// Bağlantı kopması durumunda yeniden bağlan
if (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi baglantisi koptu, yeniden deneniyor...");
WiFi.reconnect();
delay(5000);
if (WiFi.status() != WL_CONNECTED) {
ESP.restart();
}
}
delay(10000);
}
Kodu Yükleme Adımları
- FTDI bağlantılarını yapın ve IO0 pinini GND'ye bağlayın
- Arduino IDE'de doğru port ve kart seçili olduğundan emin olun
- Koddaki
WIFI_ADINIZveWIFI_SIFRENIZdeğerlerini kendi ağ bilgilerinizle değiştirin - Yükle butonuna basın
- Konsolda "Connecting..." mesajı görünürken ESP32-CAM üzerindeki RST butonuna basın
- Yükleme tamamlandıktan sonra IO0-GND bağlantısını çıkarın
- RST butonuna tekrar basarak kartı yeniden başlatın
- Seri monitörü 115200 baud hızında açın ve IP adresini not edin
- Tarayıcınızda gösterilen IP adresine gidin (örn:
http://192.168.1.105)
Uzaktan Erişim Yapılandırması
ESP32-CAM varsayılan olarak yalnızca yerel ağınızda erişilebilir durumdadır. Dışarıdan erişim sağlamak için birkaç yöntem kullanabilirsiniz:
1. Port Yönlendirme (Port Forwarding)
Router ayarlarınızdan 80 numaralı portu ESP32-CAM'in yerel IP adresine yönlendirin. Ancak bu yöntem güvenlik riskleri taşır ve statik IP veya DDNS hizmeti gerektirir.
2. Reverse Tunnel Servisleri
Cloudflare Tunnel, ngrok veya PageKite gibi servisler NAT arkasındaki cihazlarınıza güvenli bir şekilde dışarıdan erişim sağlar. Bu yöntem port yönlendirmeye göre çok daha güvenlidir. Ancak bu servisleri ESP32-CAM üzerinde doğrudan çalıştıramazsınız; yerel ağınızda bir aracı cihaz (Raspberry Pi, bilgisayar vb.) gerekir.
3. MQTT ile Bildirim Sistemi
Sürekli akış yerine olay tabanlı bir mimari tercih ediyorsanız, ESP32-CAM'den bir MQTT broker'a (örneğin Mosquitto) anlık görüntüler veya hareket algılama bildirimleri gönderebilirsiniz. Bu yöntem bant genişliği tüketimini önemli ölçüde azaltır.
Performans İyileştirmeleri
ESP32-CAM'den en iyi performansı almak için aşağıdaki önerilere dikkat edin:
- Çözünürlüğü ihtiyaca göre ayarlayın: Sürekli akış için
FRAMESIZE_VGAveyaFRAMESIZE_SVGAyeterlidir. Yüksek çözünürlük FPS değerini düşürür. - JPEG kalitesini dengeleyin:
jpeg_qualitydeğeri 10-15 arası çoğu senaryo için idealdir. Düşük değer daha iyi kalite ancak daha büyük dosya boyutu demektir. - Wi-Fi sinyalini güçlü tutun: ESP32-CAM'in dahili anteni zayıftır. Harici anten bağlantısı destekleyen modellerde harici anten kullanmayı tercih edin. Bunun için kart üzerindeki 0 ohm direnci harici anten padına lehimlemeniz gerekir.
- Güç kaynağına dikkat edin: Yetersiz güç kaynağı kararsız çalışmaya, ani yeniden başlamalara ve kamera hatalarına neden olur. USB'den besleme yerine düzenli bir 5V/1A adaptör kullanın.
- Isınmayı göz önünde bulundurun: Sürekli akış sırasında ESP32-CAM ısınabilir. Kapalı muhafazalarda havalandırma delikleri bırakın.
Sık Karşılaşılan Sorunlar ve Çözümleri
Kamera başlatılamadı hatası (0x20001)
Bu genellikle kamera modülünün düzgün oturmadığını gösterir. Kamera ribbon kablosunu çıkarıp tekrar takın, altın kontakların konnektöre doğru baktığından emin olun. Ayrıca güç kaynağınızın yeterli akım sağladığını kontrol edin.
Wi-Fi bağlantısı kurulamıyor
SSID ve şifrenin doğru olduğunu kontrol edin. ESP32-CAM yalnızca 2.4 GHz ağları destekler; 5 GHz ağlara bağlanamaz. Router'ınızda MAC filtreleme aktifse ESP32-CAM'in MAC adresini beyaz listeye ekleyin.
Görüntü bulanık veya karanlık
Kamera lensinin üzerindeki koruyucu plastiği çıkardığınızdan emin olun. Lens odağını, lensi yavaşça saat yönünde veya tersine çevirerek manuel olarak ayarlayabilirsiniz. Düşük ışık ortamlarında set_brightness ve set_gainceiling değerlerini artırmayı deneyin.
Akış donuyor veya çok yavaş
Çözünürlüğü düşürün, fb_count değerini 2 yapın (PSRAM gerektirir) ve Wi-Fi sinyal gücünü kontrol edin. Aynı anda birden fazla istemcinin bağlanması performansı önemli ölçüde düşürür.
Güvenlik Önerileri
Bir izleme sistemi kurarken güvenliği göz ardı etmemelisiniz:
- HTTP yerine HTTPS: ESP32-CAM'in sınırlı kaynakları nedeniyle doğrudan TLS zordur, ancak bir reverse proxy (nginx) arkasına alarak HTTPS sağlayabilirsiniz.
- Temel kimlik doğrulama: Web sunucusuna en azından basit bir kullanıcı adı ve şifre doğrulaması ekleyin. HTTP header'larında
Authorizationkontrolü yaparak yetkisiz erişimi engelleyebilirsiniz. - Ağ izolasyonu: IoT cihazlarınızı ana ağınızdan ayrı bir VLAN veya misafir ağında tutun.
- Firmware güncellemeleri: OTA (Over-The-Air) güncelleme desteği ekleyerek güvenlik yamalarını kolayca uygulayabilirsiniz.
Sonuç ve İleri Adımlar
ESP32-CAM ile temel bir uzaktan izleme sistemi kurmak oldukça basit ve ekonomiktir. Bu temel yapı üzerine ekleyebileceğiniz özelliklerden bazıları:
- PIR sensörü ile hareket algılama: GPIO 13 veya 15 pinlerine bir PIR sensör bağlayarak yalnızca hareket olduğunda kayıt veya bildirim gönderebilirsiniz
- MicroSD karta kayıt: Zamanlı veya olay tabanlı görüntü kaydetme
- Telegram bot entegrasyonu: Hareket algılandığında Telegram üzerinden anlık görüntü gönderme
- Çoklu kamera desteği: Birden fazla ESP32-CAM'i merkezi bir panelde birleştirme
- Güneş paneli ile besleme: Dış mekân kullanımı için enerji bağımsız sistem kurulumu
- Deep sleep modu: Pil ömrünü uzatmak için belirli aralıklarla uyandırma ve görüntü gönderme
ESP32-CAM, profesyonel güvenlik kameralarının yerini alacak bir çözüm olmasa da, hobi projeleri, prototipleme ve özelleştirilmiş izleme senaryoları için son derece güçlü ve esnek bir platformdur. Açık kaynak ekosistemi ve geniş topluluk desteği sayesinde hayal gücünüzün sınırlarına kadar genişletebileceğiniz projeler oluşturabilirsiniz.