آموزش‌های کاربردیاخبار تکنولوژیبایگانی مطالب
مقاله جدید

معرفی مشخصات و روش راه‌اندازی برد دوربین XIAO ESP32S3 Sense

در این نوشتار کوچک‌ترین دوربین ESP32 به نام سنس برد Seeeduino XIAO ESP32S3 رو با هم بررسی می‌کنیم.

معرفی برد دوربین Seeeduino XIAO ESP32S3

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

اما Espressif در سال 2016 تراشه ESP32 (جانشین ماژول ESP8266) رو عرضه کرد و همه چیز تغییر کرد. این میکروکنترلر 32بیتی مشخصات و عملکردی داشت که خیلی از نسخه‌های 8بیتی بهتر بود. علاوه بر این، سرعت و مموری این تراشه به اندازه‌ای بود که می‌تونست ویدئوها رو پردازش کنه.

معرفی برد دوربین Seeeduino XIAO ESP32S3

بیشتر از یک سال بعد از عرضه ESP32، شرکتی به نام AI Thinker برد ESP32-CAM رو عرضه کرد. این دوربین کوچک که فقط 250هزار تومن قیمت داشت برای ساخت تفریحی قطعات الکترونیکی و پیاده‌سازی سیستم‌های نظارتی ارزان عالی بود. این برد علاوه بر قیمت پایینش، یک نگهدارنده کارت MicroSD و همچنین یک Flash LED سفید رنگ هم داره. این برد درگاه USB نداره برای همین برای برنامه‌نویسی اون به یک آداپتور FTDI لازمه ( این روزها، این قطعه به همراه یک برد آداپتور USB عرضه و فروخته می‌شه).

معرفی و راه اندازی ماژول دوربین ESP32-CAM

تولیدکنندگان دیگر بردهای دوربین مبتنی بر ESP32 از ESP32-CAM پیروی کردن. ESpressif هم یک برد دوربین کوچک و مبتنی بر ESP32 عرضه کرد که دارای یک میکروفونه.

مقایسه ابعاد برد XIAO ESP32S3 Sense با ESP32-CAM

Espressif یک نمونه طرح به نام CameraWebServer به نمونه‌های ESP32 اضافه کرده؛ کاربران با استفاده از این نمونه می‌تونن از دوربین به همراه یک رابط تمام عیار استفاده کنن. این رابط تعداد قابل توجهی کنترل برای دوربین داره و علاوه بر پخش ویدئو می‌تونه عملیات تشخیص چهره رو هم انجام بده.

این روزها، بردهای دوربین ESP32 متفاوتی وجود داره که تولیدکنندگان مختلف عرضه کردن و هر کدومشون امکانات و قابلیت‌های متفاوتی دارن. در این مطلب، قراره یکی از جدیدترین این بردها رو به نام سنس برد Seeeduino XIAO ESP32S3 بررسی کنیم.


معرفی برد XIAO ESP32S3 Sense

بررسی کوچکترین برد دوربین Seeeduino XIAO ESP32S3

سنس برد Seeeduino XIAO ESP32S3 در واقع از دو تا برد جداگانه تشکیل شده:

  • برد Seeeduino XIAO ESP32S3: این برد رو به طور جداگانه هم می‌تونین تهیه کنین. این برد شامل میکروکنترلر، دو تا LED، یک کانکتور USB-C و دو تا سوییچ کلید فشاری کوچک داره.

  • ماژول دوربین: این ماژول به بالای برد XIAO وصل می‌شه. این ماژول علاوه بر دوربین، یک میکروفون و یک نگهدارنده کارت MicroSD هم داره.

برد Seeeduino XIAO ESP32S3 و ماژول دوربین OV2640

برد XIAO ESP32S3 یک کانکتور USB-C برای برق و انتقال داده داره و ویژگی‌ها و اتصالاتش شبیه به سایر بردهای گروه میکروکنترلرهای Seeeduino XIAO هست.

XIAO ESP32S3 Sense package


خانواده بردهای Seeeduino XIAO

بردهای Seeeduino XIAO میکروکنترلرهای خیلی کوچکی هستن که بر روی بردهای مدار چاپی کوچک ساخته شدن. همچنین کانکتورهای پین دژمانندی(castellated) دارن که میشه اونا رو به همراه پایه‌های Dupont رایج و دستگاه surface-mount استفاده کرد.

خانواده برد XIAO خیلی بزرگ‌ و متنوع هستن که به طور خلاصه به شرح زیر هستند:

  • XIAO SAMD21: برد اصلی که یک پردازنده SAMD21 Cortex-M0+ داره که سرعتش 48 مگاهرتز هست.

  • XIAO RP2040: یک پردازنده RP2040 دو هسته‌ای Cortex-M0+ داره و سرعتش 133 مگاهرتز هست.

  • XIAO nRF52840 : دستگاه بلوتوث فوق کم مصرف. پردازنده Cortex-M4 و سرعت 64 مگاهرتز.

  • XIAO nRF52840 Sense : نسخه پیشرفته nRF52840 به همراه میکروفون و IMU.

  • ESP32 RISC-V : XIAO ESP32C3  با سرعت 160 مگاهرتز مجهز به بلوتوث و وای‌فای.

  • XIAO ESP32S3: پردازنده دو هسته‌ای Xtensa LX7 با سرعت 240 مگاهرتز.

  • XIAO ESP32S3 : XIAO ESP32S3 Sense مجهز به ماژول دوربین و میکروفون

مشخصات فنی XIAO ESP32S3 Sense

مشخصات فنی Seeeduino XIAO ESP32S3 به شرح زیر است:

  • پردازنده: پردازنده دو هسته‌ای ESP32-S3R8 Xtensa LX7/ حداکثر سرعت 240 مگاهرتز

  • وای‌فای: 2.4 مگاهرتز

  • بلوتوث – بلوتوث کم‌مصرف: Bluetooth 5.0، Bluetooth mesh

  • مموری: 8 مگابایت PSRAM و 8 مگابایت فلش

  • پایه GPIO: شامل 11 پورت I/O

  • سوییچ‌های لمسی: 9 پین برای سوییچ‌های لمسی

  • رابط: UART، SPI، I2C و I2S

  • ابعاد: 21 x 17.5 میلی‌متر

  • دوربین: حسگر OV2640 1600*1200

  • میکروفون: میکروفون MSM261D3526H1CPM MEMS

  • MicroSD: حداکثر 32 گیگابایت، فرمت FAT32

طراحی پایه‌های برد XIAO دژمانند هستند و می‌شه اونا رو روی سطح نصب کرد یا به همراه پایه‌های نری و مادگی Dupont استفاده کرد. این پایه‌ها در پکیج برد نیستن.

Seeeduino XIAO ESP32S3


طرح پایه‌های XIAO ESP32S3 Sense

XIAO ESP32S3 Sense از دو تا برد تشکیل می‌شه:

  • برد اصلی
  • برد دوربین / میکروفون / MicroSD

نمای فوقانی برد اصلی به این شکله:

قطعات برد Seeeduino XIAO ESP32S3

همان‌طور که مشاهده می‌کنین کلیدهای فشاری خیلی کوچک هستن. از این کلیدها می‌شه برای reset برد یا فعال کردن حالت bootloader استفاده کرد.

برد XIAO دو تا LED هم داره:

  • قرمز: شارژ باتری و برق رو نشون میده.
  • زرد: LED کاربر، معادل LED_BUILTIN. این LED زمانی روشن می‌شه که ورودی LOW باشه که برای بیشتر بردهای آردوینو برعکسه.

طرح پایه برد اصلی

طرح پایه برد اصلی به شکل زیر است:

نقشه pinout برد Seeeduino XIAO ESP32S3

تمامی پایه‌های I/O چند منظوره هستند و میشه با نام‌هایی که آردوینو مشخص کرده یا با شماره ESP32 GPIO اونا رو تشخیص‌ داد.

پایه برق 5 ولتی هم میشه بعنوان پایه ورودی باشه هم بعنوان پایه خروجی:

  • ورودی: 5 ولت برای تأمین برق XIAO. این کار رو باید با یک دیود Schottky انجام داد تا منبع تغذیه از ولتاژ USB-C جدا بشه.

  • خروجی: اگر به USB-C برق‌رسانی بشه، میشه از این پایه به عنوان خروجی 5 ولتی استفاده کرد. البته توجه داشته باشین که این ولتاژ وقتی برد رو با باتری روشن می‌کنین، وجود نداره.

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


