Page 1 of 1

ESP32作为BLE外设,使用iOS手机连接速度慢,容易断连,不稳定

Posted: Tue Nov 01, 2022 6:42 am
by alex_loveying
现象:ESP32作为BLE外设,使用iOS手机的nRF connect APP连接,连接速度很慢,且不稳定,有时5秒就连上,有时2分钟才能连上,且有时容易断连,不稳定。使用Android手机,随便下载了一个蓝牙调试的app,连接速度很快,1秒就连上了。
分析:初步怀疑是连接参数,iOS有自己规定的蓝牙连接参数,如果不符合,会发生这种情况。而我使用的是arduino IDE进行开发,只发现了BLEServer类下的updateConnParams()函数是设置连接参数的,但需要在连接成功后的回调中设置,试了不管用,而且我理解设置连接参数应该是在setup阶段就设置吧。。
求问各位大佬,如何解决?以下附上我的代码。

Code: Select all

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


uint8_t txValue = 0;                          // 后面需要发送的值
BLEServer *pServer = NULL;                    // BLEServer指针 pServer
BLECharacteristic *pTxCharacteristic = NULL;  // BLECharacteristic指针 pTxCharacteristic
bool deviceConnected = false;                 // 本次连接状态
bool oldDeviceConnected = false;              // 上次连接状态
const int relay = 2;                          // 定义继电器 IN 引脚连接的引脚。

// See the following for generating UUIDs: https://www.uuidgenerator.net/
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID_WRITE "12a59e0a-17cc-11ec-9621-0242ac130002"
#define CHARACTERISTIC_UUID_NOTIFY "12a5a148-17cc-11ec-9621-0242ac130002"


class MyServerCallbacks : public BLEServerCallbacks {
  void onConnect(BLEServer *pServer, esp_ble_gatts_cb_param_t *param) {
    // 	void			updateConnParams(esp_bd_addr_t remote_bda, uint16_t minInterval, uint16_t maxInterval, uint16_t latency, uint16_t timeout);
    // iOS BLE要求的连接参数
    // •Interval Max * (Slave Latency + 1) <= 2 s
    // •Interval Max >= 20 ms
    // •Interval Min + 20 ms <= Interval Max
    // •Slave Latency <= 4
    // •ConnSupervisionTimeout <= 6 s
    // •Interval Max * ( Slave Latency + 1) * 3 < ConnSupervisionTimeout
    uint16_t latency = 2;       // 潜伏期,单位:xx个数据包
    uint16_t maxInterval = 50;  // 最大连接间隔,单位:ms
    uint16_t minInterval = 20;  // 最小连接间隔,单位:ms
    uint16_t timeout = 3000;    // 超时时间,单位:ms
    // 设置连接参数
    // pServer->updateConnParams(param->connect.remote_bda, minInterval, maxInterval, latency, timeout);
    deviceConnected = true;
    Serial.println("onConnect");
  };

  void onDisconnect(BLEServer *pServer) {
    deviceConnected = false;
    // // 关闭服务
    // pService->stop();
    // 关闭广播
    // pServer->getAdvertising()->stop();
    Serial.println("onDisconnect");
  }
};

class MyCallbacks : public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic *pCharacteristic) {
    // 接收信息
    std::string signal = pCharacteristic->getValue();
    int switchValue = atoi(signal.c_str());
    // 1开 2关
    if (switchValue == 1) {
      digitalWrite(relay, HIGH);
      Serial.println("turn on");
    } else if (switchValue == 2) {
      digitalWrite(relay, LOW);
      Serial.println("turn off");
    } else {
      Serial.print("unknown signal...");
      Serial.println(switchValue);
    }
  }
};

void setup() {
  // 设置波特率
  Serial.begin(115200);
  // 将继电器定义为输出。
  pinMode(relay, OUTPUT);
  setupBLE("ESP32-BLE");  //设置蓝牙名称
}

void setupBLE(String BLEName) {
  // 将传入的BLE的名字转换为指针
  const char *ble_name = BLEName.c_str();
  // 初始化一个蓝牙设备
  BLEDevice::init(ble_name);

  // 创建一个蓝牙服务器
  BLEServer *pServer = BLEDevice::createServer();
  // 服务器回调函数设置为MyServerCallbacks
  pServer->setCallbacks(new MyServerCallbacks());

  // 创建一个BLE服务
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // 创建一个NOTIFY特征 通知特征
  pTxCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_NOTIFY, BLECharacteristic::PROPERTY_NOTIFY);
  // 为特征添加一个描述
  pTxCharacteristic->addDescriptor(new BLE2902());

  // 创建一个WRITE特征 写入特征
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_WRITE, BLECharacteristic::PROPERTY_WRITE);
  // 为特征添加一个回调
  pCharacteristic->setCallbacks(new MyCallbacks());

  // 开启服务
  pService->start();
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);   //设置服务UUID
  pAdvertising->setScanResponse(true);   //开启扫描响应(?)
  pAdvertising->setMinPreferred(0x06);  // 解决ipone手机连接问题,functions that help with iPhone connections issue
  pAdvertising->setMinPreferred(0x12);
  // 服务器开始广播
  BLEDevice::startAdvertising();   //开始广播
  Serial.println("Waiting a client connection to notify...");
}

void loop() {
  // // deviceConnected 已连接
  // if (deviceConnected) {
  //   pTxCharacteristic->setValue(&txValue, 1);  // 设置要发送的值为1
  //   pTxCharacteristic->notify();               // 广播
  //   txValue++;                                 // 指针数值自加1
  //   delay(5000);                               // 如果有太多包要发送,蓝牙会堵塞
  //   Serial.print("deviceConnected txValue = ");
  //   Serial.println(txValue);
  // }

  // disconnecting  断开连接
  if (!deviceConnected && oldDeviceConnected) {
    delay(500);  // 留时间给蓝牙缓冲
    pServer->startAdvertising();  // 重新广播
    // 服务器开始广播
    // pServer->getAdvertising()->start();
    Serial.println("startAdvertising");
    oldDeviceConnected = deviceConnected;
  }

  // connecting  正在连接
  if (deviceConnected && !oldDeviceConnected) {
    // do stuff here on connecting
    oldDeviceConnected = deviceConnected;
    Serial.println("connecting");
  }
}