714|2

328

帖子

5

TA的资源

纯净的硅(中级)

楼主
 

【Beetle ESP32 C6迷你开发板】双机通讯并实现蓝牙开关 [复制链接]

 

在之前的文章 【Beetle ESP32 C6迷你开发板】低功耗蓝牙(BLE)功能初步使用 中,已经实现了UART Service服务,在此基础上,使用两块Beetle ESP32 C6迷你开发板,就可以实现基于UART的双机通讯,并在此基础上,实现蓝牙开关的功能。

 

一、双机通讯

双机通讯,原则上,需要一个Server,一个Client。

其中,Server部分,直接使用之前文章中的即可。或者参考DFRobot Beetle ESP32 C6迷你开发板的WiKi文章:https://wiki.dfrobot.com.cn/_SKU_DFR1075_FireBeetle_2_Board_ESP32_C6_Advanced_Tutorial#target_2

Client部分,自动扫描周边的BLE设备,然后检查是否有符合要求的Service设备,如果有,则进行连接,然后进行后续的处理。

 

Server部分的代码如下:

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"  // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

uint8_t txValue = 0;
bool deviceConnected = false;
BLECharacteristic *pTxCharacteristic;


//蓝牙连接/断开处理。当有连接/断开事件发生时自动触发
class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {   //当蓝牙连接时会执行该函数
      Serial.println("蓝牙已连接");
      deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {  //当蓝牙断开连接时会执行该函数
        Serial.println("蓝牙已断开");
        deviceConnected = false;
        delay(500); // give the bluetooth stack the chance to get things ready
        BLEDevice::startAdvertising(); // restart advertising
    }
};
/****************数据接收部分*************/
/****************************************/
//蓝牙接收数据处理。当收到数据时自动触发
class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string rxValue = pCharacteristic->getValue();  //使用rxValue接收数据

      if (rxValue.length() > 0) {
        Serial.println("*********");
        Serial.print("Received Value: ");
        for (int i = 0; i < rxValue.length(); i++)
              Serial.print(rxValue[i]);    //将接收的数据打印出来

        Serial.println();
        Serial.println("*********");
      }
    }
};
/****************************************/
/****************************************/

void setup() {
  Serial.begin(115200);
  Serial.println("Starting BLE work!");
  bleBegin();
}

/****************数据发送部分*************/
/****************************************/
void loop() {
  if(deviceConnected){  //当有设备连接时发送数据
    pTxCharacteristic->setValue("我是从机");
    pTxCharacteristic->notify();

  }
  /****************************************/
  /****************************************/
  delay(1000);
}


void bleBegin()
{
  BLEDevice::init(/*BLE名称*/"ESP32-C6 BLE Server");
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());
  BLEService *pService = pServer->createService(SERVICE_UUID);
  BLECharacteristic *pRxCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID_RX,
                                         BLECharacteristic::PROPERTY_WRITE 
                                       );
  pRxCharacteristic->setCallbacks(new MyCallbacks()); 

 pTxCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID_TX,
                                         BLECharacteristic::PROPERTY_NOTIFY
                                       );
 pTxCharacteristic->addDescriptor(new BLE2902());

  pService->start();
  // BLEAdvertising *pAdvertising = pServer->getAdvertising();  // this still is working for backward compatibility
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->setScanResponse(true);
  pAdvertising->setMinPreferred(0x06);  // functions that help with iPhone connections issue
  pAdvertising->setMinPreferred(0x12);
  BLEDevice::startAdvertising();

  }

 

Client部分的代码如下:

#include "BLEDevice.h"


#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"  // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

static BLEUUID serviceUUID(SERVICE_UUID);
static BLEUUID    charTXUUID(CHARACTERISTIC_UUID_RX);
static BLEUUID    charRXUUID(CHARACTERISTIC_UUID_TX);


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


/****************数据接收部分*************/
/****************************************/
//蓝牙接收数据处理,当收到数据时自动触发
static void notifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify) {  //传入uint8_t* pData用于存放数据
    String BLEData = "";
    for(int i = 0; i < length; i++)  //
      BLEData += (char)pData[i];
    Serial.println("*********");
    Serial.print("Received Value: ");
    Serial.println(BLEData);
    Serial.println("*********");
}
/****************************************/
/****************************************/

//蓝牙连接/断开处理。当有连接/断开事件发生时自动触发
class MyClientCallback : public BLEClientCallbacks {
  void onConnect(BLEClient* pclient) {
  }

  void onDisconnect(BLEClient* pclient) {
    connected = false;
    Serial.println("onDisconnect");
  }
};


/**
 * 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) {
    //Serial.print("BLE Advertised Device found: ");
    //Serial.println(advertisedDevice.toString().c_str());

    // 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);
  Serial.println("Starting Arduino BLE Client application...");
  bleBegin();

}

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 (connected) {  //当连接到蓝牙从机时发送数据
    pTXRemoteCharacteristic->writeValue("我是主机");
  }
  if(!connected){  //当没有连接到蓝牙从机时重新扫描
    BLEDevice::getScan()->start(5,false);  // this is just example to start scan after disconnect, most likely there is better way to do it in arduino
  }
/****************************************/
/****************************************/
  delay(1000); 
}


void bleBegin()
{
  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);//扫描时间,单位秒
  }


//蓝牙连接处理
bool connectToServer() {
    Serial.print("Forming a connection to ");
    Serial.println(myDevice->getAddress().toString().c_str());

    BLEClient*  pClient  = BLEDevice::createClient();
    Serial.println(" - Created client");

    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)
    Serial.println(" - Connected to server");
    pClient->setMTU(517); //set client to request maximum MTU from server (default is 23 otherwise)

    // Obtain a reference to the service we are after in the remote BLE server.
    BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
    if (pRemoteService == nullptr) {
      Serial.print("Failed to find our service UUID: ");
      Serial.println(serviceUUID.toString().c_str());
      pClient->disconnect();
      return false;
    }
    Serial.println(" - Found our service");


    // Obtain a reference to the characteristic in the service of the remote BLE server.
    pTXRemoteCharacteristic = pRemoteService->getCharacteristic(charTXUUID);
    if (pTXRemoteCharacteristic == nullptr) {
      Serial.print("Failed to find our characteristic UUID: ");
      Serial.println(charTXUUID.toString().c_str());
      pClient->disconnect();
      return false;
    }
    pRXRemoteCharacteristic = pRemoteService->getCharacteristic(charRXUUID);
    if (pRXRemoteCharacteristic == nullptr) {
      Serial.print("Failed to find our characteristic UUID: ");
      Serial.println(charRXUUID.toString().c_str());
      pClient->disconnect();
      return false;
    }
    Serial.println(" - Found our characteristic");

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

    connected = true;
    return true;
}

在Client部分的connectToServer()中,连接到 SERVICE_UUID 设定的BLE服务上,然后在通过RX、TX对应的Characteristic,来收发消息。

 

将上述代码,分别烧录到两个ESP32-C6开发板以后,从串口监听可以收到如下的消息:

 

二、基于双机通讯的蓝牙开关

在双机通讯的基础上,在要做为开关的一端,添加按键的处理,然后发送控制LED的信息到受控的一端,而受控一端收到消息后,根据消息的具体情况来控制LED的亮灭即可。

 

处理按键部分,可以使用中断来实现,涉及到的代码如下:

#define BUTTON 9 //设置引脚9为按键的引脚


    pinMode(BUTTON, INPUT_PULLUP); //设置BUTTON引脚为外部中断引脚
    attachInterrupt(BUTTON, PinIntEvent, RISING);

void PinIntEvent()
{
    Serial.printf("PinInt Event.\r\n");
}

在上,有一个按键D9/IO9,可以用作BOOT,也可以在启动后,做为用户按键:

 

在上面的按键中断代码中,就使用了这个按键,一旦按键后,就会调用设置好的中断PinIntEvent(),在PinIntEvent()中,可以添加对应的调用代码:

void PinIntEvent()
{
    Serial.printf("PinInt Event.\r\n");
    if(millis() - lastInterrupt > 300) // we set a 10ms no-interrupts window
    {
      if(deviceConnected){  //当有设备连接时发送数据
        ledStatus = !ledStatus;
        lastInterrupt = millis();
        for (;;) {
          if (shared_var_mutex != NULL) {
            if (xSemaphoreTake(shared_var_mutex, portMAX_DELAY) == pdTRUE) {
                if(ledStatus) {
                  Serial.println("控制开灯");
                  digitalWrite(LED, HIGH);
                } else {
                  Serial.println("控制关灯");
                  digitalWrite(LED, LOW);
                }
                hasMsg = true;
                xSemaphoreGive(shared_var_mutex);
                break;
              }
            }
        }
      }
    }
}

在主循环,添加发送消息的代码即可:

void loop() {
  if(deviceConnected){  //当有设备连接时发送数据
    if(hasMsg) {
      hasMsg = false;
      pTxCharacteristic->setValue("我是主机");
      pTxCharacteristic->notify();

      if(ledStatus) {
        pTxCharacteristic->setValue("ON");
        pTxCharacteristic->notify();
      } else {
        pTxCharacteristic->setValue("OFF");
        pTxCharacteristic->notify();
      }
    }
  }
  /****************************************/
  /****************************************/
  // delay(1000);
}

 

在受控端,收到消息后,根据消息的具体内容,控制LED,对应代码如下:

//蓝牙接收数据处理,当收到数据时自动触发
static void notifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify) {  //传入uint8_t* pData用于存放数据
    String BLEData = "";
    for(int i = 0; i < length; i++)  //
      BLEData += (char)pData[i];
    Serial.println("*********");
    Serial.print("Received Value: ");
    Serial.println(BLEData);
    Serial.println("*********");

    if(BLEData == "ON"){
      Serial.println("开灯");
      digitalWrite(LED, HIGH);
      hasMsg = true;
    }  //判断接收的字符是否为"ON"

    if(BLEData == "OFF"){
      Serial.println("关灯");
      digitalWrite(LED, LOW);
      hasMsg = true;
    }  //判断接收的字符是否为"OFF"
}

 

通过以上的处理后,控制端和受控端,就能够通过BLE UART服务来发送控制信息,控制LED了。

 

最终,具体的代码如下:

Server代码:

/*
    Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleServer.cpp
    Ported to Arduino ESP32 by Evandro Copercini
    updates by chegewara
*/

#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"  // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

#define LED 15 //设置引脚15为LED引脚
#define BUTTON 9 //设置引脚9为按键的引脚

uint8_t txValue = 0;
bool deviceConnected = false;
BLECharacteristic *pTxCharacteristic;

SemaphoreHandle_t shared_var_mutex = NULL;
bool ledStatus = false;
unsigned long lastInterrupt = 0;
bool hasMsg = false;

// 定义外部中断的Mode
// 0: 无中断,读取Touch值
// 1:Touch中断,执行 TouchEvent()
// 2: 外部IO的中断
#define EXT_ISR_MODE 2

void TouchEvent()
{
    Serial.printf("Touch Event.\r\n");
}
 
void PinIntEvent()
{
    Serial.printf("PinInt Event.\r\n");
    if(millis() - lastInterrupt > 300) // we set a 10ms no-interrupts window
    {
      if(deviceConnected){  //当有设备连接时发送数据
        ledStatus = !ledStatus;
        lastInterrupt = millis();
        for (;;) {
          if (shared_var_mutex != NULL) {
            if (xSemaphoreTake(shared_var_mutex, portMAX_DELAY) == pdTRUE) {
                if(ledStatus) {
                  Serial.println("控制开灯");
                  digitalWrite(LED, HIGH);
                } else {
                  Serial.println("控制关灯");
                  digitalWrite(LED, LOW);
                }
                hasMsg = true;
                xSemaphoreGive(shared_var_mutex);
                break;
              }
            }
        }
      }
    }
}

//蓝牙连接/断开处理。当有连接/断开事件发生时自动触发
class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {   //当蓝牙连接时会执行该函数
      Serial.println("蓝牙已连接");
      deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {  //当蓝牙断开连接时会执行该函数
        Serial.println("蓝牙已断开");
        deviceConnected = false;
        delay(500); // give the bluetooth stack the chance to get things ready
        BLEDevice::startAdvertising(); // restart advertising
    }
};
/****************数据接收部分*************/
/****************************************/
//蓝牙接收数据处理。当收到数据时自动触发
class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      String rxValue = pCharacteristic->getValue();  //使用rxValue接收数据

      //if(rxValue == "ON"){Serial.println("开灯");}   //判断接收的字符是否为"ON"

      if (rxValue.length() > 0) {
        Serial.println("*********");
        Serial.print("Received Value: ");
        for (int i = 0; i < rxValue.length(); i++)
              Serial.print(rxValue);    //将接收的数据打印出来

        Serial.println();
        Serial.println("*********");
      }
    }
};
/****************************************/
/****************************************/

void setup() {
  Serial.begin(115200);
  Serial.println("Starting BLE work!");
  bleBegin();

  pinMode(LED, OUTPUT);
  digitalWrite(LED, LOW);

  shared_var_mutex = xSemaphoreCreateMutex();  // Create the mutex

#if 1 == EXT_ISR_MODE   // 触摸中断
    // Pin: T0(GPIO4), 函数指针:TouchEvent, 阈值: 40
    // touchAttachInterrupt(7, TouchEvent, 40);
 
#elif 2 == EXT_ISR_MODE   // 下降沿触发 
    pinMode(BUTTON, INPUT_PULLUP); //设置BUTTON引脚为外部中断引脚
    attachInterrupt(BUTTON, PinIntEvent, RISING);
#endif
}

/****************数据发送部分*************/
/****************************************/
void loop() {
  if(deviceConnected){  //当有设备连接时发送数据
    // pTxCharacteristic->setValue("我是从机");
    // pTxCharacteristic->notify();

    // pTxCharacteristic->setValue("Hello Sever");
    // pTxCharacteristic->notify();

    // for (;;) {
    //   if (shared_var_mutex != NULL) {
    //     if (xSemaphoreTake(shared_var_mutex, portMAX_DELAY) == pdTRUE) {

    //       pTxCharacteristic->setValue("我是从机");
    //       pTxCharacteristic->notify();

    //         xSemaphoreGive(shared_var_mutex);
    //         break;
    //       }
    //     }
    // }

    // hasMsg = true;
    if(hasMsg) {
      hasMsg = false;
      pTxCharacteristic->setValue("我是主机");
      pTxCharacteristic->notify();

      if(ledStatus) {
        pTxCharacteristic->setValue("ON");
        pTxCharacteristic->notify();
      } else {
        pTxCharacteristic->setValue("OFF");
        pTxCharacteristic->notify();
      }
    }
  }
  /****************************************/
  /****************************************/
  // delay(1000);
}