طرح پایه زیر برد اصلی

در زیر برد اتصالات دیگه‌ای هم وجود داره:

نقشه pinout بخش زیرین برد Seeeduino XIAO ESP32S3

این نقاط امکان اتصال به چند تا پایه USB-C و برخی اتصالات کانکتور برد به برد رو فراهم می‌کنن. برای اتصال باتری پدهایی برای لحیم هم اینجا قرار دادن.


طرح پایه و اتصالات برد دوربین

برد دوربین دو تا اتصال GPIO اضافی داره:

طرح pinout ماژول دوربین OV2640 برد Seeeduino XIAO ESP32S3


مقایسه XIAO ESP32S3 Sense و ESP32-CAM

در جدول زیر در برد Seeeduino XIAO ESP32S3 Sense و برد ESP32-CAM از AI Thinker رو با هم مقایسه کردیم:

مقایسه XIAO ESP32S3 Sense و ESP32-CAM

توجه داشته باشین که XIAO در تمامی معیارها یا برابر با برد ESP32-CAM هست یا بهتر از اون. تنها استثنایی که وجود داره LED سفید فلش در برد ESP32-CAM هست که XIAO اونو نداره.

ESP32-CAM رو می‌شه به همراه آنتن داخلی و خارجی(External) هم استفاده کرد، اما XIAO رو فقط میشه به همراه آنتن خارجی استفاده کرد.

به ندرت پیش میاد که آنتن XIAO کاربرد داشته باشه. اگر این آنتن رو با یک آنتن 2.4 گیگاهرتزی به همراه یک کانکتور U.FL عوض کنین خیلی بهتره.


شروع کار با XIAO ESP32S3 Sense

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

بعد از این مرحله، می‌تونین بردتون رو همراه با Arduino IDE رو تو کامپیوترتون راه‌اندازی کنین.


راه‌اندازی Arduino IDE

برد Seeeduino XIAO ESP32S3 به یک فایل JSON جدید boards manager نیاز نداره، چون از قبل آخرین نسخه ESP32 Boards Manger در اون نصب شده.

از طریق USB-C برد XIAO رو به کامپیوترتون وصل کنین. حالا باید ببینین که Arduino IDE می‌تونه اون رو به درستی تشخیص بده یا نه. اگه تشخیصش نداد (احتمالا یک برد ESP32S3 دیگه پیدا می‌کنه) به صورت دستی برد رو جست‌وجو کنین و باید “XIAO ESP32S3” رو پیدا کنین. اگر XIAO رو پیدا نکردین احتمالا باید boards manager رو به‌روزرسانی کنین.

بعد از انتخاب برد مناسب باید یک کار دیگه هم انجام بدین. شما باید گزینه IDE PSRAM رو روی OPI PSRAM تنظیم کنین. برای انجام این کار، به منوی Tools برید و به سمت PSRAM اسکرول کنین. اگر غیرفعال بود، OPI PSRAM رو انتخاب و فعال کنین.

در نهایت، Arduino IDE به درستی برای برد Seeeduino XIAO ESP32S3 Sense راه‌اندازی می‌شه.


بارگذاری مجدد Bootloader

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

بارگذاری مجدد Bootloader

برای حل این مشکل، باید bootloader رو مجدداً بارگذاری کنین. این کار حداقل اگه انگشت‌های کوچکی دارین، ساده است:

  • کابل USB-C رو جدا کنین.
  • کلید کوچک Boot رو بزنین (کنارش حرف B به صورت کوچک نوشته شد)
  • کابل USB-C رو وارد کنین.
  • دستتون رو از روی کلید بردارید.

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

بعد از این مرحله، یک طرح ساده مثل Blink رو بارگذاری کنین تا ببینین کار می‌کنه یا نه.


دموی CameraWebServer

پروژه “Hello World” دوربین مبتنی بر ESP32 طرح CameraWebServer است. این طرح در فایل‌های Examples، در کنار ESP32 boards manager و زیر بخش WiFi قرار داره.

CameraWebServer یک رابط دوربین کامل اجرا می‌کنه و با استفاده از اون می‌شه دوربین رو به عنوان یک دستگاه پخش یا دستگاه ثابت کنترل کرد. شما می‌تونین تمامی پارامترها رو تنظیم کنین و علاوه بر این، با استفاده از این اپلیکیشن می‎تونین تصاویر رو در MicroSD card ذخیره کنین.

قبل از بارگذاری نمونه طرح، باید دو تا تغییر رو اعمال کنین:

  • نوع دوربین باید CAMERA_MODEL_XIAO_ESP32S3 باشه. این مدل باید در فایل h قرار بگیره.
  • SSID و گذرواژه شبکه وای‌فای رو هم باید وارد کنین.

اگه از یک نسخه قدیمی CameraWebServer استفاده می‌کنین که XIAO رو نداره می‌تونین از کپی اون که در فایل ZIP قرار داره به همراه کدهای جدیدتر استفاده کنین. پس از بارگذاری اون می‌تونین امتحانش کنین. راه‌اندازیش کنین و در Serial Monitor دنبال یک URL بگردین که شامل یک آدرس IP هست که روتر بی‌سیم مشخص کرده. بعد به کامپیوتر یا لپ‌تاپی برید که به همان شبکه بی‌سیم وصل هست و اون آدرس رو تایپ کنین.

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

دموی CameraWebServer

عملکرد دوربین مثل ESP32-CAM هست که کاملاً منطقی هست چون این دو تا برد از 2 تا حسگر MP یکسان استفاده می‌کنن.


ساخت پروژه آزمایشی
دوربین ضبط صدا

امروز می‌خوایم یک آزمایش انجام بدیم و می‌تونیم اون رو به یک پروژه عملی تبدیل کنیم.

در این آزمایش از XIAO به عنوان یک دوربین ثابت استفاده می‌کنیم. تصاویر با فرمت JPEG در کارت میکرو SD ذخیره می‌شن. XIAO بعد از ذخیره تصاویر، یک صدای 10 ثانیه‌ایی ضبط می‌کنه و اون رو در قالب فایل WAV ذخیره می‌کنه. این مدت زمان رو خودتون می‌تونین تغییر بدین.

با لمس یکی از سوییچ‌های لمسی پروژه فعال می‌شه.


اتصال XIAO

اتصال این پروژه خیلی آسونه. فقط کافیه یک سوییچ لمسی ررو به اولین پایه یعنی TOUCH1 وصل کنین.

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


آماده‌سازی کارت میکرو SD

کارت میکرو SD باید نهایتا 32 گیگابایت یا کمتر باشه؛ می‌تونین از یک کارت بزرگ‌تر هم استفاده کنین اما ظرفیت بیشتر از 32 گیگابایت قابل استفاده نیست.

این کارت باید با FAT32 فرمت بشه، اگه فرمت کارتتون این نبود باید فرمت اون رو تغییر بدین که در این صورت تمامی داده‌های اون حذف می‌شه. File Manager سیستم عامل Windows آسون‌ترین روش برای فرمت کردن کارت هست. در سیستم عامل مک هم ابزار Mac Disk Utility می‌تونه این کار رو انجام بده.

فرمت خیلی ازکارت میکرو SDهای حجم پایین معمولا بصورت پیشفرض FAT32 هست و برای همین لازم نیست شما تغییری انجام بدین.

کارت میکرو SD رو بعد از فرمت کردن در جایگاه برد XIAO ESP32D3 Sense قرار بدین. حتماً برد دوربین رو به روشی ایمن روی برد اصلی نصب کنین و USB-C رو به کامپیوترتون وصل کنین.


طرح دوربین ضبط صدا

این طرح از چند تا کتابخانه استفاده می‌کنه تا با دستگاه‌هایی برد Sense ارتباط برقرار کنه.


ماژول دوربین OV2640

مشخصات ماژول دوربین OV2640

ماژول دوربین از کتابخانه ESP32 Camera استفاده می‌کنه. زمانی که ESP32 Boards Manager رو نصب کردین این کتابخانه هم نصب شده.


میکروفون MSM261D3526H1CPM MEMS

میکروفون MSM261D3526H1CPM MEMS

این ماژول میکروفون یک رابط I2S داره و به همین دلیل، برای کار کردن با اون از کتابخانه I2S استفاده می‌کنیم. کتابخانه I2S یکی دیگه از کتابخانه‌هایی هست که به همراه ESP32 Boards Manager نصب می‌شه.


کارت MicroSD

کارت MicroSD

برای کار کردن با کارت میکرو SD به 3 تا کتابخانه نیاز داریم. با توجه به اینکه کارت میکرو SD یک رابط SPI داره، از کتابخانه SPI استفاده می‌کنیم. کتابخانه FS هم file system رو مدیریت می‌کنه که برای ایجاد و ذخیره فایل‌ها بهش نیاز داریم. کتابخانه SD هم کارت SD رو مدیریت می‌کنه.


طرح XIAO-Camera-Microphone-SD

از طرح زیر برای دموی «دوربین ضبط صدا» استفاده می‌کنیم:

سورس کد دوربین ضبط صدا

/*
  XIAO ESP32S3 Sense Camera with Microphone Demo
  xiao-camera-mic-demo.ino
  Tests onboard Camera, MEMS Microphone, and MicroSD Card
  Takes a picture and a 10-second recording when Touch Switch is pressed
  Saves to MicroSD card in JPG & WAV format
*/

// Include required libraries
#include <Arduino.h>
#include <esp_camera.h>
#include <FS.h>
#include <SD.h>
#include <SPI.h>
#include <I2S.h>

// Define camera model & pinout
#define CAMERA_MODEL_XIAO_ESP32S3  // Has PSRAM
#include "camera_pins.h"

// Audio record time setting (in seconds, max value 240)
#define RECORD_TIME 10

// Audio settings
#define SAMPLE_RATE 16000U
#define SAMPLE_BITS 16
#define WAV_HEADER_SIZE 44
#define VOLUME_GAIN 3

// Camera status variable
bool camera_status = false;

// MicroSD status variable
bool sd_status = false;

// File Counter
int fileCount = 1;

// Touch Switch variables
int threshold = 1500;  // Adjust if not responding properly
bool touch1detected = false;

// Save pictures to SD card
void photo_save(const char *fileName) {
  // Take a photo
  camera_fb_t *fb = esp_camera_fb_get();
  if (!fb) {
    Serial.println("Failed to get camera frame buffer");
    return;
  }
  // Save photo to file
  writeFile(SD, fileName, fb->buf, fb->len);

  // Release image buffer
  esp_camera_fb_return(fb);

  Serial.println("Photo saved to file");
}

// SD card write file
void writeFile(fs::FS &fs, const char *path, uint8_t *data, size_t len) {
  Serial.printf("Writing file: %s\r\n", path);

  File file = fs.open(path, FILE_WRITE);
  if (!file) {
    Serial.println("Failed to open file for writing");
    return;
  }
  if (file.write(data, len) == len) {
    Serial.println("File written");
  } else {
    Serial.println("Write failed");
  }
  file.close();
}

void record_wav(String audiofile) {
  uint32_t sample_size = 0;
  uint32_t record_size = (SAMPLE_RATE * SAMPLE_BITS / 8) * RECORD_TIME;
  uint8_t *rec_buffer = NULL;
  Serial.printf("Recording Sound...\n");

  File file = SD.open(audiofile, FILE_WRITE);
  // Write the header to the WAV file
  uint8_t wav_header[WAV_HEADER_SIZE];
  generate_wav_header(wav_header, record_size, SAMPLE_RATE);
  file.write(wav_header, WAV_HEADER_SIZE);

  // PSRAM malloc for recording
  rec_buffer = (uint8_t *)ps_malloc(record_size);
  if (rec_buffer == NULL) {
    Serial.printf("Malloc failed!\n");
    while (1)
      ;
  }
  Serial.printf("Buffer: %d bytes\n", ESP.getPsramSize() - ESP.getFreePsram());


  // Start recording
  esp_i2s::i2s_read(esp_i2s::I2S_NUM_0, rec_buffer, record_size, &sample_size, portMAX_DELAY);
  if (sample_size == 0) {
    Serial.printf("Record Failed!\n");
  } else {
    Serial.printf("Record %d bytes\n", sample_size);
  }

  // Increase volume
  for (uint32_t i = 0; i < sample_size; i += SAMPLE_BITS / 8) {
    (*(uint16_t *)(rec_buffer + i)) <<= VOLUME_GAIN;
  }

  // Write data to the WAV file
  Serial.printf("Writing to the file ...\n");
  if (file.write(rec_buffer, record_size) != record_size)
    Serial.printf("Write file Failed!\n");

  free(rec_buffer);
  file.close();
  Serial.printf("The sound recording has finished.\n");
}

void generate_wav_header(uint8_t *wav_header, uint32_t wav_size, uint32_t sample_rate) {
  // See this for reference: http://soundfile.sapp.org/doc/WaveFormat/
  uint32_t file_size = wav_size + WAV_HEADER_SIZE - 8;
  uint32_t byte_rate = SAMPLE_RATE * SAMPLE_BITS / 8;
  const uint8_t set_wav_header[] = {
    'R', 'I', 'F', 'F',                                                   // ChunkID
    file_size, file_size >> 8, file_size >> 16, file_size >> 24,          // ChunkSize
    'W', 'A', 'V', 'E',                                                   // Format
    'f', 'm', 't', ' ',                                                   // Subchunk1ID
    0x10, 0x00, 0x00, 0x00,                                               // Subchunk1Size (16 for PCM)
    0x01, 0x00,                                                           // AudioFormat (1 for PCM)
    0x01, 0x00,                                                           // NumChannels (1 channel)
    sample_rate, sample_rate >> 8, sample_rate >> 16, sample_rate >> 24,  // SampleRate
    byte_rate, byte_rate >> 8, byte_rate >> 16, byte_rate >> 24,          // ByteRate
    0x02, 0x00,                                                           // BlockAlign
    0x10, 0x00,                                                           // BitsPerSample (16 bits)
    'd', 'a', 't', 'a',                                                   // Subchunk2ID
    wav_size, wav_size >> 8, wav_size >> 16, wav_size >> 24,              // Subchunk2Size
  };
  memcpy(wav_header, set_wav_header, sizeof(set_wav_header));
}

// Callback function for touch switch
void gotTouch1() {
  touch1detected = true;
}

// Camera Parameters for setup
void CameraParameters() {
  // Define camera parameters
  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;
  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 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
  }

  // 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;
  }
}

void setup() {
  // Start Serial Monitor, wait until port is ready
  Serial.begin(115200);
  while (!Serial)
    ;

  // I2S Setup and start
  I2S.setAllPins(-1, 42, 41, -1, -1);
  if (!I2S.begin(PDM_MONO_MODE, SAMPLE_RATE, SAMPLE_BITS)) {
    Serial.println("Failed to initialize I2S!");
    while (1)
      ;
  }

  // Attach touch switch to interrupt handler
  touchAttachInterrupt(T1, gotTouch1, threshold);

  // Define Camera Parameters and Initialize
  CameraParameters();

  // Camera is good, set status
  camera_status = true;
  Serial.println("Camera OK!");

  // Initialize the MicroSD card
  if (!SD.begin(21)) {
    Serial.println("Failed to mount MicroSD Card!");
    while (1)
      ;
  }

  // Determine what type of MicroSD card is mounted
  uint8_t cardType = SD.cardType();

  if (cardType == CARD_NONE) {
    Serial.println("No MicroSD card inserted!");
    return;
  }

  // Print card type
  Serial.print("MicroSD Card Type: ");
  if (cardType == CARD_MMC) {
    Serial.println("MMC");
  } else if (cardType == CARD_SD) {
    Serial.println("SDSC");
  } else if (cardType == CARD_SDHC) {
    Serial.println("SDHC");
  } else {
    Serial.println("UNKNOWN");
  }
  // MicroSD is good, set status
  sd_status = true;
}

void loop() {

  // Make sure the camera and MicroSD are ready
  if (camera_status && sd_status) {

    // See if the touch switch has been selected
    if (touch1detected) {
      // Take picture and record sound
      if (touchInterruptGetLastStatus(T1)) {
        Serial.println("Touched, take a picture");
        // Create image file name
        char imageFileName[32];
        sprintf(imageFileName, "/image%d.jpg", fileCount);

        // Take a picture
        photo_save(imageFileName);
        Serial.printf("Saving picture: %s\r\n", imageFileName);

        // Create audio file name
        Serial.print("Recording ");
        Serial.print(RECORD_TIME);
        Serial.println(" seconds of sound");
        char audioFileName[32];
        sprintf(audioFileName, "/image%d.wav", fileCount);

        // Record audio from microphone
        record_wav(audioFileName);
        Serial.printf("Saving sound: %s\r\n", audioFileName);

        // Increment file counter
        fileCount++;
      }
      // Reset the touch variable
      touch1detected = false;
    }
    delay(80);
  }
}

این کدی که نوشتیم شامل دو فایل camera_pins.h و camera_index.h هست. این دو فایل در طرح CameraWebServer هم موجود  بودن و اتصالات و قابلیت‌های دوربین رو مشخص می‌کردن.

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

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

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

خط 40 آستانه حساسیت سوییچ لمسی رو مشخص می‌کنه. عملکردش باید خوب باشه اما اگه در عملکرد سوییچ لمسی به مشکل خوردین می‌تونین تغییرش بدید.

سپس، چند تا تابع معرفی می‌کنیم:

  • photo_save : تصاویر رو در کارت میکرو SD ذخیره می‌کنه. باید نام فایل رو مشخص کنین.
  • writeFile : یک تصویر رو در کارت ایجاد می‌کنه. این تابع از photo_save فراخوان می‌شه.
  • record_wav : یک فایل WAV رو ذخیره می‌کنه و اون رو در کارت میکرو SD رایت می‌کنه. اینجا هم باید یک نام فایل تعیین کنین.
  • generate_wav_header : یک هدر WAV برای فایل صوتی ایجاد می‌کنه.
  • gotTouch1 : تابع فراخون سوییچ لمسی هست. هر وقت که سوییچ رو کسی لمس کنه این تابع فعال می‌شه.
  • CameraParameters : چند تا پارامتر دوربین رو تنظیم می‌کنه. از این تابع در Setup استفاده می‌شه.

در Setup ،serial monitor رو شروع می‌کنیم و ازش برای نظارت و بررسی فرایند ضبط صدا و تصویر استفاده می‌کنیم.

در مرحله بعدی، I2S رو برای میکروفون راه‌اندازی می‌کنیم.

بعد سوییچ لمسی interrup رو به interrupt handler gotTouch1 وصل می‌کنیم.

در خط بعد، تابعی که پارامترهای دوربین رو بارگذاری می‌کنه فراخوان می‌کنیم. اگر همه چیز به خوبی پیش رفت، وضعیت دوربین رو روی true تنظیم می‌کنیم.

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

وضعیت دوربین و کارت میکرو SD رو چک می‌کنیم و loop می‌زنیم. با فرض اینکه وضعیت دوربین و کارت میکرو SD درست هستن، متغیر touch1detected رو چک می‌کنیم که وضعیتش رو تابع callback مشخص می‌کنه.

اگر متغیر از قبل تنظیم شده بود، می‌تونیم شروع به کار کنیم. اول، یک image filename ایجاد می‌کنیم و با استفاده از متغیر شمارنده یک filename خاص ایجاد می‌کنیم. با استفاده از تابع photo_save عکس می‌گیریم و اون رو در کارت میکرو SD ذخیره می‌کنیم.

این کار رو برای صوتی هم انجام می‌دیم، یک filename ایجاد می‌کنیم و با استفاده از تابع record_wav اون رو در کارت میکرو SD ذخیره می‌کنیم.

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


دموی دوربین ضبط صدا

دشوارترین بخش این دمو نصب دوربین هست. دوربین برد XIAO ESP32S3 شناور هست و فقط به کابل کوتاهش وصله. ساختار ESP32-CAM هم به همین شکله اما محفظه MicroSD card بزرگتری داره و بیشتر افراد برای اینکه دوربین رو سر جای خودش نگه دارن از چسب دو طرفه استفاده می‌کنن. در برد Seeeduino هم می‌شه از این روش استفاده کرد اما این روش استاندارد نیست و باعث می‌شه کابل نواری خم بشه.

دموی دوربین ضبط صدا

بعد از نصب دوربین، حتماً باید ماژول دوربین رو به درستی قرار بدین و یک کارت میکرو SD با فرمت FAT-32 نصب کنین. سپس، نمونه کد رو رو بارگذاری کنین.

زاویه دوربین رو مشخص کنین و سوییچ لمسی رو لمس کنین. LED زرد شروع به فلش زدن می‌کنه و در serial monitor می‌تونین این فرایند رو مشاهده کنین. اول، فایل تصویر رایت می‌شه و بعد ضبط صوت 10 ثانیه‌ای شروع می‌شه. بعد از اینکه اتمام ضبط، یک فایل WAV در کارت میکرو SD ذخیره می‌شه.

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

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

بیشتر کامپیوترها اپلیکیشن‌هایی برای دیدن تصاویر و پخش فایل‌های WAV دارن. من فایل‌ها رو با ادیتور صوتی و متن‌باز Ocenaudio پخش کردم. به خاطر اینکه اسم تصاویر و فایل‌های صوتی یکسانه، Ocanaudio تصاویر رو به عنوان یک سری تصویر کوچک(thumbnail) برای فایل‌های صوتی نشون می‌ده.


ارتقای دوربین به مدل OV5640

این امکان رو داریم که دوربین 2MP برد XIAO ESPO32S3 Sense رو به مدل 5MP ارتقا بدیم. اینجوری حسگر بزرگ‌تری داریم که می‌تونه ویدئوی HD رو با 30fps پخش کنه و در نتیجه کیفیت تصاویر بهتر خواهد بود.

مشخصات ماژول دوربین OV5640

دوربین OV5640 محصول Omnivision نسخه ارتقایافته ماژول OV2640 هست که در برد Sense وجود داره. این ماژول یک حسگر 5 مگاپیکسل CameraChip داره و می‌تونه تصاویری در ابعاد 2592×1944 پیکسل ثبت کنه.

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

این دوربین یک موتور voice-coil هم داره تا بتونه لنزها رو برای اتوفوکس جابه‌جا کنه. هرچند که Seeed Studio این دوربین رو به عنوان یک دوربین اتوفوکس تبلغ می‌کنه اما هیچ اطلاعاتی در مورد استفاده از اون منتشر نکرده.


نصب دوربین OV5640

نصب این دوربین بسیار سادس، کافیه مراحل زیر رو دنبال کنید:

  • برد دوربین رو از برد اصلی XIAO Sense جدا کنین.

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

  • ماژول دوربین 2MP رو جدا کنین. این ماژول رو نگه دارین، می‌تونین ازش در پروژه‌های دیگه استفاده کنین.

  • کابل نواری ماژول جدید 5MP رو وارد کنین. حتماً قسمت رسانای کابل رو به پایین باشه و در کانکتور قرار داشته باشه.

  • «در» کانکتور رو ببندین.

دوربین نصب شد.


آزمایش دوربین ارتقایافته

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

در زمان اجرای CameraWebServer لازم نیست تغییری در تنظیمات ایجاد کنین چون خودش OV5640 رو تشخیص می‌ده. وقتی نمونه طرح رو اجرا می‌کنین و اونو در مرورگر وب مشاهده می‌کنین باید نام OV5640 رو در بالای نوار مرورگر ببینین. این نشون می‌ده که دوربین به درستی تشخیص داده شده.

یک مورد عجیبی که من متوجهش شدم اینه که محور افقی دوربین برعکس می‌شه و به همین دلیل همه چیز به صورت «تصویر آینه‌ای» هست. با استفاده از اسلایدر Horiz Mirror برد CameraWebServer می‌تونین این مورد رو اصلاح کنین.

دوربین ارتقایافته دو تا گرماگیر(heatsink) داره و بهتون توصیه می‌کنم از گرماگیر بزرگ‌تر که پشت ماژول هست استفاده کنین. اگر بخواین ویدئو پخش کنین، ماژول OV5640 خیلی داغ می‌شه.

هیت سینک ماژول دوربین OV5640


جمع‌بندی

سنس برد Seeeduino XIAO ESP32S3 قدرت زیادی داره و چیزی حدود 600 هزار تومن قیمت داره. اگر به دوربین، میکروفون و کارت SD نیاز نداشته باشین می‌تونین XIAO ESP32S3 رو با نصف این قیمت تهیه کنید که یکی از ارزان‌ترین بردهای ESP32S3 به حساب میاد.

برد Seeeduino XIAO ESP32S3

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

به طور کلی، این پکیج کوچک خیلی عالیه و نسبت به برد قدیمی ESP32-CAM مزایای بیشتری داره.

این مقاله چطور بود ؟
+1
4
+1
0
+1
1
مشاهده بیشتر

محمد حسنی

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

نوشته های مشابه

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

دکمه بازگشت به بالا