ESP32 BLE Kullanımı

Merhaba,

Bu konuda ESP32 ile BLE(Bluetooth Low Energy) kullanarak veri iletimi yapacağız. Daha önceki konularda Arduino ve HM-10 Bluetooth modülü kullanarak BLE haberleşme gerçekleştirmiştik. Önceki konuya bağlantıdan ulaşabilirsiniz. Önceki konuda içerisinde BLE karakteristiklerinden ve çalışma mantığından biraz bahsetmiştik. Bu konuda BLE içeriğine biraz daha girmeyece çalışacağız.

BLE ile klasik Bluetooh arasında bazı farklar vardır. Bu farkların bazıları BLE için olumsuz gibi görünse de kullanım alanına göre BLE çok daha avantajlı konuma gelebilmektedir. Bu farkların başlıcaları şunlardır

Bluetooth 2Bluetooth LE
Daha fazla güç tüketimiDaha az güç tüketimi
3 Mbps’ e kadar veri hızı1 Mbps’ e kadar veri hızı
Daha yüksek gecikmeDaha düşük gecikme
Bağlanabilir slave sayısı 7Bağlanabilir slave sayısı sınırsız

BLE için tabloda verilen özelliklerinden bence en önemlileri daha az güç tüketimi ve sınırsız sayıda slave ile bağlantı kurulabilmesidir. Daha az güç tüketimi günümüzde yaygınlaşan düşük batarya ile uzun süreli çalışan cihazlar ile kullanımına büyük avantaj sağlamaktadır. Bağlanabilir slave sayısının sınırsız olması ise Mesh ağlar gibi topolojileri desteklemesine imkan sağlamaktadır.

BLE’ nin Broadcasting (yayın yapma) teknolojisini desteklemesi, Mesh network gibi topolojilerin de kullanılabilmesine imkan sağlamaktadır. Ayrıca BLE kullanarak göndermek istediğiniz verinin değiştiğini “Notify” özelliği sayesinde karşıya bildirebilirsiniz. Böylece alıcı cihaz, güncel veriyi tekrar okuyabilir.

Şimdik BLE yapısından biraz bahsedelim. BLE yapı olarak klasik Bluetooh’ dan biraz daha karmaşıktır. İçerdiği hiyerarşik yapıda önemli olan iki kategori vardır. Bunlardan bir tanesi Genel Erişim Profili (Generic Access Profile, GAP) ve diğeri Genel Özellik Profili (General Attribute Profile, GATT)’ dir. GATT tanımlanan kurallara göre verinin nasıl paketleneceği, formatlanacağı ve gönderileceğine odaklanır. BLE cihazının çevresi ile haberleşemebilmesi için 2 yöntem vardır. Bunlar bağlantı (Connecting) ve yayın yapma (Broadcasting) yöntemleridir. Bu yöntemler GAP yönergelerince oluşturulur. Cihazlar birbiri ile GAP tanımlarını kullanarak iletişimi geçerler.

Broadcasting ile veri iletimi yapılırken cihazların birbirine bağlanması gerekmez. BLE cihazlar bu modda çalışırken iki durumda olabilir. Yayın yapan (Broadcaster) ya da yayını alan (Observer). Bir cihaz yayın yaparken diğer cihazlar onu dinleyerek veri iletimi gerçekleştirilebilir.

Connecting ile veri iletimi yapılırken, adından da anlaşılacağı gibi cihazların birbirine bağlanması gerekir. Cihazlar connection modunda iki durumda olabilir. Bu modlar Peripheral ve Central olarak isimlendirilirler. Central cihaz, bilgisayar gibi bir cihazdır ve diğer Peripheral’ lara bağlanarak veri iletimi gerçekleştirebilir. Peripheral cihaz çevre cihazıdır ve genellikle veri iletimi yapıp sonra uyku durumuna geçer. Connecting modda bağlantı bir kere sağlandığı zaman Central cihaz bağlantı parametrelerini güncelleyebilir. Peripheral ya da Central cihaz bağlantıyı sonlandırabilir.

BLE hakkında bir çok bilgiye Wikipedia başta olmak üzere farklı web sitelerinden ulaşılabilir. Ben bu bilgilerden kısa bir derleme yapmaya çalıştım. Yapacağımız uygulamada Connecting yöntemi ile haberleşme gerçekleştireceğiz. Ancak ESP32 ile BLE kullanılarak Mesh topolojileri de gerçekleştirilebilir.

