آموزش Espآموزش ESP32آموزش اینترنت اشیا

تشخیص وجود دستگاه بلوثوثی BLE با ESP32

سنسورهای مجاورت را می‌توان به عنوان یکی از سنسور هایی توصیف کرد که یک جسم نزدیک را با کمک نور، میدان الکترومغناطیسی یا صدا تشخیص می‌دهند. به طور معمول، این نوع دستگاه‌ها برای تشخیص سوژه‌های نزدیک طراحی شده‌اند، و اغلب کاربرد عملی این سنسورها همین است. اما شرایطی وجود دارد که سوژه از حسگر فاصله زیادی دارد یا مسیر سوژه با مانعی مسدود شده است، در این نوع شرایط می‌توان از دستگاه‌های دارای BLE (بلوتوث کم انرژی) برای تشخیص نزدیکی جسم استفاده کرد. برد توسعه ESP32 دارای BLE داخلی است که ما در بسیاری از پروژه های دیگر از آن استفاده کرده ایم. اگر با BLE کاملاً تازه کار هستید، پروژه های گیرنده ESP32 BLE و سرور ESP32 BLE  را که قبلا ساخته ایم بررسی کنید. همچنین قبلاً یک Bluetooth iBeacon با استفاده از ESP32 ساخته‌ایم.

در این مقاله قصد دارم نحوه ساخت یک مجاورت سنج ساده BLE را با کمک ESP32 و آردوینو IDE به شما نشان دهم.

بلوتوث کم انرژی (BLE) چیست؟

بلوتوث کم انرژی (BLE)

BLE مخفف Bluetooth Low Energy است و در سال 2011 وارد زندگی روزمره ما شد. زیرا از آن سال به بعد هر تولیدکننده بزرگی شروع به تعبیه فناوری BLE در دستگاه های خود کرد. BLE یک فناوری ارتباط بی سیم کم مصرف است که برای بهینه تر شدن مصرف باتری توسعه یافته است و می توان از آن برای برقراری ارتباط بین دستگاه ها در فاصله کوتاه استفاده کرد. برخی از دستگاه‌هایی که هر روز استفاده می‌کنید دارای بلوتوث هستند مانند تلفن هوشمند، ساعت هوشمند، هدفون‌های بی‌سیم، اسپیکر های بی‌سیم، تجهیزات خانه هوشمند، و دیگر دستگاه های که بلوتوث در آن ها تعبیه‌شده و بیشتر برای برقراری ارتباط یا دریافت اطلاعات استفاده میشود.

BLE یک فناوری نسبتاً جدید است و پروتکل BLE توسط گروه Bluetooth Special Interest Group (SIG) با هدف اصلی به واقعیت پیوستن ساختن دستگاه‌های کم مصرف توسعه یافته است. اگرچه نام پروتکل جدید ساخته شده ثابت مانده اما پروتکل BLE جدید با پروتکل قبلی سازگار نیست، به این معنی که دستگاه های کلاسیک بلوتوث ما نمی توانند با دستگاه های BLE مبادله اطلاعات کنند، با وجود این نقاط ضعف، توسعه دهندگان را قادر می سازد تا انرژی بسیار کمی مصرف کنند و دستگاه‌های کارآمدی که می‌توانند ماه‌ها و حتی سال‌ها به وسیله باتری‌های کوچک سکه‌ای کار کنند را بسازند.

ارتباط BLE چگونه کار می کند؟

BLE از ساختار داده سلسله مراتبی برای ارسال و دریافت اطلاعات استفاده می کند. یک دستگاه BLE که به عنوان یک سرور عمل می کند، services  و characteristics هایش را انتشار می دهد که توسط کلاینت قابل شناسایی است و یک بار که تبادل اطلاعات موفقیت آمیز باشد، دستگاه های BLE می توانند به طور همزمان با یکدیگر ارتباط برقرار کنند. از نظر فنی، این بسته اطلاعات با هم به عنوان ویژگی های یک دستگاه BLE شناخته می شوند و با استفاده از پروفایل GATT (Generic Attributes) تعریف و پیاده سازی شده اند. در این پروفایل‌ها  services ، characteristics  و values ها را به ترتیب سلسله مراتبی داریم. services  شامل characteristics  و characteristics  حاوی values است، با خواندن characteristics می توان values و تغییرات values را در طول زمان فهمید.

ارتباط BLE چگونه کار می کند؟

characteristics  را می توان پردازش کرد تا اطلاعات خواندن یا نوشتن دستگاه را استخراج کرد. دستگاه های حاوی اجزای خواندنی می توانند اطلاعات را منتشر کنند و دستگاه هایی که حاوی ویژگی های نوشتن هستند می توانند داده ها را از یک کلاینت دریافت کنند.

پروفایل GATT که تحت آن services  وcharacteristics  تعریف می‌شوند، به عنوان یک شناسه منحصربه‌فرد جهانی (UUID) شناخته می‌شود. برخی ازservices  وcharacteristics   استاندارد وجود دارد که توسط شرکت SIG تعریف و رزرو شده است، اگر UUID یک دستگاه BLE را بخوانیم، فوراً می توانیم بگوییم که چه نوع دستگاهی است. (اطلاعات بیشتر در مورد این موضوع را میتوانید در اینترنت بیابید).

داده های BLE در بسته های بسیار کوچک ارسال و دریافت می شوند، یک بسته BLE در مجموع تنها 31 بایت است درحالی که یک بسته TCP حدود 60 بایت یا بیشتر می باشد. در نهایت، یک نکته مهم که باید به خاطر بسپارید این است که یک بسته BLE باید به درستی ساختار یافته باشد که بتواند به طور مداوم در هر دو سمت سرور و کلاینت، سریال‌سازی و غیرسریالی‌سازی شود.

سنسور مجاورت سنج بلوتوثی چگونه کار می کند؟

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

سنسور مجاورت سنج بلوتوثی چگونه کار می کند؟

سرورهای BLE به طور منظم سیگنال های شناسنده را پخش می کنند تا کلاینت ها بتوانند آن را جستجو کرده و به آن متصل شوند. این سیگنال شناسنده حاوی یک آدرس منحصر به فرد BLE MAC (Media Access Control) است که بسیار شبیه به یک آدرس MAC استفاده شده در Wi-Fi است، ماژول ESP32 ما دارای بلوتوث داخلی هست، ما به راحتی می توانیم برای تشخیص وجود یک دستگاه از قبل شناسایی شده این سیگنال پخش شده را شناسایی کرده و آن را با یک جدول حاوی دستگاه شناخته شده جستجو و مقایسه کنیم،. هنگامی که دستگاه تأیید شد، می‌توانیم یک چراغ را روشن کنیم و یا می‌توانیم از Adafruit IO برای راه‌اندازی اعلان در برنامه اندروید خود استفاده کنیم. ما همچنین پروژه هایی را قبلا با Adafruit IO ساخته ایم، اگر می خواهید Adafruit IO را پیاده سازی کنید، می توانید آنها را بررسی کنید.

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

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

همانطور که در تصویر بالا می بینید، الزامات زیادی برای این پروژه وجود ندارد، یک برد توسعه esp32 و یک دستگاه دارای BLE فعال، در اینجا من از MI Band خود استفاده می کنم، همین.

اگر در مورد این مطلب سوالی دارید در قسمت نظرات بپرسید

کد آردوینو برای تشخیص مجاورت BLE با ESP32

برای نشاندادن، کنترلر ESP32 خود را طوری برنامه ریزی می کنیم که ESP32 یک دستگاه دارای BLE شناخته شده را حس کند و زمانی که دستگاه شناخته شده به نزدیکی ESP32 ما نزدیک شود، LED آنبورد را روشن می کنیم. برنامه کامل برای انجام این کار را می توانید در پایین این صفحه بیابید. توضیح کد به شرح زیر است.

ما برنامه خود را با include کردن کتابخانه ها مورد نیاز و تعریف کردن متغیرها شروع می کنیم.

همانطور که ما از کلاس BLEScan استفاده می کنیم، باید کتابخانه BLEScan را به همراه سایر کتابخانه های BLE اضافه کنیم.

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>

در مرحله بعد، چند متغیر را تعریف خواهیم کرد، متغیر اول آرایه ای است که آدرس های BLE MAC شناخته شده خود را در آن ذخیره می کنیم. در مرحله بعد، مقدار آستانه را اعلام می کنیم که با رد شدن از این مقدار، اقدام مورد نظر آغاز می شود. در مرحله بعد، یک Boolean تعریف می کنیم که اگر دستگاه شناخته شده ای در آرایه ما با لیست دستگاه های اسکن شده مطابقت داشته باشد، روی true تنظیم می شود. سپس، متغیر دیگری را برای پاک کردن دستگاه‌های BLE که قبلاً اسکن شده‌اند، اعلام می‌کنیم، اگر این کار را انجام ندهیم، مشکلات حافظه پیش خواهد آمد. سپس، یک اشاره گر به کلاس BLEScan میسازیم.

String knownBLEAddresses[] = {"aa:bc:cc:dd:ee:ee", "54:2c:7b:87:71:a2"};
int RSSI_THRESHOLD = -55;
bool device_found;
int scanTime = 5; //In seconds
BLEScan* pBLEScan;

ما باید یک تابع call-back تعریف کنیم، ابتدا این تابع call back هر چند ثانیه یک بار فراخوانی می شود تا بررسی شود که آیا دستگاه های BLE جدیدی در دسترس هستند یا خیر. هنگامی که در تابع call-back قرار گرفتیم، اگر دستگاه BLE را پیدا کردیم، یک پرچم تنظیم می کنیم و حلقه را می شکنیم. در نهایت، ما اطلاعات دستگاه BLE را چاپ خواهیم کرد.

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice advertisedDevice) {
      for (int i = 0; i < (sizeof(knownBLEAddresses) / sizeof(knownBLEAddresses[0])); i++)
      {
        //Uncomment to Enable Debug Information
        //Serial.println("*************Start**************");
        //Serial.println(sizeof(knownBLEAddresses));
        //Serial.println(sizeof(knownBLEAddresses[0]));
        //Serial.println(sizeof(knownBLEAddresses)/sizeof(knownBLEAddresses[0]));
        //Serial.println(advertisedDevice.getAddress().toString().c_str());
        //Serial.println(knownBLEAddresses[i].c_str());
        //Serial.println("*************End**************");
        if (strcmp(advertisedDevice.getAddress().toString().c_str(), knownBLEAddresses[i].c_str()) == 0)
                        {
          device_found = true;
                          break;
                        }
        else
          device_found = false;
      }
      Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
    }
};

بعد ازآن قسمت تنظیمات است که پین LED را به عنوان خروجی اعلام می کنیم. همچنین، ما BLEDevice را با متد  BLEDevice::init مقداردهی اولیه می کنیم، پس از آن، یک شیء اسکن شده را از BLEDevice خود دریافت می کنیم، آدرس را در نشانگر pBLEScan قبلاً گفنه شده ذخیره می کنیم.

در مرحله بعد، ما تابع call-back را تنظیم می کنیم، این تابع call-back یک بار در چند ثانیه فراخوانی می شود تا بررسی شود آیا دستگاه جدیدی در دسترس است یا خیر، در مرحله بعد من از روش SetActiveScan برای تنظیم حالت غیرفعال استفاده می کنم زیرا اگر ما این قابلیت را فعال کنیم، دستگاه BLE نتایج بسیار دقیقی به ما می دهد. در نهایت متد setInterval و setWindow را برای تکمیل راه اندازی تنظیم میکنیم.

  Serial.begin(115200); //Enable UART on ESP32
  Serial.println("Scanning..."); // Print Scanning
  pinMode(LED_BUILTIN, OUTPUT); //
  BLEDevice::init("");
  pBLEScan = BLEDevice::getScan(); //create new scan
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); //Init Callback Function
  pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
  pBLEScan->setInterval(100); // set Scan interval
  pBLEScan->setWindow(99);  // less or equal setInterval value

در قسمت loop با استفاده از متد start دستگاه BLE را راه اندازی می کنیم. پارامتر scanTime تعیین می‌کند که دستگاه BLE چقدر زمان برای اسکن دستگاه‌های جدید نیاز دارد.

 BLEScanResults foundDevices = pBLEScan->start(scanTime, false);

و هنگامی که اسکن انجام شد، آن را در متغیری به نام foundDevices قرار می دهیم.

هنگامی که اسکن کامل شد، می‌توانیم تعداد دستگاه‌هایی را که اسکنر پیدا کرده است با استفاده از متد finded devices.getCount () دریافت کنیم و به راحتی آن را در یک حلقه for قرار می‌دهیم و هر دستگاه را یک به یک دریافت می‌کنیم تا مقادیر RSSI را دریافت کنیم. ما مقایسه می کنیم که آیا آن دستگاه با دستگاهی در لیست مطابقت داشت یا خیر، این کار را با استفاده از یک دستور if ساده انجام می دهیم. اگر دستگاه شناخته‌شده‌ای دریافت کنیم، LED آنبورد را روشن می‌کنیم تا نشان دهیم که دستگاه شناخته‌شده‌ای را در لیست خود پیدا کرده‌ایم. در غیر این صورت led را خاموش می کنیم.

for (int i = 0; i < foundDevices.getCount(); i++)
  {
    BLEAdvertisedDevice device = foundDevices.getDevice(i);
    int rssi = device.getRSSI();
    Serial.print("RSSI: ");
    Serial.println(rssi);
    if (rssi > RSSI_THRESHOLD && device_found == true)
      digitalWrite(LED_BUILTIN, HIGH);
    else
      digitalWrite(LED_BUILTIN, LOW);
  }

در نهایت، اطلاعات را با فراخوانی (کد زیر) پاک می کنیم.

clearResults() methode
pBLEScan->clearResults();   // delete results fromBLEScan buffer to release memory

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

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

موارد موجود در فایل : سورس کامل

1 (2 نفر)

برای دریافت مطالب جدید کانال تلگرام یا پیج اینستاگرام ما را دنبال کنید.

محمد رحیمی

محمد رحیمی هستم. سعی میکنم در آیرنکس مطالب مفید قرار بدهم. سوالات مربوط به این مطلب را در قسمت نظرات همین مطلب اعلام کنید. سعی میکنم در اسرع وقت به نظرات شما پاسخ بدهم.

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

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *