راهاندازی ESP32-CAM: آموزش استریم تصویر
راهنمای کامل راهاندازی ماژول ESP32-CAM (AI Thinker)
مقدمه
ماژول ESP32-CAM یکی از محبوبترین و اقتصادیترین ماژولهای دوربین بر پایه تراشه ESP32 است که امکاناتی مانند استریم تصویر، تشخیص چهره، ضبط عکس و ذخیره روی کارت SD را فراهم میکند. اما بهدلیل تنوع نسخهها (مثل AI Thinker و مدلهای مشابه چینی)، لازم است مراحل راهاندازی و تنظیمات با دقت انجام شود.
در این راهنما به شما نشان میدهیم چگونه این ماژول را بهدرستی راهاندازی کنید، کدهای مورد نیاز را روی آن آپلود نمایید و تصویر را در مرورگر مشاهده کنید.
معرفی سختافزار مورد نیاز
- ماژول ESP32-CAM (ترجیحاً مدل AI Thinker)
- برد توسعه/پروگرمر مثل ESP32-CAM-MB
- کابل USB مناسب
- کارت حافظه MicroSD (در صورت نیاز به ذخیره عکس)
- آداپتور یا منبع تغذیه مطمئن ۵ ولت ۲ آمپر (در صورت استفاده بدون USB)
نکته مهم: مدل AI Thinker معمولاً دارای PSRAM است که باعث بهبود کیفیت عکس و امکان انتخاب رزولوشنهای بالاتر میشود. در برخی نسخههای چینی این ویژگی ممکن است وجود نداشته باشد.
مرحله اول: تنظیمات Arduino IDE
برای برنامهریزی برد، ابتدا Arduino IDE را باز کرده و مراحل زیر را دنبال کنید:
۱. نصب ESP32 Board:
در تنظیمات Arduino IDE مسیر زیر را در بخش Preferences > Additional Board URLs وارد کنید:
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
سپس از Boards Manager، پکیج ESP32 را جستجو و نصب نمایید.
۲. انتخاب برد مناسب:
از منوی Tools > Board گزینه AI Thinker ESP32-CAM
را انتخاب کنید.
اگر این گزینه در لیست نبود، ابتدا گزینه
ESP32 Wrover Module
را انتخاب کنید، اما AI Thinker توصیه میشود چون دقیقاً با پینهای این ماژول سازگار است.
۳. تنظیمات دیگر:
- Partition Scheme:
Huge APP (3MB No OTA / 1MB SPIFFS)
یا مشابه آن - Flash Frequency:
40 MHz
- Flash Mode:
DIO
- Upload Speed:
115200
۴. فعالسازی PSRAM (در صورت نیاز):
از منوی Tools گزینه PSRAM: Enabled
را فعال کنید. (در نسخههای جدید ممکن است خودکار فعال باشد)
مرحله دوم: اتصال سختافزار
- ماژول ESP32-CAM را به برد پروگرمر مثل ESP32-CAM-MB وصل کنید.
- از کابل Micro USB مناسب برای اتصال به کامپیوتر استفاده کنید.
- اگر از پروگرمر USB به UART استفاده میکنید:
- GPIO 0 را به GND وصل کنید (برای ورود به حالت فلش)
- اتصالات RX ↔ TX و TX ↔ RX را چک کنید
مرحله سوم: کد نمونه و تست اولیه
کدی که در ادامه آمده است:
- به ماژول امکان اتصال به WiFi را میدهد
- وبسرور راهاندازی میکند
- امکان تنظیمات کیفیت تصویر، چرخش عمودی، و روشن/خاموش کردن LED
- و پشتیبانی از streaming زنده با لینک
/stream
اگر کارت SD وصل باشد، میتوان با دکمه ذخیره، عکس گرفته و روی کارت ذخیره کرد (در نسخه پیشرفتهتر)
#include "esp_camera.h" #include <WiFi.h> #include <WebServer.h> #include "FS.h" #include "SD.h" #include "SPI.h"</pre> // AI Thinker ESP32-CAM pins #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 #define LED_PIN 4 // SD Card CS pin - تغییر بده اگر CS شما فرق دارد #define SD_CS_PIN 13 const char* ssid = "ARMAGHAN"; const char* password = "ELECTRONIC"; WebServer server(80); framesize_t frameSize = FRAMESIZE_QVGA; int jpegQuality = 12; bool verticalFlip = false; bool ledOn = false; void setup() { Serial.begin(115200); pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); // Mount SD card if(!SD.begin(SD_CS_PIN)){ Serial.println("SD Card Mount Failed"); } else { Serial.println("SD Card mounted successfully"); } 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_sccb_sda = SIOD_GPIO_NUM; config.pin_sccb_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; config.frame_size = frameSize; config.jpeg_quality = jpegQuality; config.fb_count = 1; esp_err_t err = esp_camera_init(&config); if (err != ESP_OK) { Serial.printf("Camera init failed with error 0x%x\n", err); return; } WiFi.begin(ssid, password); Serial.print("Connecting to WiFi"); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("\nWiFi connected. IP: " + WiFi.localIP().toString()); server.on("/", []() { String html = "<html><head><meta name='viewport' content='width=device-width, initial-scale=1'>"; html += "<style>body{font-family:sans-serif; font-size:20px; margin:10px;} input, select{font-size:18px; margin:5px 0;} "; html += "button{font-size:20px; padding:10px 20px; margin-top:10px; cursor:pointer;} </style></head><body>"; html += "<h2>ESP32-CAM Settings</h2>"; html += "<form action='/set'>"; html += "Resolution: <select name='framesize'>"; html += "<option value='QVGA'" + String(frameSize == FRAMESIZE_QVGA ? " selected" : "") + ">QVGA</option>"; html += "<option value='SVGA'" + String(frameSize == FRAMESIZE_SVGA ? " selected" : "") + ">SVGA</option>"; html += "<option value='UXGA'" + String(frameSize == FRAMESIZE_UXGA ? " selected" : "") + ">UXGA</option>"; html += "</select><br>"; html += "JPEG Quality (5-20): <input type='number' name='quality' min='5' max='20' value='" + String(jpegQuality) + "'><br>"; html += "Vertical Flip: <input type='checkbox' name='vflip'" + String(verticalFlip ? " checked" : "") + "><br>"; html += "LED On: <input type='checkbox' name='ledon'" + String(ledOn ? " checked" : "") + "><br>"; html += "<input type='submit' value='Apply'><br><br>"; html += "</form>"; html += "<a href='/stream'>Live Stream</a><br><br>"; html += "<button onclick=\"fetch('/capture').then(resp => resp.text()).then(data => alert(data));\">Capture Photo</button>"; html += "</body></html>"; server.send(200, "text/html", html); }); server.on("/set", []() { if (server.hasArg("framesize")) { String fs = server.arg("framesize"); if (fs == "QVGA") frameSize = FRAMESIZE_QVGA; else if (fs == "SVGA") frameSize = FRAMESIZE_SVGA; else if (fs == "UXGA") frameSize = FRAMESIZE_UXGA; } if (server.hasArg("quality")) { int q = server.arg("quality").toInt(); if (q >= 5 && q <= 20) jpegQuality = q; } verticalFlip = server.hasArg("vflip"); ledOn = server.hasArg("ledon"); digitalWrite(LED_PIN, ledOn ? HIGH : LOW); sensor_t * s = esp_camera_sensor_get(); if (s) { s->set_framesize(s, frameSize); s->set_vflip(s, verticalFlip ? 1 : 0); } server.sendHeader("Location", "/"); server.send(302, "text/plain", ""); }); server.on("/stream", []() { WiFiClient client = server.client(); String response = "HTTP/1.1 200 OK\r\nContent-Type: multipart/x-mixed-replace; boundary=frame\r\n\r\n"; server.sendContent(response); while (client.connected()) { camera_fb_t * fb = esp_camera_fb_get(); if (!fb) { Serial.println("Camera capture failed"); break; } response = "--frame\r\nContent-Type: image/jpeg\r\nContent-Length: " + String(fb->len) + "\r\n\r\n"; server.sendContent(response); client.write(fb->buf, fb->len); server.sendContent("\r\n"); esp_camera_fb_return(fb); if (!client.connected()) break; } }); server.on("/capture", []() { camera_fb_t * fb = esp_camera_fb_get(); if (!fb) { server.send(500, "text/plain", "Camera capture failed"); return; } // Save to SD card with timestamp filename String path = "/photo_" + String(millis()) + ".jpg"; File file = SD.open(path.c_str(), FILE_WRITE); if (!file) { esp_camera_fb_return(fb); server.send(500, "text/plain", "Failed to open file on SD"); return; } file.write(fb->buf, fb->len); file.close(); esp_camera_fb_return(fb); server.send(200, "text/plain", "Photo saved to SD as " + path); }); server.begin(); } void loop() { server.handleClient(); }
نکات مهم در کد:
- GPIO4 برای کنترل LED فلش استفاده میشود (روشنایی اختیاری شده)
- آدرس IP پس از اتصال به WiFi در سریال مانیتور نمایش داده میشود
- استریم تصویر از مسیر
http://<IP_ADDRESS>/stream
در مرورگر قابل مشاهده است
مرحله چهارم: اجرا و مشاهده نتیجه
- پس از آپلود کد، مانیتور سریال را باز کنید و منتظر بمانید تا اتصال WiFi برقرار شود.
- آدرس IP نمایش دادهشده را در مرورگر وارد کنید.
- صفحه تنظیمات ساده باز میشود:
- انتخاب کیفیت تصویر
- چرخش تصویر
- روشن/خاموش کردن LED
- پس از اعمال تنظیمات، روی لینک
View Stream
کلیک کنید تا تصویر زنده دوربین را ببینید.
قابلیتهای پیشرفته با کارت SD
اگر کارت MicroSD به ماژول متصل باشد و به درستی mount شود:
✅ میتوان با یک دکمه ساده:
- تصویر را ذخیره کرد (JPEG)
- فایل را روی کارت SD با نام یکتا ذخیره کرد
✅ امکانات دیگر قابل توسعه:
- ضبط دورهای تصاویر (Time-lapse)
- تشخیص چهره و ذخیره خودکار
- ارسال تصاویر از طریق اینترنت یا ایمیل
جمعبندی
ماژول ESP32-CAM یک ابزار بسیار قدرتمند برای پروژههای IoT و امنیتی است. با راهاندازی صحیح و استفاده از PSRAM و کارت SD، میتوانید پروژههایی مانند:
- دوربین امنیتی بیسیم
- کنترل از راه دور تصویر
- تشخیص چهره و تشخیص حرکت
- ثبت عکس و ذخیره روی SD را به سادگی پیادهسازی کنید.
اگر سوال یا مشکلی در اجرای مراحل دارید، در بخش نظرات بپرسید یا با ما در ارتباط باشید 🌐