Yapacağımız projeye gelecek olursak. Projede 3 adet LED ve bir potansiyometre kullanacağız. Potansiyometre değerini ESP32′ ye bağlanıp gerçek zamanlı görüntülerken aynı zamanda LED’ lerin yanıp sönme durumlarını BLE bağlantı üzerinden kontrol edebileceğiz. LED’ lerin yanıp sönme durumlarını kontrol ederken basit bir string paket formatı kullanacağız. Bu paketin yapısını şu şekilde belirledim.

<LED_NUM>|<STAT>?

Daha açıklayıcı olması açısından örnek verecek olursam 1|0? verisi gönderdiğimizde 1. LED’ i söndüreceğiz. Bu formata uygun olacak şekilde LED sayısı arttırılabilir. Ya da isterseniz farklı veri formatı oluşturarak da iletişimi sağlayabilirsiniz. Bağlanamak için kullanılacak yazılımı da siz tasarlayacaksanız Byte iletişim kullanmanızı öneririm. Çünkü Arduino tarafında byte olarak gelen veriler ile işlem yapmak daha kolaydır. Ben bu çalışmada bağlantı için hazır yazılım kullanacağım için string veri formatı kullanmak istedim.

Devre Tasarımı

BLE uygulaması için gerekli devre bağlantı şeması aşağıda verilmiştir. 3 LED herhangi dijital pine bağlanabilir. Ancak potansiyometre ADC pinine bağlanmalıdır.

Yazılım

BLE uygulaması için hazırlayacağımız yazılımda ana şablon olarakArduino IDE’ sinde BLE Notify yazılımını kullanacağız. Yazılımda bir servis UUID’ si iki adet de karaktersitik bulunacak. Servis, Bluetooth bağlantı noktasının UUID’ sini içerirken, Karakteristikler LED ve potansiyometre bilgilerine erişilebilmesi için karakteristikleri içerekecektir. Oluşturulan karakteristikler aşağıdaki gibidir.

#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID_LED "beb5483e-36e1-4688-b7f5-ea07361b26a8"
#define CHARACTERISTIC_UUID_ADC "5ed9c888-7bf7-11ed-a1eb-0242ac120002"

Daha sonrasında BLE cihaza isim verim bağlantı noktası oluşturmak için BLE server kurulumu yapalım. BLE server’ a yapılan bağlantıları ve bağlantı kesilmelerini görebilmek için oluşturduğumuz server sınıfına, callback gonksiyonları içeren bir sınıf bağladık. Bu sınıf BLEserverCallbacks sınfından gerekli fonksiyonları miras alarak çalışmaktadır. Biz sadece “onConnect” ve “onDisconnect” fonksiyonlarını bu aşamada kullanacağız.

  // BLE Device Name
  BLEDevice::init("My BLE ESP32");
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallback());  // set BLE server callbacks

Daha sonrasında karakteristikleri oluşturacağız. Daha önce de belirttiğimiz gibi iki adet karakteristiğe ihtiyacımız var. Bu karakteristiklerden LED için olandan ESP32′ ye veri gönderilirken, ADC için olandan veri okunacaktır. Bu sebeple LED karakteristiğine Callback, ADC karakteristiğine notify eklemeliyiz. Bu ayarları da aşağıdaki gibi gerçekleştirebiliriz. Öncelikle bir servis oluşturup karakteristikleri bu servise bağlayacağız.

// create BLE service
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // Create Service Characteristic for LED status
  pCharacteristicLED = pService->createCharacteristic(
    CHARACTERISTIC_UUID_LED,
    BLECharacteristic::PROPERTY_WRITE);
  pCharacteristicLED->setCallbacks(new MyCharacteristicsCallbacks());  // create LED characteristic callback funciton

  pCharacteristicADC = pService->createCharacteristic(
    CHARACTERISTIC_UUID_ADC,
    BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_INDICATE);

  // add notify spec for BLE device
  pCharacteristicADC->addDescriptor(new BLE2902());

  // start BLE service
  pService->start();

LED karakteristiğine yazma yetkisi verirken, ADC karakteristiğine read, notify ve indicate özelliği verdik. “notify” özelliği, bağlanan cihaza gönderilmek istenilen veri değiştiğinde bağlanan cihazı bilgilendirmek için kullanılır. Böylece her notify event’ i geldiğinde bağlanan cihaz okumak istediği verinin güncellendiğini bilir ve veriyi tekrar okur. “indicate” de aynı işlemi yapar. Notify kullanıldığında BLE cihazı herhangi bir cihazın notify edilip edilmediğini bilmezken, indicate özelliği kullanıldığına BLE cihazı bağlanan herhangi bir cihazın notify edildiğini bilir.