void bleBegin()
{
  BLEDevice::init(/*BLE名称*/"Long name works now");
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());
  BLEService *pService = pServer->createService(SERVICE_UUID);
  BLECharacteristic *pRxCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID_RX,
                                         BLECharacteristic::PROPERTY_WRITE 
                                       );
  pRxCharacteristic->setCallbacks(new MyCallbacks()); 

 pTxCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID_TX,
                                         BLECharacteristic::PROPERTY_NOTIFY
                                       );
 pTxCharacteristic->addDescriptor(new BLE2902());

  pService->start();
  // BLEAdvertising *pAdvertising = pServer->getAdvertising();  // this still is working for backward compatibility
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->setScanResponse(true);
  pAdvertising->setMinPreferred(0x06);  // functions that help with iPhone connections issue
  pAdvertising->setMinPreferred(0x12);
  BLEDevice::startAdvertising();

  }

 

Client代码:


/**
 * A BLE client example that is rich in capabilities.
 * There is a lot new capabilities implemented.
 * author unknown
 * updated by chegewara
 */

#include "BLEDevice.h"
//#include "BLEScan.h"

#define LED 15 //设置引脚13为LED引脚

#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"  // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

// The remote service we wish to connect to.
static BLEUUID serviceUUID(SERVICE_UUID);
// The characteristic of the remote service we are interested in.
static BLEUUID    charTXUUID(CHARACTERISTIC_UUID_RX);

static BLEUUID    charRXUUID(CHARACTERISTIC_UUID_TX);

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

bool hasMsg = false;

/****************数据接收部分*************/
/****************************************/
//蓝牙接收数据处理,当收到数据时自动触发
static void notifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify) {  //传入uint8_t* pData用于存放数据
    String BLEData = "";
    for(int i = 0; i < length; i++)  //
      BLEData += (char)pData[i];
    Serial.println("*********");
    Serial.print("Received Value: ");
    Serial.println(BLEData);
    Serial.println("*********");

    if(BLEData == "ON"){
      Serial.println("开灯");
      digitalWrite(LED, HIGH);
      hasMsg = true;
    }  //判断接收的字符是否为"ON"

    if(BLEData == "OFF"){
      Serial.println("关灯");
      digitalWrite(LED, LOW);
      hasMsg = true;
    }  //判断接收的字符是否为"OFF"

    //Serial.print("Notify callback for characteristic ");
    //Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
    //Serial.print(" of data length ");
    //Serial.println(length);
}
/****************************************/
/****************************************/

//蓝牙连接/断开处理。当有连接/断开事件发生时自动触发
class MyClientCallback : public BLEClientCallbacks {
  void onConnect(BLEClient* pclient) {
  }

  void onDisconnect(BLEClient* pclient) {
    connected = false;
    Serial.println("onDisconnect");
  }
};


/**
 * 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) {
    //Serial.print("BLE Advertised Device found: ");
    //Serial.println(advertisedDevice.toString().c_str());

    // 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);
  Serial.println("Starting Arduino BLE Client application...");
  bleBegin();

  pinMode(LED, OUTPUT);
  digitalWrite(LED, LOW);
}

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 (connected) {  //当连接到蓝牙从机时发送数据
    // pTXRemoteCharacteristic->writeValue("我是从机");
    // hasMsg = true;
    if(hasMsg) {
      hasMsg = false;
      pTXRemoteCharacteristic->writeValue("我是从机");
      pTXRemoteCharacteristic->writeValue("OK");
    }
  }
  if(!connected){  //当没有连接到蓝牙从机时重新扫描
    BLEDevice::getScan()->start(5,false);  // this is just example to start scan after disconnect, most likely there is better way to do it in arduino
    delay(1000); 
  }
  delay(1000); 
/****************************************/
/****************************************/
}


void bleBegin()
{
  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);//扫描时间,单位秒
  }


//蓝牙连接处理
bool connectToServer() {
    Serial.print("Forming a connection to ");
    Serial.println(myDevice->getAddress().toString().c_str());

    BLEClient*  pClient  = BLEDevice::createClient();
    Serial.println(" - Created client");

    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)
    Serial.println(" - Connected to server");
    pClient->setMTU(517); //set client to request maximum MTU from server (default is 23 otherwise)

    // Obtain a reference to the service we are after in the remote BLE server.
    BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
    if (pRemoteService == nullptr) {
      Serial.print("Failed to find our service UUID: ");
      Serial.println(serviceUUID.toString().c_str());
      pClient->disconnect();
      return false;
    }
    Serial.println(" - Found our service");


    // Obtain a reference to the characteristic in the service of the remote BLE server.
    pTXRemoteCharacteristic = pRemoteService->getCharacteristic(charTXUUID);
    if (pTXRemoteCharacteristic == nullptr) {
      Serial.print("Failed to find our characteristic UUID: ");
      Serial.println(charTXUUID.toString().c_str());
      pClient->disconnect();
      return false;
    }
    pRXRemoteCharacteristic = pRemoteService->getCharacteristic(charRXUUID);
    if (pRXRemoteCharacteristic == nullptr) {
      Serial.print("Failed to find our characteristic UUID: ");
      Serial.println(charRXUUID.toString().c_str());
      pClient->disconnect();
      return false;
    }
    Serial.println(" - Found our characteristic");

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

    connected = true;
    return true;
}

将上述代码烧录到两块开发板,通过串口监听,可以查看对应的输出信息:

 在Server板上按BOOT按键 ,就会发送消息到Client板,进行LED的控制了。

 

 

 

最新回复

上电自动搜索连接的吗?   详情 回复 发表于 2024-5-20 14:33
点赞 关注
 
 

回复
举报

7196

帖子

2

TA的资源

版主

沙发
 

上电自动搜索连接的吗?

点评

那必须的  详情 回复 发表于 2024-5-20 23:29
 
 
 

回复

328

帖子

5

TA的资源

纯净的硅(中级)

板凳
 
wangerxian 发表于 2024-5-20 14:33 上电自动搜索连接的吗?

那必须的

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
推荐帖子
C程序中嵌入汇编新方法

由于C语言在定时方面的缺陷,在某些场合下,C程序中需要嵌入汇编代码,以弥补C的缺陷。通常,在C语言程序中嵌入汇编的方法,无外 ...

【EEWORLD模块整理】+步进电机

再来一个步进电机的驱动,我用的是这里的那个142驱动的。

关于cortex-M3中断优先级如何使用的解答

最近在帖子上看到有童鞋在问关于M3的优先级的问题,很多人都不太了解IntPriorityGroupingSet()和IntPrioritySet()的用户, ...

DO了一个逻辑分析仪,Show一下

最近在学AD画板子,做了一块逻辑分析仪,蛮好用,支持Logic,USBee Suite,USBee AX Pro,可以分析uart,spi,iic等协议,很实用哦。 ...

锂电池剩余电量SOC的估计方法介绍

本帖最后由 qwqwqw2088 于 2020-6-19 08:52 编辑 荷电状态又叫剩余电量,SOC,StateofCharge,是反应电池包内当前电量占总体 ...

基于Verilog的顺序状态逻辑FSM的设计与仿真.pdf

基于Verilog的顺序状态逻辑FSM的设计与仿真.pdf

【e络盟e选】快速下单晒单

1、在e络盟e选选了几样东东,虽然还有海外的部分,但是都极速到货 2、下单物料 652896 3、开箱晒图 652895 H ...

42“万里”树莓派小车——ROS学习(Android使用ROSBridge控制小乌龟)

本帖最后由 lb8820265 于 2022-11-8 23:14 编辑 前面通过网页使用ROSBridge控制小乌龟,这里介绍使用Android手机来控制小乌 ...

清华AI医院首批42位AI医生亮相,诊断覆盖300余种疾病

11月23日,人民日报健康客户端记者从清华大学获悉,清华大学智能产业研究院团队打造的首家“AI医院”Agent Hospital正 ...

【FRDM-MCXN947】UTICK定时器

测试N947内部的UTICK定时器,定时1MS中断。 一、UTICK内部框图 870274 二、程序部分 2.1、utick.c ...

关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表