close

這程式為改編,記錄使用

ESP32 藍芽SERVER端的草稿,發送雷射測距的結果,利用藍芽傳送到另一個ESP32裝置

/*
    Video: https://www.youtube.com/watch?v=oCMOYS71NIU
    Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
    Ported to Arduino ESP32 by Evandro Copercini
    updated by chegewara

   Create a BLE server that, once we receive a connection, will send periodic notifications.
   The service advertises itself as: 4fafc201-1fb5-459e-8fcc-c5c9c331914b
   And has a characteristic of: beb5483e-36e1-4688-b7f5-ea07361b26a8

   The design of creating the BLE server is:
   1. Create a BLE Server
   2. Create a BLE Service
   3. Create a BLE Characteristic on the Service
   4. Create a BLE Descriptor on the characteristic
   5. Start the service.
   6. Start advertising.

   A connect hander associated with the server starts a background task that performs notification
   every couple of seconds.
*/
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <Wire.h>
#include <VL53L0X.h>//雷射測距感測器
VL53L0X sensor;//感測器命名為senser
///////////////////////////////////////////////////////////////////////////////////////////
BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;
bool oldDeviceConnected = false;
uint32_t value = 0;

////////////////////////  可以在下列網站生成一個專用的藍芽UUID /////////////////////////////////
// https://www.uuidgenerator.net/

/////////////////////// 定義裝置藍芽server的UUID ///////////////////////////////////////////
#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"

////////////////////// 定義字元特徵碼 /////////////////////////////////////////////////////////
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

////////////////////// 判斷目前server裝置能不能回傳值給client////////////////////////////////
//////設置布林變數deviceConnected,true表示可連線,false表示沒有連線//////////////////////////
class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
    };
    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
    }
};


void setup() {
  Serial.begin(115200);
  Wire.begin();  
  
  /////////////設定500毫秒偵測一次,如果設備啟動失敗,印出失敗//////////////////////////////
  sensor.setTimeout(500);
  if (!sensor.init())
  {
   Serial.println("Failed to detect and initialize sensor!");
   while (1) {}
  }
  //////////////////////設定TOF為持續執行狀態//////////////////////////////////////////
  sensor.startContinuous();
  
  //////////////// 啟動藍芽裝置 初始化名稱為ESP32,可在手機中搜尋///////////////////////////
  BLEDevice::init("ESP32");

  /////////////// 將藍芽裝置設置為server狀態/////////////////////////////////////////////
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  //////////////將server藍芽裝置的UUID設置為之前宣告的UUID////////////////////////////////
  BLEService *pService = pServer->createService(SERVICE_UUID);

  ///////////// Create a BLE Characteristic (NOTIFY)可發送訊息/////////////////////////
  pCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID,
                      BLECharacteristic::PROPERTY_READ   |
                      BLECharacteristic::PROPERTY_WRITE  |
                      BLECharacteristic::PROPERTY_NOTIFY |
                      BLECharacteristic::PROPERTY_INDICATE
                    );

  // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
  // Create a BLE Descriptor
  pCharacteristic->addDescriptor(new BLE2902());

  /////////////////////////////////啟動藍芽SERVER功能////////////////////////////////////////
  pService->start();

  //////////////////////////////開始對外廣播/////////////////////////////////////////
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->setScanResponse(false);
  pAdvertising->setMinPreferred(0x0);  // set value to 0x00 to not advertise this parameter
  BLEDevice::startAdvertising();
  Serial.println("Waiting a client connection to notify...");
}

void loop() {

  /////////////////////////////////////////////////////////////////////////
  //設定A值為測距數據
  int a=sensor.readRangeContinuousMillimeters();
  //設定最遠只能偵測到400mm
  if (a>400){a=400;}
  //轉換為CM
  a=a/10;
  //Serial.println(a);
  //if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); }  
  
 ////////////////////////// notify changed value 開始推送數值//////////////////////////////////////////////////
 //////(uint8_t*)定義一個指標,數值0-255 &a取出a的記憶體位置,與指標共用 4為值的size/////////////////////////////
    if (deviceConnected) {      
        pCharacteristic->setValue((uint8_t*)&a, 4);
        pCharacteristic->notify();//隊有連上server的client發布a的值
        delay(3); // bluetooth stack will go into congestion, if too many packets are sent, in 6 hours test i was able to go as low as 3ms
    }
    // disconnecting
    if (!deviceConnected && oldDeviceConnected) {
        delay(500); // give the bluetooth stack the chance to get things ready
        pServer->startAdvertising(); // restart advertising
        Serial.println("start advertising");
        oldDeviceConnected = deviceConnected;
    }
    // connecting
    if (deviceConnected && !oldDeviceConnected) {
        // do stuff here on connecting
        oldDeviceConnected = deviceConnected;
    }
}

 

ESP32 藍芽CLIENT端的草稿,接收雷射測距的結果,

#include "BLEDevice.h"
//#include <WebServer.h>
//#include <WiFi.h>

/*//////////////////////////wifi_connect/////////////////////////////////////////////////

//WiFiServer server(80);  //聲明伺服器對象
//WebSocketsServer webSocket();
//設定ESP32wifi的SSID
//const char *ssid = "AA";
//const char *password = "";
//int readBuff=12;
*/
//////////////////////////藍芽設定////////////////////////////////////////////////////////////////
///////////////定義想要連上藍芽SERVER的UUID,以及字元特徵,一定要和SERVER一樣才能連上////////////////////
static BLEUUID serviceUUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b");
// The characteristic of the remote service we are interested in.
static BLEUUID    charUUID("beb5483e-36e1-4688-b7f5-ea07361b26a8");

static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;
static BLEAdvertisedDevice* myDevice;

///////////////////////函式   接收連牙SERVER傳送過來的資料/////////////////////////////////////////////////////////////
static void notifyCallback(
  BLERemoteCharacteristic* pBLERemoteCharacteristic,
  //宣告pData指標,型別為uint8_t,須和SERVER一樣,pData為記憶體位置,裡面要放置為SERVER傳過來的值
  uint8_t* pData,
  size_t length,
  //判斷有沒有傳送值到本地  
  bool isNotify) {
   //上述 bool為TRUE,將值放置到pDatat記憶體位置
   //指派distance為測距結果(*pData 為pData記憶體位置裡面的資料)
   //取出pData記憶體位置裡面的資料,指派給distance
    int distance=*pData;
    Serial.println(distance);
}

class MyClientCallback : public BLEClientCallbacks {
  void onConnect(BLEClient* pclient) {
  }

  void onDisconnect(BLEClient* pclient) {
    connected = false;
    }
};
//////////////////////////////布林函式 判斷有沒有連上藍芽SERVER/////////////////////////////////////////////
bool connectToServer() {
        
    BLEClient*  pClient  = BLEDevice::createClient();    
    pClient->setClientCallbacks(new MyClientCallback());
    // Connect to the remove BLE Server.
    pClient->connect(myDevice);  // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
    
    // Obtain a reference to the service we are after in the remote BLE server.
    BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
    if (pRemoteService == nullptr) {
      pClient->disconnect();
      return false;
    }
    
    // Obtain a reference to the characteristic in the service of the remote BLE server.
    pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
    if (pRemoteCharacteristic == nullptr) {
      pClient->disconnect();
      return false;
    }
    
    // Read the value of the characteristic.
    if(pRemoteCharacteristic->canRead()) {
      std::string value = pRemoteCharacteristic->readValue();
         }

    if(pRemoteCharacteristic->canNotify())
      pRemoteCharacteristic->registerForNotify(notifyCallback);

    connected = true;
}
/**
 * Scan for BLE servers and find the first one that advertises the service we are looking for.
 */
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
 /**
   * Called for each advertising BLE server.
   */
  void onResult(BLEAdvertisedDevice advertisedDevice) {
    
    // We have found a device, let us now see if it contains the service we are looking for.
    if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {

      BLEDevice::getScan()->stop();
      myDevice = new BLEAdvertisedDevice(advertisedDevice);
      doConnect = true;
      doScan = true;

    } // Found our server
  } // onResult
}; // MyAdvertisedDeviceCallbacks


void setup() {
  Serial.begin(115200);
/*  /////////////////////////////////////wifi設定//////////////////////////////////////////////////////////

  WiFi.mode(WIFI_AP_STA);  //wifi模式 AP STA雙模
  WiFi.softAP(ssid);      //命名WIFIAP的SSID名稱
  //AP的預設IP為 192.168.4.1
  IPAddress myIP = WiFi.softAPIP(); 
  server.begin(22333);
 */ 
/////////////////////////////////////藍芽設定/////////////////////////////////////////////////////////
  //本地藍芽設備名稱,不想被搜尋就為空
  BLEDevice::init("");

  // Retrieve a Scanner and set the callback we want to use to be informed when we
  // have detected a new device.  Specify that we want active scanning and start the
  // scan to run for 5 seconds.
  BLEScan* pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setInterval(1349);
  pBLEScan->setWindow(449);
  pBLEScan->setActiveScan(true);
  pBLEScan->start(5, false);
} // End of setup.


// This is the Arduino main loop function.
void loop() {

  // If the flag "doConnect" is true then we have scanned for and found the desired
  // BLE Server with which we wish to connect.  Now we connect to it.  Once we are 
  // connected we set the connected flag to be true.
  if (doConnect == true) {
    if (connectToServer()) {
      Serial.println("We are now connected to the BLE Server.");
    } else {
      Serial.println("We have failed to connect to the server; there is nothin more we will do.");
    }
    doConnect = false;
  }

  // If we are connected to a peer BLE Server, update the characteristic each time we are reached
  // with the current time since boot.
  if (connected) {
      }else if(doScan){
    BLEDevice::getScan()->start(0);  // this is just eample to start scan after disconnect, most likely there is better way to do it in arduino
  }
  
  delay(1000); // Delay a second between loops.
}

 

 

arrow
arrow
    文章標籤
    esp32教學
    全站熱搜
    創作者介紹
    創作者 a15001500 的頭像
    a15001500

    麵包雜記

    a15001500 發表在 痞客邦 留言(1) 人氣()