آموزش استفاده از ESP32CAM و راه اندازی ویدیو استریم و تشخیص چهره

فهرست مطالب

مقدمه

به آموزش گام به گام ESP32CAM خوش آمدید! آیا به دنیای اینترنت اشیا (IoT) علاقه مندید و به دنبال افزودن توان خود در زمینه ویدئو هستید؟ در این راهنمای جامع، با ماژول ESP32CAM آشنا خواهیم شد. چه یک علاقمند، دانشجو یا یک توسعه دهنده مشتاق اینترنت اشیا باشید، این آموزش شما را با دانش و مهارت هایی که برای ایجاد پروژه های مرتبط نیاز دارید، آشنا می کند.
ما شما را در هر مرحله راهنمایی می‌کنیم؛ از راه‌اندازی ماژول ESP32CAM گرفته تا پیکربندی دوربین، گرفتن فریم‌های ویدئویی و پخش آن‌ها از طریق شبکه.

ESP32CAM Board

آنچه در این آموزش یاد می گیرید

• دریافت تصویر از ESP32CAM
• تشخیص چهره با ESP32CAM

آشنایی با ESP32CAM

ESP32CAM یک برد توسعه قدرتمند و همه کاره است که میکروکنترلر ESP32 را با ماژول دوربین ترکیب می کند. این پلتفرم، برای ساخت پروژه‌های اینترنت اشیا که شامل پخش ویدئو باشد بسیار مفید است.
ماژول ESP32CAM با قابلیت‌های Wi-Fi و بلوتوث داخلی ارائه می‌شود که آن را برای نظارت از راه دور، سیستم‌های امنیتی و سایر کارهایی که نیاز به پخش ویدئو به صورت زنده و بی سیم دارند ایده‌آل می‌کند.

امکانات ESP32CAM

• کوچکترین ماژول SoC (وای فای و بلوتوث)
• CPU سی و دو بیتی کم مصرف
• حداکثر کلاک 160 مگاهرتز، قدرت محاسباتی تا 600 DMIPS
• SRAM داخلی 520 کیلوبایت، 4MPSRAM خارجی
• پشتیبانی از UART/SPI/I2C/PWM/ADC/DAC
• پشتیبانی از دوربین های OV2640 و OV7670
• لامپ فلاش داخلی
• پشتیبانی از آپلود تصویر با WiFi
• پشتیبانی از کارت TF
• پشتیبانی از چند حالت sleep
• LwIp و FreeRTOS
• پشتیبانی از حالت های کاری STA/AP/STA+AP
• پشتیبانی از فناوری Smart Config/AirKiss

کاربردهای ESP32CAM

ESP32CAM طیف گسترده ای از ویژگی های پیشرفته و گزینه های سفارشی سازی را برای پخش ویدئو ارائه می دهد. در اینجا بعضی از کاربرد های متنوع این برد را به شما معرفی می کنیم:
• مسائل امنیتی: با به کار بردن چندین ماژول ESP32CAM می توانید یک سیستم امنیتی هوشمند بسازید.
• صنایع رباتیک: با ارسال تصاویر از طریق WiFi و پردازش آن در یک سخت افزار قدرتمند، شما می توانید این ماژول را در انواع پروژه های رباتیک به کار ببرید.
• IOT: شاید یکی از مواردی که در اجرای پروژه های IOT نتوان از آن چشم پوشی کرد استفاده از تصاویر باشد. ماژول ESP32CAM، به دلیل داشتن امکانات یک میکروکنترلر، در کنار وای فای، بلوتوث داخلی و دوربین، کاربردهای فراوانی در اجرای هوشمندسازی اماکن دارد.
• کاربردهای ترکیبی با استفاده از نرم افزارهای پردازش تصویر (مانند OPENCV): با استفاده از ESP32CAM، می توانید دنیای بی انتهای پردازش تصویر را به پروژه های خود بیافزایید.

معرفی پایه های ESP32CAM (Pinout)

این ماژول دارای 16 پین به شرح زیر است:
5V: اتصال به منبع تغذیه 5 ولت
GND: اتصال به زمین منبع تغذیه
GPIO2-16: پایه های ورودی و خروجی دیجیتال، به همراه قابلیت های جانبی از جمله:
• مبدل آنالوگ به دیجیتال (7 کانال)
• پروتکل ارتباطی SPI
• درگاه کارت حافظه
• UART
در تصویر زیر، می توانید پین اوت (Pinout) این ماژول را مشاهده کنید.

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

لوازمی که به آن احتیاج دارید

ESP32CAM × 1
مبدل USB به TTL* × 1

*: هر نوع مبدل USB به سریال که قابلیت کار با سطح 3.3 ولت را داشته باشد، می توانید به کار ببرید.

راه اندازی سرور استریم ویدئو با ESP32CAM

گام اول: سیم بندی

ماژول ESP32CAM، پورت USB ندارد. بنابراین نمی توانید آن را به صورت مستقیم به کامپیوتر وصل کنید. برای پروگرام کردن و ارتباط با پورت سریال این ماژول، باید مبدل USB به TTL را به کار ببرید. در تصویر زیر، نقشه سیم کشی بین این ماژول و تبدیل USB به TTL را نمایش داده ایم.

پایه های مبدل USB به TTL، از راست به چپ به شرح زیر است:
+5V، VCC، +3.3V، TX، RX، GND

گام دوم: کد Video Streaming با استفاده از ESP32CAM

در این آموزش، برای کار با ماژول ESP32، از مثال موجود در کتابخانه آن استفاده می کنیم. گام های زیر را به تریتب انجام دهید.
1- نصب Add-on مربوط به ESP32: در صورت نیاز، راهنمای انجام این کار را در این لینک مطالعه کنید.
2- باز کردن مثال CameraWebServer.ino از مسیرِ Files-> Examples-> ESP32-> Camera

با باز کردن مثال اشاره شده، کد زیر برای شما به نمایش در می آید. توجه داشته باشید که این کد جهت اجرا، نیازمند چند تغییر جزئی است. این تغییرات را در قسمت توضیحات کد شرح خواهیم داد.

#include "esp_camera.h"
#include <WiFi.h>

//
// WARNING!!! PSRAM IC required for UXGA resolution and high JPEG quality
// Ensure ESP32 Wrover Module or other board with PSRAM is selected
// Partial images will be transmitted if image exceeds buffer size
//
// You must select a partition scheme from the board menu that has at least 3MB of APP space.
// Face Recognition is DISABLED for ESP32 and ESP32-S2, because it takes up from 15 
// seconds to process a single frame. Face Detection is ENABLED if PSRAM is enabled as well

// ===================
// Select camera model
// ===================
//#define CAMERA_MODEL_WROVER_KIT // Has PSRAM
//#define CAMERA_MODEL_ESP_EYE // Has PSRAM
//#define CAMERA_MODEL_ESP32S3_EYE // Has PSRAM
//#define CAMERA_MODEL_M5STACK_PSRAM // Has PSRAM
//#define CAMERA_MODEL_M5STACK_V2_PSRAM // M5Camera version B Has PSRAM
//#define CAMERA_MODEL_M5STACK_WIDE // Has PSRAM
//#define CAMERA_MODEL_M5STACK_ESP32CAM // No PSRAM
//#define CAMERA_MODEL_M5STACK_UNITCAM // No PSRAM
#define CAMERA_MODEL_AI_THINKER // Has PSRAM
//#define CAMERA_MODEL_TTGO_T_JOURNAL // No PSRAM
//#define CAMERA_MODEL_XIAO_ESP32S3 // Has PSRAM
// ** Espressif Internal Boards **
//#define CAMERA_MODEL_ESP32_CAM_BOARD
//#define CAMERA_MODEL_ESP32S2_CAM_BOARD
//#define CAMERA_MODEL_ESP32S3_CAM_LCD

#include "camera_pins.h"

// ===========================
// Enter your WiFi credentials
// ===========================
const char* ssid = "Caferobot-2G";
const char* password = "caferobot.ir";

void startCameraServer();
void setupLedFlash(int pin);

void setup() {
 Serial.begin(115200);
 Serial.setDebugOutput(true);
 Serial.println();

 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.frame_size = FRAMESIZE_UXGA;
 config.pixel_format = PIXFORMAT_JPEG; // for streaming
 //config.pixel_format = PIXFORMAT_RGB565; // for face detection/recognition
 config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
 config.fb_location = CAMERA_FB_IN_PSRAM;
 config.jpeg_quality = 12;
 config.fb_count = 1;
 
 // if PSRAM IC is present, init with UXGA resolution and higher JPEG quality
 // for larger pre-allocated frame buffer.
 if(config.pixel_format == PIXFORMAT_JPEG){
 if(psramFound()){
 config.jpeg_quality = 10;
 config.fb_count = 2;
 config.grab_mode = CAMERA_GRAB_LATEST;
 } else {
 // Limit the frame size when PSRAM is not available
 config.frame_size = FRAMESIZE_SVGA;
 config.fb_location = CAMERA_FB_IN_DRAM;
 }
 } else {
 // Best option for face detection/recognition
 config.frame_size = FRAMESIZE_240X240;
#if CONFIG_IDF_TARGET_ESP32S3
 config.fb_count = 2;
#endif
 }

#if defined(CAMERA_MODEL_ESP_EYE)
 pinMode(13, INPUT_PULLUP);
 pinMode(14, INPUT_PULLUP);
#endif

 // camera init
 esp_err_t err = esp_camera_init(&config);
 if (err != ESP_OK) {
 Serial.printf("Camera init failed with error 0x%x", err);
 return;
 }

 sensor_t * s = esp_camera_sensor_get();
 // initial sensors are flipped vertically and colors are a bit saturated
 if (s->id.PID == OV3660_PID) {
 s->set_vflip(s, 1); // flip it back
 s->set_brightness(s, 1); // up the brightness just a bit
 s->set_saturation(s, -2); // lower the saturation
 }
 // drop down frame size for higher initial frame rate
 if(config.pixel_format == PIXFORMAT_JPEG){
 s->set_framesize(s, FRAMESIZE_QVGA);
 }

#if defined(CAMERA_MODEL_M5STACK_WIDE) || defined(CAMERA_MODEL_M5STACK_ESP32CAM)
 s->set_vflip(s, 1);
 s->set_hmirror(s, 1);
#endif

#if defined(CAMERA_MODEL_ESP32S3_EYE)
 s->set_vflip(s, 1);
#endif

// Setup LED FLash if LED pin is defined in camera_pins.h
#if defined(LED_GPIO_NUM)
 setupLedFlash(LED_GPIO_NUM);
#endif

 WiFi.begin(ssid, password);
 WiFi.setSleep(false);

 while (WiFi.status() != WL_CONNECTED) {
 delay(500);
 Serial.print(".");
 }
 Serial.println("");
 Serial.println("WiFi connected");

 startCameraServer();

 Serial.print("Camera Ready! Use 'http://");
 Serial.print(WiFi.localIP());
 Serial.println("' to connect");
}

void loop() {
 // Do nothing. Everything is done in another task by the web server
 delay(10000);
}

توضیحات کد

روند کلی کد به صورت زیر است.
1. بارگذاری کتابخانه های مورد استفاده

#include "esp_camera.h"
#include <WiFi.h>

2. انتخاب مدل دوربین:
در خط 16 الی 30، دوربین مورد نظر را انتخاب و آن را از حالت کامنت خارج کنید. در ماژول ESP32CAM ما، دوربین نصب شده بر روی ماژول، از نوع AI_THINKER است.

#define CAMERA_MODEL_AI_THINKER // Has PSRAM

3. بارگذاری کتابخانه camera_pins.h که نحوه اتصال پایه های دوربین به ESP32 را مشخص می کند.

#include "camera_pins.h"

4. تعریف شبکه وای فای مورد نظر: در این قسمت، نام شبکه وای فای (SSID) و رمز آن (password) را وارد کنید.

const char* ssid = "**************";
const char* password = "**************";

5. تعریف توابع راه اندازی سرور، صفحه وب و فلاش دوربین ماژول ESP32CAM

void startCameraServer();
void setupLedFlash(int pin);

6. تابع setuo()
• راه اندازی ارتباط سریال و فعال کردن پیام های debug

Serial.begin(115200);
  Serial.setDebugOutput(true);

• تعریف پین های دوربین بر روی ESP32 بر اساس فایل camera_pins.h

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.frame_size = FRAMESIZE_UXGA;
  config.pixel_format = PIXFORMAT_JPEG; // for streaming
  //config.pixel_format = PIXFORMAT_RGB565; // for face detection/recognition
  config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
  config.fb_location = CAMERA_FB_IN_PSRAM;
  config.jpeg_quality = 12;
  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", err);
    return;
  }

• اتصال به وای فای

  WiFi.begin(ssid, password);
  WiFi.setSleep(false);

• فعال کردن سرور

  startCameraServer();

• چاپ آی پی ماژول ESP32CAM در درگاه سریال (در صورت موفقیت در فعالسازی دوربین و WiFi)

  Serial.print("Camera Ready! Use 'http://");
  Serial.print(WiFi.localIP());
  Serial.println("' to connect");

گام سوم: پروگرام کردن ESP32CAM

قبل از پروگرام کردن برد، ابتدا نوع برد ESP32CAM را بر روی “AIThinker ESP32-CAM” تنظیم کنید.

سپس، تنظیمات “Flash Mode” را بر روی “DIO” قرار دهید.

همچنین، در بین گزینه های “Partition Scheme” گزینه “Huge APP” را انتخاب کنید.

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

این آدرس را در مرورگر باز کنید. صفحه زیر را مشاهده خواهید کرد.

ESP32CAM (Web Result)

با زدن بر روی دکمه “Start stream،” تصویر دریافتی از ماژول ESP32Cam در صفحه نمایش داده می شود.

تشخیص چهره با ESP32CAM

برای تشخیص چهره، ابتدا رزولوشن تصویر را روی QVGA قرار دهید و سپس گزینه های Face detection و Face recognition را تیک بزنید.

ESP32CAM (Face Recognition Settings)

حال تصویری مشابه تصویر زیر را مشاهده خواهید کرد. در این تصویر، صورت فرد توسط ESP32CAM تشخیص داده شده است.

ESP32CAM (Face Recognition Result)

رفع مشکلات احتمالی ESP32 Video Streaming

1- پروگرام نشدن برد ESP32CAM

برای رفع این خطا، موراد زیر را بررسی کنید.
• سیم کشی را چک کنید.
• اگر مبدل USB به TTL شما امکان انتخاب بین 5 و 3.3 ولت دارد، آن را در وضعیت 3.3 ولت قرار دهید.
• ولتاژ خروجی مبدل را با استفاده از ولتمتر اندازه گیری کنید. نباید کمتر از 5 ولت باشد.
• در انتخاب نوع برد و دوربین دقت داشته باشید.
• قبل از هر بار پروگرام کردن برد، پایه IO0 را با پایه GND متصل کرده و دکمه RST را بزنید.

2- چاپ عبارت “Brownout detector was triggered”

 در صورتی که این عبارت به شکل مرتب در پورت سریال چاپ می شود، موارد زیر را امتحان کنید:
• استفاده از کابل USB کوتاه‌تر (با سیم‌های داده)
• اتصال به پورت USB دیگر کامپیوتر و یا هاب USB با منبع تغذیه خارجی

3- خطای “Sketch too big”

در صورت وقوع این خطا، احتمالاً “Partition Scheme” خود را بر روی “Big APP” قرار نداده اید. این مورد را اصلاح و مجدداً پروگرام کنید.

4- خطای ناشی از آنتن دهی ضعیف WiFi

در صورتی که فاصله شما از دستگاه روتر زیاد باشد و به خوبی نتوانید به شبکه وای فای متصل شوید، لازم است از آنتن خارجی کمک بگیرید. برای اینکار، باید مقاومت 0 کیلواهم قرار گرفته در کنار پورت آنتن ماژول ESP32CAM را جابجا کنید.
جهت استفاده از آنتن خارجی، مقاومت علامت زده شده باید جدا شده و به صورت عمود بر آن لحیم شود (تصویر زیر).

ESP32CAM (External Antenna)

5- نمی توانم صفحه وب سرور را باز کنم

اگر ESP32Cam شما در درگاه سریال مانیتور، آی پی آدرس را چاپ می کند ولی نمی توانید آن را در مرورگر خود باز کنید، احتمالاً به صورت همزمان با چندین tab مرورگر سعی در اتصال به وب سرور را دارید. در حال حاضر، امکان اتصال تنها یک Client به وب سرور ESP32CAM وجود دارد.

6- تصویر با تاخیر همراه است

در صورت مشاهده تاخیر در به روز رسانی تصویر، می توانید راهکارهای زیر را امتحان کنید.
• اتصال ماژول ESP32CAM به منبع تغذیه 5 ولت جداگانه
• کوچکتر کردن رزولوشن تصویر
• استفاده از آنتن خارجی

یک گام جلوتر

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

ESP32CAM (Patrol Robot)
جزئیات بیشتر برای انجام این پروژه را اینجا مطالعه کنید. • آیفون تصویری هوشمند: این آیفون زمانی که کسی زنگ در شما را بزند، تصویر او را بر روی صفحه نمایش تلفن همراهتان نمایش می دهد و می توانید درب منزل خود را از راه دور کنترل کنید.
ESP32CAM (Smart Doorbell)
جزئیات بیشتر برای انجام این پروژه را اینجا مطالعه کنید.

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

Comments (6)

  • حسین علیرمضانی Reply

    با سلام
    این راهنما یک اشکال دارد و من برای پیدا کردن آن نزدیک ۳ ساعت با اسیلوسکوپ تمام پایه ها و سیگناها را چک کردم تا بالاخره با این توضیح در یکی از سایتها، این اشکال را پیدا کردم:
    Some ESP32-CAM boards have that pin near the big LED labeled “GND/R”. This is where most tutorials and posts say to connect the ground from the serial board. This will NOT work because that pin is not a ground. Use any of the other real GND pins and assuming you’re doing the other stuff correctly then everything should work.
    بنا بر این در بخش «گام اول: سیم بندی» عکس باید تغییر کند. سیم GND نباید به پایه GND/R وصل شود. بلکه باید به پایه GND وصل شود.
    در این صورت با ریست ESP32، در ترمینال سریال، وضعیت بوت شدن CPU دیده می شود.
    برای آپلود کردن، باید پایه IO0 به GND وصل بماند. در این وضعیت، ریست کردن برد عبارت waiting for download را در ترمینال سریال نشان می دهد. در این حالت می توان آپلود برنامه را انجام داد. بعد ارتباط IO0 به GND قطع شود تا با ریست دوباره، برنامه آپلود شده اجرا گردد.

    فوریه 6, 2024 at 11:16 ب.ظ
    • محمد دمیرچی Reply

      با سلام
      ممنون بابت نظر شما، آموزش اصلاح می شود.

      فوریه 7, 2024 at 9:58 ق.ظ
  • احمدرضا Reply

    سلام خسته نباشید من کد که آپلود کردم این خط#include “camera_pins.h” را برایم خطا گرفت بعد کتاب خانه اش را جست‌وجو کردم ولی نبود ممنون میشم راهنماییم کنید

    مارس 14, 2024 at 6:16 ب.ظ
    • محمد دمیرچی Reply

      با سلام
      در گام دوم، بخش دوم اعلام شده است (2- باز کردن مثال CameraWebServer.ino از مسیرِ Files-> Examples-> ESP32-> Camera)
      باید پروژه را باز کنید. وقتی از مثال باز کنید فایل camera_pins.h را نیز همراه پروژه باز میشود و دیگر به شما ارور داده نمیشود.

      مارس 24, 2024 at 10:33 ق.ظ
  • ddddd Reply

    سلام خسته نباشید
    من بعد اینکه همه کار هارو کردم و پروگرام کردم وقتی دکمه ریست رو میزنم توی قسمت مانیتور این ارور رو میده

    E (488) camera: Camera probe failed with error 0x105(ESP_ERR_NOT_FOUND)
    Camera init failed with error 0x105

    مارس 30, 2024 at 6:18 ب.ظ
    • محمد دمیرچی Reply

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

      آوریل 2, 2024 at 11:09 ق.ظ

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد.