ورکشاپ آموزشی - آیسی مدار
رفتن به محتوا

دوربین مداربسته هوشمند و پرتابل با ماژول ESP32

ابزار و گجت
۰ نظر
۷۱ نفر
کد ۳۰۶۲

ساخت یک دوربین مداربسته شیک، جمع‌و‌جور و کاملا پرتابل دیگه فقط مختص شرکت‌های بزرگ تکنولوژی نیست. ما قراره با هم یک دوربین امنیتی هوشمند بسازیم که به راحتی توی کف دست جا می‌گیره و هیچ نیازی به سیم‌کشی‌های دردسرساز یا اشتراک‌های ابری گرون‌قیمت نداره. این دوربین همه‌چیز رو به صورت محلی پردازش می‌کنه و خیالت رو بابت امنیت اطلاعات راحت می‌کنه.

توی تیم آیسی‌مدار همیشه عاشق پروژه‌هایی هستیم که ترکیب بی‌نقصی از پرینت سه‌بعدی، الکترونیک و برنامه‌نویسی هستن. دوربینی که در این آموزش می‌سازیم، قابلیت پخش زنده ویدیو، تشخیص حرکت پیشرفته، دید در شب خودکار، ضبط روی کارت حافظه و حتی یک دشبورد کنترلی فوق‌العاده حرفه‌ای تحت وب داره. و بخش هیجان‌انگیزش اینجاست که تمام این پردازش‌های سنگین فقط روی یک میکروکنترلر قدرتمند ESP32-S3 انجام می‌شه!

پس وسایل لحیم‌کاریت رو آماده کن، فیلامنت پرینترت رو لود کن و بریم تا قدم‌به‌قدم این گجت حرفه‌ای و جذاب رو با هم بسازیم و لذت خلق یک محصول واقعی رو تجربه کنیم.

قطعات موردنیاز

  • ماژول دوربین DFRobot ESP32 S3
  • ماژول شارژ باتری (TP4056 یا مشابه)
  • اسپیکر مخصوص DFRobot (برای پخش صدا)
  • باتری قابل شارژ 3.6 ولت (لیتیومی)
  • هویه و وسایل لحیم‌کاری
  • چسب قطره‌ای یا فوری
  • پیچ‌گوشتی مینیاتوری
  • پرینتر سه‌بعدی (برای چاپ قاب دستگاه)
مرحله ۱

طراحی سه‌بعدی بدنه دستگاه

اولین قدم برای ساخت این پروژه، طراحی یک محفظه کامل و ساختار داخلی اصولی برای دوربین بود. همه قطعات از صفر توی نرم‌افزار Fusion 360 طراحی شدن. هدف اصلی این بود که لبه‌ها کاملا نرم باشن، ابعاد تا جای ممکن فشرده در بیاد و قطعات داخلی بدون هیچ فشاری سر جای خودشون بشینن تا موقع مونتاژ به مشکل نخوری.

از اونجایی که این دوربین قراره پرتابل باشه و با باتری کار کنه، می‌خواستیم بدنه‌اش حس یک محصول واقعی، مدرن و مینیمال رو بهت بده، نه اینکه شبیه یک کاردستی الکترونیکی پر از سیم‌های آویزون باشه. به همین دلیل روی تمیزی و باریک بودن طراحی خیلی کار شد.

این طراحی مهندسی‌شده باعث می‌شه تا در نهایت یک خروجی بسیار جذاب و حرفه‌ای داشته باشی که بتونی با افتخار اون رو روی میز یا قفسه اتاقت بذاری.

مرحله ۲

پرینت قطعات بدنه

حالا که فایل‌های طراحی آماده‌ست، باید قطعات رو پرینت بگیریم. بدنه اصلی این دوربین از سه بخش مجزا تشکیل شده که باید جداگانه چاپ بشن:

  1. محفظه اصلی قطعات
  2. درپوش بالایی
  3. رابط پلاستیکی دکمه

برای این دستگاه، فیلامنت PLA با رنگ خاکستری انتخاب بسیار خوبیه، چون هم ظاهر مدرن و صنعتی به دوربین می‌ده و هم پرینت باهاش راحته. دقت ابعادی PLA بالاست و باعث می‌شه قطعات با تلورانس‌های دقیقی که طراحی شدن، خیلی راحت و بدون گیر کردن روی هم مونتاژ بشن.

مرحله ۳

نصب اسپیکر داخل قاب

بریم سراغ نصب اسپیکر. اول باید سیم‌های اسپیکر رو به اندازه مناسب کوتاه کنی. البته یه مقدار خیلی کم اضافه بذار تا موقع مونتاژ نهایی، سیم‌ها اذیتت نکنن و فضای داخل قاب هم شلوغ نشه.

بعد از اون، چسب دوطرفه پشت اسپیکر رو بکن و با دقت اون رو توی قسمت دایره‌ای شکلی که داخل محفظه اصلی براش در نظر گرفته شده قرار بده. با انگشتت کمی فشارش بده تا محکم سر جاش بچسبه.

مرحله ۴

جای‌گذاری باتری

قدم بعدی نصب باتری داخل قاب هست. اول دو تا سیم رو به ترمینال‌های مثبت و منفی باتری لحیم کن تا بعدا بتونیم به راحتی برق سیستم رو تامین کنیم.

توی درپوش بالایی بدنه، یک فضای دقیقا هم‌اندازه با باتری طراحی شده تا بدون هدر رفتن هیچ فضای اضافه‌ای، باتری همونجا بشینه. باتری رو داخل این شیار قرار بده و با یک قطره چسب سر جاش محکمش کن تا موقع تکون خوردن دستگاه، لق نزه.

مرحله ۵

اتصال ماژول شارژر

حالا باید باتری رو به ماژول شارژ متصل کنی. سیم‌هایی که به باتری لحیم کرده بودی رو به پایه‌های ورودی باتری روی ماژول شارژ لحیم کن. حتما قبل از لحیم‌کاری مثبت و منفی رو چند بار چک کن تا مدارت نسوزه!

در نهایت دو تا سیم دیگه به خروجی‌های 5 ولت ماژول شارژ لحیم کن. ما از این دو سیم خروجی برای تغذیه برد اصلی ESP32-S3 استفاده می‌کنیم.

مرحله ۶

نگاهی به معماری نرم‌افزاری سیستم

قبل از اینکه بریم سراغ آپلود کد، خیلی مهمه بدونی سیستم داخلی این دوربین چطور کار می‌کنه. فریم‌ور (Firmware) این دستگاه بر پایه سیستم‌عامل درنگ‌درنگ FreeRTOS نوشته شده و به چندین تسک (Task) مجزا تقسیم می‌شه. این یعنی کارهایی مثل استریم ویدیو، تشخیص حرکت، بررسی سنسورها و پخش صدا کاملا مستقل از هم پردازش می‌شن تا هیچ کدوم باعث کندی اون یکی نشه و سیستم همیشه روان کار کنه.

TXT
xTaskCreatePinnedToCore(streamTask, "stream", 8192, nullptr, 5, nullptr, 0);
xTaskCreatePinnedToCore(sensorTask, "sensor", 6144, nullptr, 3, nullptr, 0);
xTaskCreatePinnedToCore(spkTask, "speaker", 6144, nullptr, 2, nullptr, 1);

به جای اینکه تمام دستورات پشت سر هم داخل لوپ اصلی آردوینو نوشته بشن، هر بخش مهم برای خودش یک وظیفه مشخص داره:

  1. تسک استریم ← برای پخش زنده و بدون وقفه ویدیو
  2. تسک سنسورها ← مدیریت تشخیص حرکت، خواندن میکروفون و سنسور نور
  3. تسک اسپیکر ← برای پخش اعلان‌های صوتی و روشن کردن آژیر خطر

این معماری فوق‌العاده باعث می‌شه دوربین بتونه همزمان که تصویر رو زنده پخش می‌کنه، ویدیو رو هم روی کارت حافظه ذخیره کنه، مراقب حرکت‌های مشکوک باشه و در صورت لزوم آژیر بکشه!

مرحله ۷

پیکربندی وای‌فای شبکه

اولین کاری که فریم‌ور بعد از روشن شدن انجام می‌ده، متصل شدن به مودم وای‌فای خونه یا محل کارته.

TXT
#define WIFI_SSID "Your SSID"
#define WIFI_PASS "Your PASS"
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
}

بعد از اینکه ماژول با موفقیت وصل شد، روتر بهش یک آی‌پی (IP Address) اختصاص می‌ده. تو باید این آی‌پی رو برداری و وارد دشبورد تحت وب دستگاه کنی تا ارتباط بین مرورگرت و دوربین برقرار بشه. به همین سادگی، بدون نیاز به نصب هیچ نرم‌افزار یا اپلیکیشن اضافه‌ای می‌تونی تصاویر رو ببینی.

مرحله ۸

راه‌اندازی اولیه سنسور تصویر

برای اینکه بالاترین سرعت رو توی انتقال تصویر داشته باشیم، ماژول دوربین رو طوری تنظیم کردیم که خروجی رو مستقیما با فرمت فشرده JPEG تولید کنه.

TXT
camera_config_t config;
config.pixel_format = PIXFORMAT_JPEG;
config.frame_size = FRAMESIZE_VGA;
config.jpeg_quality = 12;
config.fb_location = CAMERA_FB_IN_PSRAM;
config.fb_count = 2;
esp_camera_init(&config);

سنسور تصویر OV3660 قبل از اینکه اطلاعات رو بفرسته به پردازنده اصلی (ESP32-S3)، خودش تصاویر رو فشرده‌سازی می‌کنه. این کار چند تا مزیت فوق‌العاده داره:

  1. اشغال فضای بسیار کمتری از حافظه رم
  2. افزایش چشمگیر سرعت استریم روی شبکه وای‌فای
  3. کاهش شدید درگیری پردازنده اصلی
  4. افزایش چشمگیر عمر باتری دستگاه

همچنین با استفاده از قابلیت PSRAM، می‌تونیم بافر تصاویر بزرگتری رو ذخیره کنیم، بدون اینکه حافظه ارزشمند داخلی میکروکنترلر هدر بره.

مرحله ۹

پخش زنده ویدیو (Live Stream)

یکی از جذاب‌ترین قابلیت‌های این پروژه، امکان پخش زنده تصاویر به صورت مستقیم روی شبکه وای‌فایه. برد ESP32-S3 مدام فریم‌های JPEG رو از دوربین می‌گیره و اون‌ها رو به شکل یک استریم روان MJPEG برای مرورگر تو ارسال می‌کنه.

TXT
camera_fb_t *fb = esp_camera_fb_get();
if (!fb) {
return;
}
client.write(fb->buf, fb->len);
esp_camera_fb_return(fb);

پروسه به این شکله که دوربین یک فریم عکس می‌گیره و توی بافر ذخیره می‌کنه. بعد، پردازنده این عکس رو از طریق شبکه برای هر کاربری که متصل شده می‌فرسته و بلافاصله بافر رو خالی می‌کنه تا دوربین عکس بعدی رو ثبت کنه.

چون تصاویر از همون اول فشرده و JPEG هستن، پردازنده دیگه نیازی نداره وقتش رو برای فشرده‌سازی عکس‌ها تلف کنه؛ در نتیجه رم و سی‌پی‌یو آزاد می‌مونن تا کارهای دیگه رو انجام بدن.

استریم با فرمت MJPEG خیلی سبکه و تقریبا روی تمام گجت‌ها و مرورگرها بدون نیاز به نصب هیچ افزونه‌ای اجرا می‌شه. در واقع مجموعه‌ای از عکس‌های باکیفیت پشت سر هم ارسال می‌شن که برای دیوایس‌هایی مثل میکروکنترلرها بهترین انتخابه.

  1. مانیتورینگ ویدیویی به صورت کاملا زنده
  2. کمترین میزان تاخیر در دریافت تصویر
  3. اجرای بی‌نقص در تمامی مرورگرهای مدرن
  4. بدون هیچ نیازی به اپلیکیشن موبایل
  5. بهینه‌سازی شده برای نهایت قدرت سخت‌افزار ESP32-S3

این قابلیت پخش زنده، هسته اصلی این پروژه رو تشکیل می‌ده و بهت اجازه می‌ده با دشبورد آنلاین، از هر نقطه‌ای توی محدوده شبکه، به راحتی به اطرافت مسلط باشی.

مرحله ۱۰

موتور تشخیص حرکت محلی

برای اینکه این دستگاه فقط یک دوربین ساده نباشه، یک سیستم تشخیص حرکت بسیار سبک و سریع روی اون پیاده‌سازی کردیم که تمام محاسباتش مستقیما روی خود تراشه ESP32-S3 انجام می‌شه و نیازی به سرورهای کلود یا هوش مصنوعی‌های سنگین نداره.

کد برنامه به صورت مداوم فریم‌هایی که از دوربین دریافت می‌کنه رو با فریم قبلی مقایسه می‌کنه و بر اساس میزان تفاوتشون، یک "امتیاز حرکت" محاسبه می‌کنه.

TXT
float motion = motionCalc(fb->buf, fb->len);
runEngine(motion, lux, sound);
if (motion >= THRESH_ALERT)
{
evLog("ALERT: High motion");
qSpk(BEEP_ALERT);
}

هر بار که دوربین تصویر جدیدی می‌گیره، اگر نسبت به لحظه قبل تغییرات محسوسی توی محیط دیده بشه، این امتیاز بالاتر می‌ره و سیستم متوجه حضور یک سوژه می‌شه.

برخلاف سیستم‌های سنتی بینایی ماشین (Computer Vision) که باید تک‌تک پیکسل‌ها رو تحلیل کنن، ما از تکنیک مقایسه مستقیم فریم‌های JPEG استفاده کردیم تا بدون فشار آوردن به پردازنده، تشخیص حرکتی بسیار دقیق و پایداری داشته باشیم.

TXT
float motionCalc(const uint8_t* cur, size_t clen)
{
long diff = 0;
for (int i = 0; i < N; i++)
{
int d = (int)cur[idx] - (int)g_prev[idx];
diff += abs(d);
}
float p = (float)diff / 80.0f;
return p > 100.0f ? 100.0f : p;
}

اکثر دوربین‌های دست‌ساز برای تشخیص حرکت به فضای ابری وابسته‌ان که هم مصرف اینترنت داره و هم باتری رو زود تموم می‌کنه. اما این دوربین با این روش ابتکاری می‌تونه امکانات زیر رو داشته باشه:

  1. تشخیص بسیار سریع و در لحظه حرکت‌ها
  2. اجرای تمام پردازش‌ها در داخل خود ماژول
  3. عدم ایجاد افت فریم در پخش زنده ویدیو
  4. کاهش چشمگیر بار روی دوش پردازنده
  5. افزایش ماندگاری شارژ باتری

حالا اگر میزان حرکت از یک حد مجازی بالاتر بره، دوربین به صورت کاملا خودکار می‌تونه واکنش نشون بده:

  1. ارسال هشدار تشخیص حرکت روی دشبورد
  2. پخش اتوماتیک پیام‌های صوتی بازدارنده
  3. روشن کردن آژیر خطر با صدای بلند
  4. شروع فوری ضبط اتفاقات روی کارت حافظه
  5. به‌روزرسانی نمودارها و آیکون‌های دشبورد به صورت آنی

این قابلیت، دوربین ساده ما رو تبدیل به یک نگهبان هوشمند می‌کنه که می‌تونه در مقابل اتفاقات محیطی از خودش عکس‌العمل نشون بده.

مرحله ۱۱

سیستم هوشمند دید در شب

برای اینکه خیالمون از بابت عملکرد دوربین تو تاریکی مطلق هم راحت باشه، یک سیستم دید در شب کاملا اتوماتیک با استفاده از سنسور نور LTR-308 و یک ال‌ای‌دی مادون قرمز طراحی کردیم. سیستم دائما در حال بررسی میزان روشنایی محیطه و هرچقدر که اتاق تاریک‌تر بشه، شدت نور مادون قرمز رو همون‌قدر افزایش می‌ده.

TXT
if (lux < NIGHT_LUX)
{
g_night = true;
}
if (lux > NIGHT_LUX * 1.5f)
{
g_night = false;
}

سنسور LTR-308 شدت نور رو بر اساس واحد لوکس (Lux) اندازه‌گیری می‌کنه. اگر روشنایی از یک حدی کمتر بشه، دوربین می‌فهمه که باید بره به حالت شب. به محض فعال شدن این حالت، ال‌ای‌دی مادون قرمز روشن می‌شه تا محیط رو برای لنز دوربین روشن کنه.

TXT
if (g_autoIR)
{
int duty = g_night ? luxToDuty(lux) : 0;
if (duty != g_irDuty)
{
irSetDuty(duty);
}
}

به جای اینکه مثل دوربین‌های قدیمی ال‌ای‌دی رو یک‌دفعه خاموش یا روشن کنیم، سیستم به صورت کاملا داینامیک شدت نور اون رو تنظیم می‌کنه.

TXT
int luxToDuty(float lux)
{
if (lux >= NIGHT_LUX * 1.5f)
return 0;
if (lux <= 5.0f)
return IR_MAX_DUTY;
float ratio =
(NIGHT_LUX * 1.5f - lux) /
(NIGHT_LUX * 1.5f - 5.0f);
return (int)(ratio * IR_MAX_DUTY);
}

پس هرچی هوا تاریک‌تر بشه:

  1. شدت نور مادون قرمز به صورت خودکار بیشتر می‌شه
  2. وضوح تصویر دوربین تو تاریکی بالا می‌ره
  3. همزمان باتری بی‌دلیل خالی نمی‌شه و مصرف بهینه می‌مونه

با استفاده از قابلیت PWM (مدولاسیون پهنای پالس) توی تراشه ESP32-S3، ما می‌تونیم نور رو نرم و روان تغییر بدیم و جلوی پرش‌های ناگهانی تصویر موقع تغییر نور روز به شب رو بگیریم.

TXT
void irSetDuty(int duty)
{
ledcWrite(PIN_IR, duty);
g_irDuty = duty;
g_irOn = (duty > 0);
}

این یعنی دوربین تو همیشه می‌دونه دقیقا چقدر نور لازم داره و با کمترین مصرف انرژی، همیشه بهترین تصویر رو تو تاریکی بهت تحویل می‌ده.

مرحله ۱۲

نظارت بر صدای محیط

علاوه بر تصویر، ما می‌تونیم به لطف میکروفون PDM نصب شده روی برد، صدای محیط رو هم به صورت زنده مانیتور کنیم. این قابلیت به سیستم کمک می‌کنه تا تغییرات ناگهانی نویز محیط رو تشخیص بده و گراف اون رو تو دشبورد بهت نشون بده. میکروفون بی‌وقفه در حال نمونه‌برداری از صدای اطرافه و میکروکنترلر با پردازش این داده‌ها، شدت صدای پایداری رو محاسبه می‌کنه.

JavaScript
float readMicLevel()
{
const int N = 512;
int16_t buf[N];
size_t got =
i2s.readBytes((char*)buf, N * 2);
if (got < 2)
return g_sndSmooth;

میکروکنترلر ESP32-S3 داده‌های میکروفون رو از طریق رابط سخت‌افزاری I2S می‌خونه و داخل یک بافر ذخیره می‌کنه تا سطح کلی صدای محیط رو به دست بیاره.

به جای اینکه فقط دنبال بلندترین صدای ناگهانی (Peak) بگردیم، این دوربین با استفاده از محاسبات ریاضی RMS (جذر میانگین مربعات) درک بسیار واقعی‌تری از ولوم صدای محیط پیدا می‌کنه.

TXT
double sum = 0.0;
for (int i = 0; i < n; i++)
{
sum +=
(double)buf[i] *
(double)buf[i];
}
float rms =
sqrt(sum / (double)n);

روش RMS توی سیستم‌های صوتی حرفه‌ای هم استفاده می‌شه، چون به جای یک صدای لحظه‌ای، انرژی واقعی موج صوتی رو می‌سنجه و باعث می‌شه دشبورد اطلاعات پایدارتر و درست‌تری رو نمایش بده.

البته چون داده‌های خام میکروفون ممکنه نوسان‌های ریز زیادی داشته باشن، از یک فیلتر نرم‌کننده اکسپوننشیال استفاده کردیم تا گراف‌های روی دشبورد پرش‌های بی‌دلیل نداشته باشن.

TXT
g_sndSmooth =
g_sndSmooth * 0.75f +
pct * 0.25f;
return g_sndSmooth;

این فیلتر جلوی پرش‌های ناگهانی رو می‌گیره اما همچنان نسبت به تغییرات واقعی صدای اتاق حساس می‌مونه. بعد از پردازش، این دیتا مستقیم برای مرورگرت فرستاده می‌شه.

TXT
float sound =
readMicLevel();
runEngine(
motion,
lux,
sound
);

حالا اگر کسی وارد محیط بشه یا صدایی بیاد، نوار شدت صدا توی دشبورد بلافاصله بالا می‌ره و تو از وضعیت محیط باخبر می‌شی. ترکیب تصویر، تشخیص حرکت و حالا صدا، این دوربین رو به یک سیستم نظارتی فوق‌العاده هوشیار تبدیل کرده.

مرحله ۱۳

موتور تولید صدای رباتیک و آژیر

یکی از خفن‌ترین ویژگی‌های این دوربین، سیستم اعلان صوتی داخلی اونه. تو این پروژه خبری از فایل‌های MP3 آماده یا وصل شدن به سرویس‌های ابری تبدیل متن به صدا (TTS) نیست! خود ESP32-S3 با استفاده از فرمول‌های ریاضی و در همون لحظه، صداهایی شبیه به یک ربات تولید می‌کنه.

این یعنی دوربین می‌تونه کاملا آفلاین صحبت کنه و هشدار بده، بدون اینکه حجم زیادی از حافظه‌اش اشغال بشه. برای اینکه این تولید صدا باعث افت فریم تصویر نشه، کل پردازش صوتی تو یک تسک مجزا توی FreeRTOS انجام می‌شه.

TXT
xTaskCreatePinnedToCore(
spkTask,
"speaker",
6144,
nullptr,
2,
nullptr,
1
);

هر موقع که تو از دشبورد دستور پخش یک کلمه یا آژیر رو می‌دی، این درخواست وارد یک صف انتظار (Queue) می‌شه تا به ترتیب پردازش بشه.

TXT
qSpk(
SPK_ANNOUNCE,
"Motion detected"
);

این ترفند باعث می‌شه حتی موقعی که دوربین در حال حرف زدنه، استریم ویدیو متوقف نشه. موتور صوتی ما حروف و کلمات رو با تولید شکل‌موج‌های سینوسی، تبدیل به یک صدای رباتیک جذاب می‌کنه.

TXT
float f0 =
120.0f +
(float)(cs % 120);
float f1 = f0 * 3.0f;
float f2 = f0 * 5.0f;

هر کلمه فرکانس خاص خودش رو می‌گیره تا تنوع آوایی ایجاد بشه. تفاوت این روش با سیستم‌های معمول اینه که:

  1. هیچ نیازی به ذخیره فایل‌های صوتی حجیم نداری
  2. کاملا آفلاین و بدون نیاز به اینترنت کار می‌کنه
  3. هیچ API یا سرویس خارجی درگیر نمی‌شه
  4. صفر تا صد پردازش روی همون پردازنده اصلی انجام می‌شه

فریم‌ور دوربین سمپل‌های صوتی رو با ریاضیات می‌سازه و یک‌راست می‌فرسته روی بلندگو.

TXT
float s =
(2.0f*p0-1.0f)*0.55f +
(2.0f*p1-1.0f)*0.28f +
(2.0f*p2-1.0f)*0.17f;
pcm[pos++] =
(int16_t)(
s * env * 22000.0f
);

این صدای خاص، خیلی متفاوت‌تر و جدی‌تر از بوق‌های ساده الکترونیکیه. علاوه بر حرف زدن، دوربین می‌تونه افکت‌های هشدار مختلفی هم پخش کنه:

TXT
case BEEP_BOOT:
doBeepBoot();
break;
case BEEP_ALERT:
doBeepAlert();
break;
case BEEP_MOTION:
doBeepMotion();
break;

این افکت‌ها کمک می‌کنن تا بدون دیدن تصویر، از وضعیت دستگاه مطلع بشی. برای مواقع خطر هم یک قابلیت آژیر پرقدرت در نظر گرفتیم.

TXT
float f =
800.0f +
400.0f *
(float)i /
(float)N;

آژیر با یک چرخش فرکانسی از 800 هرتز تا 1200 هرتز تولید می‌شه و صدای به شدت بلندی ایجاد می‌کنه که توجه همه رو توی یک اتاق جلب می‌کنه. تولید همزمان صدا و تصویر روی یک چیپ کوچک، این سیستم رو تبدیل به یک دستگاه امنیتی یکپارچه و فوق‌العاده مستقل کرده.

مرحله ۱۴

نظارت بر درصد شارژ باتری

از اونجایی که ما داریم یک دوربین پرتابل می‌سازیم، مانیتور کردن وضعیت باتری خیلی حیاتیه. برد ما مدام ولتاژ باتری رو می‌خونه، اون رو به درصد تبدیل می‌کنه و به صورت یک عدد قابل فهم توی دشبورد بهت نشون می‌ده.

اینطوری همیشه می‌دونی چقدر از عمر باتری مونده و قبل از اینکه دوربینت خاموش بشه می‌تونی بزنیش به شارژ. برای خوندن ولتاژ هم از پین آنالوگ (ADC) متصل به GPIO44 و یک مدار تقسیم ولتاژ استفاده کردیم.

TXT
#define BAT_PIN 44
#define BAT_DIV 0.3197f
float v =
(float)(sum / 64) /
4095.0f *
3.3f /
BAT_DIV;

مدار مقسم ولتاژ کمک می‌کنه تا ولتاژ باتری تا حدی کم بشه که برای پین آنالوگ ESP32-S3 امن و قابل خوندن باشه. برای اینکه درصد باتری پرش نداشته باشه، سیستم در هر ثانیه چند بار ولتاژ رو می‌خونه و میانگین می‌گیره.

TXT
long sum = 0;
for (int i = 0; i < 64; i++)
{
sum += analogRead(BAT_PIN);
delayMicroseconds(200);
}

این کار نویزهای مدار رو حذف می‌کنه و یک عدد پایدار تحویلت می‌ده. مهم‌تر از همه، ما از یک فرمول خطی ساده برای محاسبه درصد استفاده نکردیم؛ بلکه از منحنی دشارژ باتری‌های لیتیوم‌پلیمر استفاده کردیم تا درصد نشون داده شده دقیقا مطابق با رفتار واقعی باتری باشه.

TXT
if (v >= 4.15f)
p = 90 +
(v - 4.15f) /
0.05f * 10;
else if (v >= 3.90f)
p = 60 +
(v - 3.90f) /
0.25f * 30;
else if (v >= 3.70f)
p = 30 +
(v - 3.70f) /
0.20f * 30;

با این فرمول پیشرفته، چه باتری 100 درصد باشه و چه 10 درصد، عددی که می‌بینی کاملا دقیقه. این اطلاعات مرتبا برای مرورگرت ارسال می‌شه.

TXT
g_vbat = v;
g_batPct = p;

تو می‌تونی با یک نگاه به دشبورد، این موارد رو چک کنی:

  1. درصد دقیق شارژ باتری
  2. ولتاژ لحظه‌ای مدار
  3. مدت زمان تقریبی روشن موندن دستگاه

برای دستگاهی که به هیچ سیم برقی وصل نیست، داشتن این اطلاعات روی پنل مدیریت خیلی واجبه و از خاموشی‌های سورپرایزکننده جلوگیری می‌کنه. با این سیستم مدیریت انرژی، دوربین ما واقعا یک دیوایس هوشمند و پرتابل به حساب میاد.

مرحله ۱۵

موتور ذخیره‌سازی روی کارت حافظه

پخش زنده برای مانیتورینگ عالیه، اما یک دوربین مداربسته باید بتونه مدارک رو ضبط هم بکنه! این دستگاه می‌تونه فریم‌ها رو به صورت فایل ویدیویی AVI مستقیما روی مموری‌کارت (SD Card) ذخیره کنه و تبدیل به یک سیستم امنیتی مستقل بشه.

برخلاف خیلی از پروژه‌های آموزشی که فقط پخش زنده دارن، دوربین ما همزمان هم ویدیو رو استریم می‌کنه و هم ضبط! وقتی دکمه ریکورد رو می‌زنی، سیستم یک فایل AVI جدید روی رم می‌سازه و هدرهای ویدیو رو داخلش می‌نویسه.

TXT
startAVI();
g_recording = true;
g_aviFr = 0;

ما فرمت AVI رو انتخاب کردیم چون همه‌جا پشتیبانی می‌شه و می‌تونی خیلی راحت مموری رو دربیاری و ویدیوها رو بدون نیاز به هیچ پلیر عجیبی روی لپ‌تاپت ببینی. بعد از ساخته شدن فایل، هر عکسی که دوربین می‌گیره سریعا داخل این فایل نوشته می‌شه.

TXT
g_avi.write(
fb->buf,
fb->len
);
g_aviFr++;

هر تصویر JPEG مثل یک فریم پشت سر هم قرار می‌گیره و یک ویدیوی سبک MJPEG تولید می‌شه. به لطف ساختار چند-تسکی که قبلا بهش اشاره کردیم، این پروسه اصلا جلوی استریم کردن رو نمی‌گیره.

TXT
camera_fb_t* fb =
esp_camera_fb_get();
recFrame(
fb->buf,
fb->len
);
esp_camera_fb_return(fb);

این یعنی تو می‌تونی در یک لحظه:

  1. تصویر رو به صورت زنده تماشا کنی
  2. ویدیوها رو روی مموری ذخیره کنی
  3. وضعیت سنسورهای صدا و حرکت رو چک کنی

برای اینکه فایل‌های ویدیویی خیلی حجیم نشن و احتمال خراب شدنشون پایین بیاد، سیستم به محض اینکه حجم فایل به مقدار مشخصی برسه، اون رو می‌بنده و یک فایل جدید می‌سازه.

TXT
if (
g_avi.size() >
(uint32_t)
SD_ROLL_MB *
1024UL *
1024UL
)
{
stopAVI();
startAVI();
}

به صورت پیش‌فرض هر فایل روی 400 مگابایت بسته می‌شه. این کار مزایای زیادی داره:

  1. مدیریت و پیدا کردن فایل‌ها راحت‌تر می‌شه
  2. پخش ویدیوها روی کامپیوتر روان‌تر انجام می‌شه
  3. کپی کردن فایل‌ها سرعت بیشتری داره

وقتی ضبط ویدیو رو متوقف می‌کنی، سیستم فایل رو نهایی (Finalize) می‌کنه و اطلاعات ایندکس ویدیو رو ته فایل می‌نویسه.

TXT
aviClose(
g_avi,
g_aviFr,
STREAM_FPS
);

این ایندکس باعث می‌شه ویدیو قابلیت جلو و عقب زدن (Seek) توی پلیرها رو داشته باشه. با این معماری قوی، دوربین تو هم به صورت آفلاین یک سیستم ضبط تصاویر قدرتمنده و هم به صورت آنلاین یک مانیتور زنده.

مرحله ۱۶

وب‌سرور داخلی و ارتباط با دشبورد

برای اینکه کنترل دوربین راحت باشه، ما یک وب‌سرور سبک رو مستقیم داخل همون تراشه ESP32-S3 پیاده‌سازی کردیم. این سرور مثل یک پل ارتباطی بین سخت‌افزار دوربین و دشبورد مرورگرت عمل می‌کنه.

به جای اینکه مجبور بشی یک اپلیکیشن سنگین روی گوشیت نصب کنی، همه‌چیز از طریق درخواست‌های ساده وب (HTTP Requests) انجام می‌شه. فریم‌ور دوربین یک سرور می‌سازه که همیشه منتظر شنیدن درخواست از طرف توئه.

TXT
WebServer server(80);
server.begin();

این سرور وظیفه داره استریم ویدیو رو تحویل بده، دیتای سنسورها رو بفرسته و دستوراتی که تو روی دشبورد کلیک می‌کنی رو اجرا کنه.

TXT
server.on(
"/stream",
HTTP_GET,
handleStream
);

هر موقع که مرورگرت درخواست آدرس /stream رو می‌ده، برد شروع می‌کنه به ارسال بی‌وقفه فریم‌های تصویر و این همون چیزیه که ویدیو رو برات پخش می‌کنه. علاوه بر ویدیو، دشبورد نیاز داره تا وضعیت سنسورها رو هم بدونه.

TXT
server.on(
"/data",
HTTP_GET,
handleData
);

پاسخی که سرور می‌ده شامل این اطلاعاته:

  1. شدت حرکت تشخیص داده شده
  2. درصد دقیق شارژ باتری
  3. میزان نویز و صدای محیط
  4. سطح نور و روشنایی محیط
  5. فضای اشغال‌شده کارت حافظه
  6. وضعیت در حال ضبط بودن ویدیو
  7. وضعیت روشن یا خاموش بودن دید در شب

مرورگرت به صورت مدام این اطلاعات رو از دوربین می‌گیره و گراف‌ها رو آپدیت می‌کنه. از اون طرف، اگر تو بخوای فرمانی به دوربین بدی، از طریق یک مسیر کنترلی ارسال می‌شه.

TXT
server.on(
"/control",
HTTP_GET,
handleControl
);

این بخش، وظیفه پردازش دستورات زیر رو داره:

  1. شروع فوری ضبط ویدیو
  2. توقف ضبط
  3. روشن کردن آژیر خطر
  4. پخش متن به صورت صوتی
  5. تغییر دستی حالت مادون قرمز

وقتی فرمانی می‌رسه، دوربین سریعا اون بخش سخت‌افزاری رو فعال می‌کنه.

TXT
if (cmd == "siren")
{
qSpk(BEEP_SIREN);
}
if (cmd == "record")
{
startAVI();
}

این چرخه، یک ارتباط پایدار و بی‌نقص بین محیط گرافیکی دشبورد و قطعات الکترونیکی ایجاد می‌کنه. وب‌سرور ما توی یک حلقه مداوم در حال گوش دادن به این درخواست‌هاست.

Arduino
void loop()
{
server.handleClient();
delay(1);
}

استفاده از وب‌سرور داخلی این مزیت‌های بزرگ رو به پروژه اضافه کرده:

  1. هیچ اپلیکیشنی روی گوشی نیاز نداری
  2. روی آی‌اواس، اندروید، ویندوز و مک کار می‌کنه
  3. فقط با وارد کردن یک آی‌پی در مرورگر باز می‌شه
  4. ارتباط بسیار سریع بدون تاخیر
  5. قابلیت تغییر ظاهر محیط گرافیکی به راحتی
  6. سازگار با صفحه نمایش لپ‌تاپ، تبلت و موبایل

با همین ساختار ساده اما قدرتمند، برد ما می‌تونه با هر دیوایسی تو شبکه ارتباط برقرار کنه.

مرحله ۱۷

طراحی پیشرفته دشبورد کاربری

ما می‌خواستیم تجربه کار با این دوربین مثل کار کردن با محصولات گرون‌قیمت بازار هوشمند و لذت‌بخش باشه. برای همین یک دشبورد تحت وب کاملا اختصاصی و چشم‌نواز طراحی کردیم که به عنوان مرکز فرماندهی دوربینت عمل می‌کنه.

این دشبورد در واقع یک فایل ساده HTML هست و از هیچ فریم‌ورک سنگینی داخلش استفاده نشده. این یعنی باز کردنش نیازی به دانلودهای سنگین نداره و در صدم‌ثانیه روی مرورگرت لود می‌شه. به جای اینکه خودمون رو درگیر ساختن اپلیکیشن‌های مجزا برای اندروید و آیفون کنیم، رفتیم سراغ مرورگر چون:

  1. روی همه‌چیز (موبایل، تبلت، پی‌سی) بی‌نقص اجرا می‌شه
  2. دردسرهای نصب اپلیکیشن رو نداره
  3. محدود به سیستم‌عامل خاصی نیست
  4. تغییر دادن کدهاش و آپدیت کردنش به شدت راحته
  5. همه با محیط مرورگرها آشنایی دارن

این دشبورد از طریق شبکه وای‌فای و ارسال ریکوئست‌های HTTP، مستقیما با ماژول ارتباط برقرار می‌کنه.

TXT

 Dashboard 
 (Browser) 


 HTTP Requests


 ESP32-S3 
 Sentra 


 Live Video Stream
 Motion Detection
 SD Recording
 Night Vision
 Audio Engine
 Sensor Monitoring

دشبورد مدام دیتای جدید رو از دستگاه می‌خونه و همزمان فرمان‌هایی که تو کلیک می‌کنی رو هم ارسال می‌کنه، مثل:

  1. شروع یا پایان ضبط ویدیو روی مموری
  2. به صدا درآوردن آژیر خطر محیط
  3. ارسال کلمات برای پخش صوتی در اسپیکر دوربین
  4. تغییر تنظیمات دوربین تو تاریکی
  5. نظارت بر میزان باتری و حافظه

یکی از بهترین تکنیک‌هایی که تو معماری این دشبورد استفاده کردیم، سیستم State-Driven هست. یعنی چی؟

JavaScript
let S = {
motion:0,
activity:'idle',
lux:500,
sound:0,
recording:false,
batPct:0
};

یعنی تمام اطلاعاتی که روی صفحه می‌بینی به یک متغیر مرکزی وصل هستن. هر وقت دیتای جدیدی از سنسورها بیاد:

TXT
S = {
...S,
...await r.json()
};
renderUI();

رابط کاربری به صورت خودکار خودش رو با دیتای جدید آپدیت می‌کنه. این باعث می‌شه کدهای فرانت‌اند خیلی تمیز بمونن و هیچ‌موقع لگ یا نمایش اطلاعات اشتباه رو تجربه نکنی.

مرحله ۱۸

رابط کاربری شیشه‌ای (Glassmorphism)

از اونجا که می‌خواستیم این پروژه حسابی حرفه‌ای باشه، زمان زیادی رو روی استایل و ظاهر گرافیکی دشبورد گذاشتیم تا حسابی شیک و مدرن به نظر بیاد.

کل این ظاهر فقط با کدنویسی تمیز HTML و CSS و کمی جاوااسکریپت خلق شده تا سنگینی فریم‌ورک‌های آماده رو نداشته باشه و تو سریع‌ترین زمان ممکن اجرا بشه. ظاهر این پنل از اپلیکیشن‌های حرفه‌ای خانه هوشمند الهام گرفته شده و ویژگی‌های زیر رو داره:

  1. فونت‌ها و سایز نوشته‌های بسیار خوانا
  2. استفاده از سایه‌های نرم برای عمق دادن به المان‌ها
  3. گوشه‌های گرد برای مدرن‌تر شدن ظاهر
  4. افکت جذاب شیشه مات (Glassmorphism)
  5. انیمیشن‌های روان موقع کلیک کردن
  6. طراحی ریسپانسیو که روی سایز موبایل هم عالی دیده می‌شه

برای اینکه رنگ‌ها و تم گرافیکی همه‌جا یکدست باشه، از متغیرهای مرکزی CSS استفاده کردیم.

TXT
:root {
--bg: #F2F4F7;
--blue: #007AFF;
--green: #34C759;
--amber: #FF9F0A;
--red: #FF3B30;
--r16:16px;
--r24:24px;
--shadow-sm:
0 2px 8px rgba(0,0,0,0.05);
}

با این روش اگر بخوای رنگ کل محیط دشبورد رو عوض کنی، فقط کافیه این متغیرها رو تغییر بدی. به جای عکس پس‌زمینه هم از گرادیانت‌های ترکیبی استفاده کردیم که حجم فایل بالا نره.

TXT
body::before {
background-image:
radial-gradient(
ellipse 80% 60%
at 20% -10%,
rgba(0,122,255,0.04),
transparent 60%
);
}

یکی از جذاب‌ترین المان‌های این پنل، کارت‌های شیشه‌ای نیمه‌شفافشه.

TXT
.card {
background:
rgba(255,255,255,0.78);
backdrop-filter:
blur(24px)
saturate(1.8);
border:
1px solid
rgba(255,255,255,0.9);
}

با ترکیب این استایل‌ها، به افکتی شبیه به شیشه مات و یخ‌زده رسیدیم که چشم رو خسته نمی‌کنه. این افکت از المان‌های زیر ساخته شده:

  1. رنگ پس‌زمینه نیمه‌شفاف
  2. تار کردن محیط زیر المان با قابلیت Backdrop-blur
  3. تقویت اشباع رنگ در پس‌زمینه
  4. سایه‌های محو در زیر باکس‌ها
  5. خطوط حاشیه بسیار ظریف و براق

و در نهایت برای اینکه کلیک کردن روی دکمه‌ها حس خوبی داشته باشه، انیمیشن‌های نرمی رو پیاده کردیم.

TXT
:root {
--ease:
cubic-bezier(
0.22,
1,
0.36,
1
);
}

این افکت‌های انیمیشنی روی این قسمت‌ها اعمال شدن:

  1. دکمه‌های کنترل دوربین
  2. سوییچ‌های روشن و خاموش کردن امکانات
  3. نشانگرهای وضعیت سنسورها
  4. پنجره‌های اطلاعاتی
  5. نمودارهای در حال لود شدن

نتیجه نهایی، یک رابط کاربری بسیار نرم و پرمیومه که حس یک گجت دست‌ساز رو بهت نمی‌ده.

مرحله ۱۹

رابط تماشای زنده و نمایشگر HUD

بخش اصلی و قلب تپنده دشبورد، نمایشگر ویدیوی زنده اونه. برای اینکه شبیه سیستم‌های حرفه‌ای نظارتی بشه، به جای اینکه ویدیو رو خشک و خالی نشون بدیم، یک لایه HUD (نمایشگر اطلاعات روی شیشه) براش طراحی کردیم که اطلاعات حیاتی رو مستقیما روی خود تصویر ویدیو نشون می‌ده. این یعنی بدون اینکه لازم باشه چشم از سوژه برداری، می‌تونی بفهمی وضعیت دوربین چطوره.

TXT
img.src =
'http://' +
IP +
'/stream';
TXT
.hud {
position:absolute;
inset:0;
pointer-events:none;
display:none;
}

این لایه اطلاعاتی، کاملا شفاف و بی‌رنگ روی ویدیو می‌شینه تا مزاحم دیدنت نشه. برای جذاب‌تر شدنش چندتا زاویه‌بندی خاص هم دور کادر تصویر انداختیم.

TXT
.hud-corner.tl {
top:12px;
left:12px;
border-top:
1.5px solid
rgba(255,255,255,0.22);
border-left:
1.5px solid
rgba(255,255,255,0.22);
}

مهم‌ترین المانی که روی تصویر ویدیو قرار داره، نشانگر وضعیت حرکت محیطه.

TXT
.hud-detect.motion {
background:
rgba(255,159,10,0.18);
border-color:
rgba(255,159,10,0.4);
color:#FFD060;
}

این نشانگر بسته به اتفاقات محیط خودش رو تغییر می‌ده:

  1. حالت عادی و بدون تحرک
  2. لحظه تشخیص حرکت مشکوک
  3. حالت تشخیص حضور افراد
  4. وضعیت قرمز و هشدار

با دیتایی که هر لحظه از سنسورها میاد، این متن تغییر می‌کنه و تو سریع متوجه اتفاقات می‌شی.

JavaScript
const act =
S.activity ||
'idle';
abt.className =
'hud-detect' +
(act !== 'idle'
? ' ' + act
: '');

علاوه بر این، وقتی دکمه ضبط رو می‌زنی، نشانگر قرمز رنگ ریکورد همون بالا چشمک می‌زنه.

TXT
if (S.recording)
{
showREC();
}

اطلاعاتی که همیشه می‌تونی روی لایه HUD ببینی این موارد هستن:

  1. میزان جنب و جوش در تصویر
  2. روشن یا خاموش بودن ریکوردر
  3. وضعیت فعلی سنسورهای تشخیص
  4. فعال بودن لامپ‌های مادون قرمز
  5. سلامت اتصال و استاتوس دوربین

در دشبوردهای معمولی تو مجبوری مدام اسکرول کنی تا این اطلاعات رو پیدا کنی. اما اینجا، مثل فیلم‌های علمی‌تخیلی همه‌چیز در همون لحظه و روی خود تصویر برات رندر می‌شه و تجربه نظارت رو به شدت ساده و لذت‌بخش می‌کنه. همین جزئیات کوچیکه که این کاردستی الکترونیکی رو تبدیل به یک محصول لوکس امنیتی کرده.

مرحله ۲۰

ویجت‌های نظارت لحظه‌ای

علاوه بر تصویر دوربین، تو به عنوان مدیر سیستم باید بدونی داخل دستگاهت چه خبره. برای همین مجموعه‌ای از ویجت‌های گرافیکی ساختیم که سلامت دوربین و دیتای سنسورها رو در لحظه مانیتور می‌کنن. این ویجت‌ها نیازی به رفرش کردن صفحه ندارن و همیشه آپدیت هستن. یکی از مهم‌ترین ویجت‌ها، گراف وضعیت حرکت تو محیطه.

JavaScript
const m =
Math.round(
S.motion
);
const mc =
m > 70 ?
'var(--red)' :
m > 40 ?
'var(--amber)' :
'var(--blue)';

دشبورد با تحلیل عددی که میکروکنترلر براش می‌فرسته، رنگ‌ها رو برای تو تغییر می‌ده تا با یک نگاه عمق ماجرا رو درک کنی:

  1. رنگ آبی ← محیط آرام و بی‌خطر
  2. رنگ نارنجی ← تحرک خفیف یا مشکوک
  3. رنگ قرمز ← حرکت زیاد و جلب توجه‌کننده

برای درک بهتر این موضوع، یک حلقه گرافیکی هم دور این ویجت طراحی شده.

JavaScript
const C = 282;
const off =
C -
(m / 100) * C;
$('rp')
.style
.strokeDashoffset =
off;

با بالا رفتن جنب و جوش در تصویر، این حلقه پرتر می‌شه. ویجت بعدی مربوط به سنسور نوره.

JavaScript
const ld =
lux < 10 ?
'Night  very dark' :
lux < 50 ?
'Night  dim' :
lux < 150 ?
'Dusk / indoor' :
'Full daylight';

به جای اینکه فقط یک عدد خشک مثل "20 لوکس" بهت نشون بده، سیستم اون رو تبدیل به یک جمله قابل فهم می‌کنه (مثلا می‌نویسه "محیط نیمه‌تاریک"). برای صدای محیط هم یک نوار اکولایزر طراحی شده.

TXT
sound =
Math.round(
S.sound
);

این نوار با کوچکترین صدایی که میکروفون روی دوربین بشنوه بالا و پایین می‌ره. و از اونجا که دستگاه ما پرتابله، ویجت باتری همیشه جلوی چشمته.

TXT
$('batPct')
.textContent =
S.batPct +
'%';

این ویجت جذاب اطلاعات زیر رو نمایش می‌ده:

  1. درصد دقیق شارژ به صورت گرافیکی
  2. ولتاژ فعلی در مدار باتری
  3. اعلام وضعیت در صورت وصل شدن به شارژر
  4. میزان انرژی تقریبی باقی‌مانده

یک ویجت هم برای فضای مموری‌کارت در نظر گرفتیم.

TXT
$('sd')
.textContent =
S.sdFreeGB +
' GB Free';

بدون اینکه نیاز باشه رم رو دربیاری، تو دشبورد می‌بینی که:

  1. چقدر فضا برای ضبط ویدیو خالی مونده
  2. حجم کل مموری‌کارتت چقدره
  3. آیا سیستم آماده ضبط فایل جدید هست یا نه

همه این‌ها دشبورد رو به یک دستیار هوشمند و کامل تبدیل کرده.

مرحله ۲۱

پنل کنترل و فرمان‌های صوتی

این دشبورد بهت اجازه می‌ده که رسما کنترل دوربین رو تو دستت بگیری. از روشن کردن دستی حالت شب گرفته تا فعال کردن آژیر خطر؛ همه‌چیز با یک کلیک انجام می‌شه. هر دکمه‌ای که روی صفحه لمس می‌کنی، در کسری از ثانیه فرمانش رو برای تراشه ESP32-S3 ارسال می‌کنه.

JavaScript
async function cmd(c)
{
const r =
await fetch(
'http://' +
IP +
'/control?cmd=' +
encodeURIComponent(c)
);
}

این ارتباط دوطرفه، حس کار کردن با یک دوربین تعاملی واقعی رو بهت می‌ده. یکی از مهم‌ترین کلیدها، کنترل ضبط ویدیوئه.

TXT
cmd('record_on');
cmd('record_off');

اگر اتفاق مشکوکی دیدی، از همونجا با موبایلت دکمه ضبط رو بزن تا مدارک مستقیما روی مموری‌کارت ذخیره بشن. برای ترسوندن مزاحم‌ها هم دکمه آژیر رو داریم.

TXT
cmd('siren');

وقتی این دکمه رو بزنی، اسپیکر روی دوربین یک صدای قدرتمند و گوش‌خراش پخش می‌کنه. کاربردهاش ایناست:

  1. دور کردن افراد ناشناس از محدوده دوربین
  2. جلب توجه افراد حاضر در محل
  3. واکنش سریع به دیدن یک صحنه مشکوک
  4. بررسی و تست سلامت اسپیکر داخلی

برای کنترل سیستم دید در شب هم گزینه‌های مختلفی داری.

TXT
cmd('ir_on');
cmd('ir_off');
cmd('ir_auto');

می‌تونی:

  1. لامپ مادون قرمز رو برای همیشه روشن بذاری
  2. کلا خاموشش کنی
  3. یا تنظیمش کنی روی حالت اتوماتیک تا بر اساس نور محیط کار کنه

اما باحال‌ترین بخش پنل، قسمت ارسال پیام صوتیه. می‌تونی هر کلمه‌ای که دوست داری رو تو باکس تایپ کنی و دکمه رو بزنی تا دوربین اونو با صدای رباتیک خودش بخونه!

TXT
sendAnn();

این سیستم همون‌طور که گفتیم اصلا به اینترنت نیازی نداره و پردازنده دوربین خودش متن رو به صدا تبدیل می‌کنه. برای اینکه سیستم هنگ نکنه، دشبورد طول پیامت رو چک می‌کنه.

JavaScript
const rem =
95 -
textarea.value.length;
charCount.textContent =
rem + ' left';

چند تا پیام آماده هم به عنوان میانبر (Shortcut) گذاشتیم تا سرعت عملت بالا بره.

TXT
qa("Motion Detected");
qa("Recording Enabled");
qa("Stay Away");

با یک کلیک ساده، اون پیام هشدار روی اسپیکر پخش می‌شه.

مرحله ۲۲

موتور شبیه‌ساز و حالت دمو

یک ویژگی خیلی منحصربه‌فرد که تو این پروژه قرار دادیم، اضافه کردن "حالت دمو" (Demo Mode) به دشبورده. با این کار می‌تونی حتی قبل از اینکه قطعات رو بخری یا کدی آپلود کنی، محیط دشبورد رو روی گوشیت باز کنی و ببینی چطوری کار می‌کنه! این حالت فقط چند تا عکس ثابت نیست؛ بلکه یک شبیه‌ساز کامله که رفتار دوربین رو تو محیط واقعی با جزئیات کامل تقلید می‌کنه.

اصلا شبیه‌ساز به چه دردی می‌خوره؟

معمولا برای تست یک محیط کاربری باید:

  1. حتما دوربینت روشن و مونتاژ شده باشه
  2. ماژول به مودم وای‌فای متصل باشه
  3. سنسورها در حال کار باشن
  4. و تصویر واقعی وجود داشته باشه

اما تو حالت دمو هیچ‌کدوم از اینا نیاز نیست. الگوریتم‌های شبیه‌ساز سناریوهای جالبی رو به صورت خودکار اجرا می‌کنن تا رفتار یک دوربین واقعی رو شبیه‌سازی کنن.

JavaScript
const SC = [
{
act:'idle',
dur:7000
},
{
act:'motion',
dur:5000
},
{
act:'person',
dur:4500
}
];

این سناریوها مدام تکرار می‌شن:

  1. حالت مانیتورینگ ساکت و معمولی
  2. لحظاتی که مثلا چیزی تو محیط تکون می‌خوره
  3. حالت تشخیص یک شخص جلو دوربین
  4. تاریک شدن ناگهانی محیط
  5. و مواقع هشدار امنیتی

توی این حالت دیتای سنسورها هم به صورت فرضی تولید می‌شن:

TXT
S.motion
S.lux
S.sound
S.batPct
S.activity

دشبورد اصلا نمی‌فهمه که این اعداد داره از دستگاه واقعی میاد یا شبیه‌ساز؛ فقط اون‌ها رو پردازش می‌کنه! برای طبیعی شدن کار، این اعداد یک‌دفعه بالا و پایین نمی‌شن، بلکه خیلی نرم تغییر می‌کنن.

TXT
S.motion =
S.motion +
(dTm - S.motion)
* 0.38;
S.lux =
S.lux +
(dLux - S.lux)
* 0.22;

جالبه بدونی حتی خالی شدن باتری هم شبیه‌سازی شده!

TXT
bv -= 0.00012;
if (bv < 3.0)
{
bv = 4.2;
}

با گذشت زمان:

  1. ولتاژ فرضی باتری کم می‌شه
  2. درصد باتری روی ویجت افت می‌کنه
  3. انیمیشن‌ها واکنش نشون می‌دن

شاهکار این شبیه‌ساز، تولید ویدیوی زنده ساختگیه. هیچ ویدیوی از پیش ضبط شده‌ای در کار نیست، بلکه همون لحظه تصویر امنیتی توسط جاوااسکریپت تولید می‌شه!

JavaScript
const id =
c.createImageData(
W,
H
);

موارد زیر در لحظه روی مرورگر ساخته می‌شن:

  1. نویز و برفک‌های تصویر دوربین
  2. افکت حرکت کردن صفحه
  3. ایجاد سایه‌ها و سوژه‌های فرضی متحرک
  4. شبیه‌سازی افکت دوربین دید در شب
  5. نمایش گرافیک‌های ضبط ویدیو
  6. درج ساعت و تاریخ متحرک روی تصویر

وقتی شبیه‌ساز حرکت رو تشخیص می‌ده، شکل‌های متحرکی تو تصویر ظاهر می‌شن.

TXT
if (ml > .1)
{
blobs.push({
x:R(.1,.85),
y:R(.3,.58)
});
}

این توهم رو بهت می‌ده که انگار یه نفر داره جلوی دوربین راه می‌ره. همچنین تاریک شدن هوا هم تست می‌شه.

JavaScript
const night =
S.ir ||
S.lux < 50;

وقتی محیط شبیه‌ساز تاریک بشه:

  1. حالت شب روشن می‌شه
  2. آیکون‌های مادون قرمز روی HUD میان
  3. نوع نویز تصویر تغییر می‌کنه
  4. رنگ تصویر حس یک دوربین امنیتی واقعی رو القا می‌کنه

کدهایی که این نسخه دمو رو اجرا می‌کنن، همون کدهای اصلی دشبورد هستن.

TXT
renderUI();

تنها فرقشون اینه که دیتا از کجا تامین می‌شه:

  1. تو حالت واقعی ← برد ESP32-S3 دیتا می‌ده
  2. تو حالت دمو ← کدهای شبیه‌ساز دیتا تولید می‌کنن

به خاطر همین وقتی حالت دمو رو باز می‌کنی، دقیقا حس می‌کنی که دوربین دستته.

مرحله ۲۳

یکپارچگی سیستم و تجربه کاربری

رسیدیم به نقطه‌ای که تمام این قطعات و کدها با هم ترکیب می‌شن تا یک محصول واحد و حرفه‌ای شکل بگیره. میکروکنترلر ESP32-S3 مثل مغز متفکر این سیستم، همزمان کارهای زیر رو با هم هندل می‌کنه:

  1. استریم روان و زنده ویدیو
  2. بررسی و تشخیص هرگونه حرکت تو محیط
  3. فعال‌سازی هوشمند حالت شب با تغییر نور
  4. اندازه‌گیری و آنالیز صدای محیط
  5. نوشتن مداوم ویدیوها روی کارت حافظه
  6. کنترل وضعیت ولتاژ و مصرف باتری
  7. سینتسایز کردن و پخش صدا از بلندگو
  8. ارسال و دریافت سریع فرمان‌ها با دشبورد

و همه این‌ها بدون اینکه باتری زود خالی بشه یا ویدیو لگ بزنه کار می‌کنه. کل چرخه سیستم به این شکل خلاصه می‌شه:

TXT
Camera & Sensors


ESP32-S3 Firmware

 Motion Detection
 Audio Processing
 Night Vision Logic
 Battery Monitoring
 SD Recording


Web Server API


Sentra Dashboard


Real-Time Monitoring & Device Control

هر تغییری تو سنسورها بلافاصله تو دشبورد مرورگرت نمایش داده می‌شه. و هر دستوری که تو دشبورد می‌دی تو کسری از ثانیه توسط دوربینت اجرا می‌شه.

مرحله ۲۴

آماده‌سازی و تنظیم کدها

قبل از اینکه برنامه‌رو روی برد بریزی، باید اطلاعات وای‌فای خونت و همین‌طور منطقه زمانیت رو به برنامه بدی. سورس کد رو باز کن و به جای مقادیر پیش‌فرض، نام و رمز وای‌فای خودت رو دقیق وارد کن:

TXT
#define WIFI_SSID "Your SSID"
#define WIFI_PASS "Your Pass"
#define TZ_OFFSET_SEC -28800 // UTC-8 Pacific Standard Time (PST)

منطقه زمانی هم برای اینه که تاریخ و ساعتی که روی ویدیوهای ذخیره شده روی مموری می‌خوره، دقیقا به وقت محلی خودت باشه.

مرحله ۲۵

آپلود برنامه روی پردازنده

حالا نرم‌افزار Arduino IDE رو باز کن. خیلی مهمه که تنظیمات برد رو دقیقا مثل لیست زیر اعمال کنی، وگرنه ممکنه دوربین اصلا روشن نشه:

  1. نوع برد: ESP32S3 Dev Module
  2. تنظیمات PSRAM: حتما روی OPI PSRAM
  3. حافظه فلش: 16MB (128Mb)
  4. پارتیشن‌بندی: Huge APP (3MB No OTA / 1MB SPIFFS)
  5. گزینه USB CDC On Boot: روشن (Enabled)
  6. فرکانس پردازنده: 240 MHz
  7. سرعت آپلود: 921600

تنظیم درست PSRAM و ظرفیت فلش حیاتیه؛ چون دوربین برای استریم کردن ویدیو و ذخیره روی رم به بافرهای خیلی بزرگی نیاز داره و اگر این گزینه‌ها اشتباه باشن، برد مدام ریستارت می‌شه.

بعد از تنظیمات، برد رو با کابل به کامپیوتر وصل کن، پورت رو انتخاب کن و دکمه آپلود رو بزن. وقتی تموم شد، سریال مانیتور رو باز کن تا هم آی‌پی آدرس دستگاه رو ببینی و هم از سالم بالا اومدن سیستم مطمئن بشی.

مرحله ۲۶

اجرای پنل مدیریت دوربین

حالا کافیه مرورگر گوشیت یا کامپیوترت رو باز کنی و آی‌پی دوربینی که تو مرحله قبل دیدی رو توش وارد کنی. دشبورد با یک رابط کاربری بسیار زیبا و حرفه‌ای برات لود می‌شه.

همون لحظه می‌تونی ویدیوی زنده دوربینت رو ببینی، ویجت‌های تشخیص حرکت رو چک کنی، ولتاژ باتری رو مانیتور کنی و فضای خالی کارت حافظه رو بررسی کنی. دکمه‌های کنترل آژیر، ریکورد و روشن کردن دید در شب هم همونجا آماده فرمان تو هستن. از کار کردن باهاش حسابی لذت ببر!

مرحله ۲۷

مونتاژ برد اصلی تو بدنه

دیگه وقت بستن قطعات و تکمیل دوربینه! برد اصلی ESP32-S3 رو با احتیاط بردار و روی استوانه‌های کوچکی که تو بدنه پرینت شده قرار بده. سوکت سیم اسپیکر رو هم به برد وصل کن.

طراحی بدنه طوریه که باید برد رو با 4 تا پیچ مینیاتوری سر جاش فیکس کنی. اگر پیچ به اون ریزی دم دستت نبود، می‌تونی مثل من از مقدار خیلی کمی چسب قطره‌ای استفاده کنی تا برد تکون نخوره.

مرحله ۲۸

نصب و جاگذاری شارژر

ماژول شارژری که تو مراحل اول سیم‌کشی کرده بودیم رو بیار. اون رو تو شیار مخصوصش قرار بده تا پورت USB Type-C دقیقا مماس با سوراخ روی بدنه بشه. اینطوری از بیرون راحت می‌تونی کابل شارژر گوشیت رو بهش بزنی.

بعد از اینکه ماژول شارژ محکم شد، اون دو تا سیمی که قراره برق 5 ولت رو به سیستم برسونن به ورودی تغذیه برد ESP32-S3 لحیم کن. بازم تاکید می‌کنم که مراقب قطب مثبت و منفی باش تا زحماتت هدر نره.

مرحله ۲۹

اضافه کردن دکمه فیزیکی

چون دکمه اصلی ماژول ESP روی خود برده و ما الان برد رو تو محفظه حبس کردیم، یک دکمه رابط پلاستیکی پرینت کرده بودیم تا از بیرون بتونیم دکمه اصلی رو فشار بدیم.

این قطعه پلاستیکی رو از شیار روی درپوش رد کن. این دکمه دقیقا مماس با دکمه روی برد قرار می‌گیره و با فشار دادنش، برد از بیرون ریستارت می‌شه.

مرحله ۳۰

بستن قاب دوربین (مرحله نهایی)

رسیدیم به مرحله جذاب آخر! درپوش رویی بدنه رو آروم بیار روی محفظه اصلی. حواست باشه سیم‌ها لای درز گیر نکنن و لنز دوربین هم تو زاویه درستی قرار گرفته باشه. وقتی همه‌چیز کیپ شد، از پشت بدنه با سه تا پیچ دو تکه قاب رو به هم سفت کن تا دوربینت شکل نهاییش رو پیدا کنه.

مرحله ۳۱

تست نهایی گجت ساخته شده

قبل از اینکه دوربین رو ببری واسه استفاده، یک کابل Type-C بهش وصل کن تا باتریش فول‌شارژ بشه. بعد از روشن شدن، دشبورد رو تو مرورگر باز کن و کیفیت استریم رو چک کن.

به خاطر سایز کوچک و بی‌سیم بودن این گجت، می‌تونی اون رو روی کتابخونه، لبه پنجره یا هر جای دیگه‌ای که دوست داری قرار بدی. حالا تک‌تک امکاناتش مثل ضبط ویدیو، روشن شدن اتوماتیک ال‌ای‌دی مادون قرمز تو تاریکی، و البته آژیر کشیدن موقع حرکت رو تست کن. دیدن اینکه مشتی قطعه الکترونیکی حالا تبدیل به یک دوربین مداربسته بی‌نقص شدن، واقعا حس فوق‌العاده‌ای داره!

مرحله ۳۲

کلام آخر

ما تو این آموزش در سایت آیسی‌مدار یاد گرفتیم که چطور از صفر، فقط با استفاده از یک برد توسعه ESP32-S3، کمی خلاقیت تو پرینت سه‌بعدی و نوشتن کدهای اصولی، یک محصول واقعی و به شدت کاربردی بسازیم.

این پروژه ثابت کرد که تکنولوژی اونقدر در دسترس قرار گرفته که می‌تونی سیستم نظارتی خودت رو بسازی که اتفاقا امنیت خیلی بالاتری نسبت به دوربین‌های ابری بازار داره، چون تمام دیتات رو روی رم خودش نگه می‌داره.

امیدوارم از ساختن این دوربین نهایت لذت رو برده باشی و چیزهای جدیدی درباره نحوه کار میکروکنترلرها، طراحی رابط کاربری تحت وب و معماری سیستم‌های توکار یاد گرفته باشی. اگر این پروژه رو ساختی یا ایده‌ای برای بهتر شدنش داری، حتما تو بخش نظرات برامون بنویس تا با هم راجع بهش گپ بزنیم. همیشه در آیسی‌مدار منتظر خلق ایده‌های جدیدت هستیم!

فایل‌های پیوست

STL Main housing.stl
STL Top cover.stl
STL Button extension.stl

تو میتونی اولین سازنده باشی!

اگه پروژه رو ساختی به اشتراک بزار و اعتبار هدیه بگیر

این آموزش با استانداردهای اختصاصی آیسی‌مدار بازنویسی و بهینه‌سازی شده و تمامی حقوق انتشار آن متعلق به این مجموعه است و در صورت کپی یا بازنشر پیگرد قانونی خواهد داشت.

آموزش‌های مشابه

گفتگو‌های کاربران

هنوز نظری ثبت نشده؛ تو شروع کن!