Son olarak da advertising işlemini başlatalım. Böylece ESP32 cihazımız BLE aygıtı olarak görünüt olacaktır.

  // create BLE advertising object
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);  // add service UUDI
  pAdvertising->setScanResponse(false);
  pAdvertising->setMinPreferred(0x0);  // set value to 0x00 to not advertise this parameter
  BLEDevice::startAdvertising();       // start BLE advertising

Ayarlama işlemleri bittikten sonra LED için gerekli olan karakteristik callback’ ini oluşturalım. LED’ karakteristiğini oluştururken sadece yazma özelliğine izin vermiştik. Bu sebeple “BLECharacteristicCallbacks” sıfınından sadece “onWrite” fonksiyonunu kullanmamız yeterlidir. Bu fonksiyon içerisinde yukarıda belirlediğimiz veri formatını ayıran bir yazılım koyarak LED’ lerin durumunun değişmesini sağlayabiliriz. Yazılım, gelen veride | ve ? karakterinin yerlerini bulup aralarında sayıları integer çevirme ve çevrilen değere göre LED yakıp söndürme işlemi gerçekleştirmektedir.

// BLE Characteristic Callbacks
class MyCharacteristicsCallbacks : public BLECharacteristicCallbacks {

  void onWrite(BLECharacteristic *pCharacteristics) {
    if (pCharacteristics == pCharacteristicLED) {

      std::string value = pCharacteristics->getValue();
      String ss = value.c_str();

      int indx1 = ss.indexOf("|");
      String str1 = ss.substring(0, indx1);
      int indx2 = ss.indexOf("?");
      String str2 = ss.substring(indx1 + 1, indx2);
      Serial.printf("Value: %s\n%s %s\n", ss, str1, str2);

      int val1 = str1.toInt();
      int val2 = str2.toInt();

      digitalWrite(led_arr[val1], val2);
    }
  }
};

Yukarıda BLE server kurulumunu yapmıştık. Bu BLE server ayarlamarında kullanılan callback da yazılıma bu şekilde eklenebilir. Daha önce de belirttiğimiz gibi sadece “onConnect” ve “onDisconnect” fonksiyonlarının kullanılması yeterlidir.

// BLE Class callbacks
class MyServerCallback : public BLEServerCallbacks {
  void onConnect(BLEServer *pServer) {
    deviceConnected = true;
    Serial.println("Device connected");
  }

  void onDisconnect(BLEServer *pServer) {
    deviceConnected = false;
    Serial.println("Device Disconnected");
    BLEDevice::startAdvertising();
  }
};

Son kısımda da loop içerisini hazırlayalım. Loop içerisinde basit olarak her 200 milisaniyede bir ADC değerini okuyup bağlanan bir cihaz olduğunda ona göndereceğiz. Bu işlemi de şu şekilde gerçekleştirebiliriz.

// read ADC value in every 200ms
  if (millis() - lastTime > 200) {
    adcVal = analogRead(pot_pin);  // read pot value with ADC

    // if BLE device connected set data to BLE characteristic and notify connected device
    if (deviceConnected) {
      pCharacteristicADC->setValue((uint8_t *)&adcVal, 2);

      pCharacteristicADC->notify();
    }

    lastTime = millis();
  }

Yazılımı yükledikten sonra ESP32′ ye bağlanmak için telefona herhangi bir BLE Android uygulaması yükleyip kullanabilirsiniz. Ben BLE Scanner kullanmayı tercih ettim. Aşağıdaki uygulama kullanılarak bağlantı yapıldıktan sonra görünen servisler verilmiştir. Kırmızı ile işaretli olan LED karakteristiği, yeşil ile işaretli olan ADC karakterisitiğidir. Yanlarındaki W R N ve I karakteristiklere verdiğimiz yetkilere göre beliren butonlardır. W, yazma butonu, R okuma butonu, N notify buyonu, I ise Indicate butonudur.

Uygulama kullanarak veri göndermeniz durumunda Seri monitörder aşağıdaki şekilde verileri görüntüleyebilirsiniz. Yazılımın tamamına bağlantıdan ulaşabilirsiniz.

Add a Comment

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir