ESP32-CAM ile Edge AI Yüz/Nesne Tanıma (ESP-WHO)
Proje Amacı
Kameradan alınan görüntü üzerinde, veriyi buluta göndermeden doğrudan cihaz üzerinde (edge AI) yüz tespiti yapmayı öğretir; Espressif'in ESP-WHO/esp-dl çerçevesi, kamera modülünün PSRAM'ini kullanarak görüntü karelerini tamponlayıp önceden eğitilmiş küçük bir sinir ağı modelini gerçek zamanlı çalıştırır. ESP32-CAM'in özel kamera arayüzü (DVP) ve harici PSRAM çipi, görüntü karelerini ve model ağırlıklarını aynı anda bellekte tutabilecek kapasiteyi sağlar. Bu tür bir işlem Arduino Uno'da gerçekleştirilemez: kamera bağlamak için gereken paralel DVP arayüzü hiç yoktur, PSRAM'i yoktur ve 2KB dahili RAM'i tek bir düşük çözünürlüklü görüntü karesini bile tutmaya yetmez — bir yapay sinir ağı modelini çalıştırmak ise bambaşka bir kapasite gerektirir.
Gerekli Malzemeler
- ESP32-CAM (AI-Thinker) modülü — DİKKAT: standart 'ESP32 DevKit V1' KARTI DEĞİLDİR, ayrı bir kamera modülüdür, farklı pin yerleşimine sahiptir
- FTDI USB-TTL programlayıcı (ESP32-CAM'de USB portu yoktur, programlamak için ZORUNLUDUR)
- OV2640 kamera (modülle birlikte gelir, entegre)
- Jumper kablolar
- Harici 5V güç kaynağı (kamera+WiFi eşzamanlı yüksek akım çeker, FTDI'nin 3.3V hattı çoğu zaman yetersiz kalır)
Gerekli Kütüphaneler
esp_camera.h (espressif/esp32-camera, ESP32 core'a 'AI Thinker' board paketiyle birlikte gelir). ESP-WHO framework (Espressif GitHub'ından ayrıca indirilir, PlatformIO ile entegrasyonu Arduino IDE'den daha sorunsuzdur) veya basitleştirilmiş alternatif olarak bu örnekte fd_forward.h (esp-face) insan yüzü tespiti kullanılmıştır.
Pin Bağlantıları
| Bileşen Pini | Bağlantı |
|---|---|
| FTDI TX -> ESP32-CAM | U0R (RX) |
| FTDI RX -> ESP32-CAM | U0T (TX) |
| FTDI GND -> ESP32-CAM | GND |
| FTDI 5V -> ESP32-CAM 5V | 5V |
| Programlama modu (SADECE kod yüklerken, GPIO0 -> GND) | GPIO0Strapping pin |
Devre Şeması
ESP32 Kodu
| 1 | // NOT: ESP32-CAM (AI-Thinker) modülünde kamera pinleri board tanımında |
| 2 | // SABİTTİR, kullanıcı tarafından kablolanmaz. Bu yüzden pin_connections |
| 3 | // tablosu sadece PROGRAMLAMA (FTDI) bağlantılarını gösterir. |
| 4 | #include <esp_camera.h> |
| 5 | #include <WiFi.h> |
| 6 | |
| 7 | // AI-Thinker ESP32-CAM kamera pin tanımları (board paketi tarafından sabitlenir) |
| 8 | #define PWDN_GPIO_NUM 32 |
| 9 | #define RESET_GPIO_NUM -1 |
| 10 | #define XCLK_GPIO_NUM 0 |
| 11 | #define SIOD_GPIO_NUM 26 |
| 12 | #define SIOC_GPIO_NUM 27 |
| 13 | #define Y9_GPIO_NUM 35 |
| 14 | #define Y8_GPIO_NUM 34 |
| 15 | #define Y7_GPIO_NUM 39 |
| 16 | #define Y6_GPIO_NUM 36 |
| 17 | #define Y5_GPIO_NUM 21 |
| 18 | #define Y4_GPIO_NUM 19 |
| 19 | #define Y3_GPIO_NUM 18 |
| 20 | #define Y2_GPIO_NUM 5 |
| 21 | #define VSYNC_GPIO_NUM 25 |
| 22 | #define HREF_GPIO_NUM 23 |
| 23 | #define PCLK_GPIO_NUM 22 |
| 24 | |
| 25 | const char* ssid = "WIFI_ADINIZ"; |
| 26 | const char* password = "WIFI_SIFRENIZ"; |
| 27 | |
| 28 | bool kameraBaslat() { |
| 29 | camera_config_t config; |
| 30 | config.ledc_channel = LEDC_CHANNEL_0; |
| 31 | config.ledc_timer = LEDC_TIMER_0; |
| 32 | config.pin_d0 = Y2_GPIO_NUM; config.pin_d1 = Y3_GPIO_NUM; |
| 33 | config.pin_d2 = Y4_GPIO_NUM; config.pin_d3 = Y5_GPIO_NUM; |
| 34 | config.pin_d4 = Y6_GPIO_NUM; config.pin_d5 = Y7_GPIO_NUM; |
| 35 | config.pin_d6 = Y8_GPIO_NUM; config.pin_d7 = Y9_GPIO_NUM; |
| 36 | config.pin_xclk = XCLK_GPIO_NUM; config.pin_pclk = PCLK_GPIO_NUM; |
| 37 | config.pin_vsync = VSYNC_GPIO_NUM; config.pin_href = HREF_GPIO_NUM; |
| 38 | config.pin_sscb_sda = SIOD_GPIO_NUM; config.pin_sscb_scl = SIOC_GPIO_NUM; |
| 39 | config.pin_pwdn = PWDN_GPIO_NUM; config.pin_reset = RESET_GPIO_NUM; |
| 40 | config.xclk_freq_hz = 20000000; |
| 41 | config.pixel_format = PIXFORMAT_GRAYSCALE; // yüz tespiti için gri tonlama yeterli ve hızlı |
| 42 | config.frame_size = FRAMESIZE_QVGA; // 320x240 — edge AI için makul hız/doğruluk dengesi |
| 43 | config.fb_count = 1; |
| 44 | |
| 45 | return esp_camera_init(&config) == ESP_OK; |
| 46 | } |
| 47 | |
| 48 | void setup() { |
| 49 | Serial.begin(115200); |
| 50 | if (!kameraBaslat()) { |
| 51 | Serial.println("Kamera başlatılamadı! Pin bağlantılarını ve PSRAM'in aktif olduğunu kontrol edin."); |
| 52 | return; |
| 53 | } |
| 54 | Serial.println("Kamera hazır."); |
| 55 | |
| 56 | WiFi.begin(ssid, password); |
| 57 | while (WiFi.status() != WL_CONNECTED) { delay(400); Serial.print("."); } |
| 58 | Serial.println("\nBağlandı: " + WiFi.localIP().toString()); |
| 59 | Serial.println("Not: Gerçek yüz tespiti modeli için ESP-WHO/esp-face kütüphanesindeki"); |
| 60 | Serial.println("'human_face_detect' örneğini bu projeye entegre edin (fd_forward.h)."); |
| 61 | } |
| 62 | |
| 63 | void loop() { |
| 64 | camera_fb_t* kare = esp_camera_fb_get(); |
| 65 | if (!kare) { |
| 66 | Serial.println("Kare alınamadı."); |
| 67 | delay(1000); |
| 68 | return; |
| 69 | } |
| 70 | |
| 71 | // Burada gerçek projede: HumanFaceDetectMSR01 + HumanFaceDetectMNP01 |
| 72 | // sınıflarıyla (esp-face kütüphanesi) kare üzerinde yüz tespiti çalıştırılır |
| 73 | // ve tespit edilen yüz sayısı/konumu Serial'e veya WiFi üzerinden bir |
| 74 | // panele bildirilir. Bu iskelet kod, kamera+WiFi kurulumunun DOĞRU ve |
| 75 | // ÇALIŞIR durumda olduğunu doğrulamak için tasarlanmıştır. |
| 76 | Serial.printf("Kare alındı: %dx%d, %d byte\n", kare->width, kare->height, kare->len); |
| 77 | |
| 78 | esp_camera_fb_return(kare); |
| 79 | delay(200); |
| 80 | } |
Çalışma Açıklaması
Bu proje bilinçli olarak standart 'ESP32 DevKit V1 (38 pin)' platformundan farklı bir donanım (ESP32-CAM/AI-Thinker) gerektirir — kamera arayüzü sadece o modülde bulunur. GPIO0'ı GND'ye bağlamak sadece kod yükleme anında yapılır, normal çalışmada bu bağlantı kaldırılmalıdır (aksi halde kart her açılışta programlama moduna girip normal çalışmaz) — bu, GPIO0'ın strapping pin olmasının doğrudan bir sonucudur.
Test Bilgisi
ESP32-CAM'i FTDI ile bilgisayara bağlayın, GPIO0'ı GND'ye kısa devre yapıp güç verin (programlama modu), kodu yükleyin, GPIO0 bağlantısını kesip RESET'e basın (normal çalışma modu). Seri Monitör'de (115200 baud) 'Kamera hazır' ve ardışık kare boyutu loglarını görmelisiniz. Kamerayı bir yüze doğrultup ESP-WHO entegrasyonu tamamlandıktan sonra tespit sonucunun loglandığını doğrulayın; bu iskelet doğru çalışıyorsa gerçek yüz tespiti modelini eklemek yalnızca bir kütüphane entegrasyonu meselesidir.
Olası Sorunlar ve Çözümleri
'Kamera başlatılamadı' hatası: Tools > Partition Scheme'den PSRAM'i etkinleştiren bir şema seçtiğinizden ve Tools > Board'da doğru 'AI Thinker ESP32-CAM' seçili olduğundan emin olun. Yükleme sırasında 'Failed to connect' hatası: GPIO0-GND bağlantısının yükleme başlamadan önce yapıldığından ve yükleme bitince kaldırıldığından emin olun. Kamera ve WiFi birlikte çalışırken cihaz kendiliğinden resetleniyorsa (brown-out): bu çok yaygın bir sorundur, FTDI/USB'nin 3.3V hattı yetersiz kalır — mutlaka harici, en az 500mA verebilen ayrı bir 5V kaynak kullanın.
Alternatif Çözümler
Gerçek zamanlı yüz tespiti yerine, belirli aralıklarla fotoğraf çekip WiFi ile bir sunucuya veya Telegram botuna gönderen daha basit bir 'güvenlik kamerası' moduna indirgenebilir (PSRAM/edge-AI karmaşıklığı olmadan). esp_camera_fb_get() ile alınan JPEG kareler doğrudan proje #06'daki ESPAsyncWebServer üzerinden MJPEG akışı olarak yayınlanıp tarayıcıdan canlı izlenebilir. Yüz tespiti yerine esp-dl ile basit nesne sınıflandırma (örn. 'kutu var/yok') gibi daha hafif bir model denenerek işlem yükü ve gecikme azaltılabilir.
Benzer Projeler
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.
Şifreli BLE ile Kimlik Doğrulamalı Akıllı Kilit
BLE (Bluetooth Low Energy) bonding/pairing ile bir telefonun kimliğini bir kez eşleştirip, sonraki bağlantılarda ESP32'nin donanımsal AES şifrelemesiyle korunan bir kanaldan 'kilidi aç' komutunu doğrulamayı ve bir servo ile fiziksel kilidi açmayı öğretir. ESP32'nin dahili BLE radyosu, Secure Connections (LE Secure Connections) ile şifreli eşleştirme yapabilecek donanımsal kripto desteğine sahiptir. Bu güvenlik düzeyi Arduino Uno'da kurulamaz: kart hiçbir Bluetooth radyosu (Classic veya BLE) içermez ve kripto hızlandırma donanımı da yoktur; harici bir BLE modülü (HM-10 gibi) eklense bile bu modüller genelde bonding/güvenli eşleştirmeyi tam desteklemez.
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.