You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESP32发射BLE iBeacon信号异常:无法被识别为iBeacon

ESP32发射BLE iBeacon信号无法被识别的问题排查

问题背景

使用**ESP32 Wroom32 DevKit V1/ESP32-D0WD-V3(v3.0版本)**开发板,搭配Arduino IDE(板管理器版本V2.0.7),尝试发射BLE iBeacon信号时出现异常:

  • 设备可正常发出蓝牙信号,但无法被识别为iBeacon信号
  • 全新裸板有时会出现晶振频率警告:WARNING: Detected crystal freq 41.01MHz is quite different to normalized freq 40MHz. Unsupported crystal in use? Crystal is 40MHz
  • 使用默认ESP32 iBeacon Arduino示例代码(如下),上传和串口输出均正常,但nRF Connect应用仅将设备识别为普通蓝牙设备,无iBeacon属性:

nRF Connect识别为普通蓝牙设备

所用代码

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

#define DEVICE_NAME            "ESP32"
#define SERVICE_UUID           "7A0247E7-8E88-409B-A959-AB5092DDB03E"
#define BEACON_UUID            "2D7A9F0C-E0E8-4CC9-A71B-A21DB2D034A1"
#define BEACON_UUID_REV        "A134D0B2-1DA2-1BA7-C94C-E8E00C9F7A2D"
#define CHARACTERISTIC_UUID    "82258BAA-DF72-47E8-99BC-B73D7ECD08A5"

BLEServer *pServer;
BLECharacteristic *pCharacteristic;
bool deviceConnected = false;
uint8_t value = 0;

class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
      Serial.println("deviceConnected = true");
    };

    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
      Serial.println("deviceConnected = false");

      // Restart advertising to be visible and connectable again
      BLEAdvertising* pAdvertising;
      pAdvertising = pServer->getAdvertising();
      pAdvertising->start();
      Serial.println("iBeacon advertising restarted");
    }
};

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string rxValue = pCharacteristic->getValue();

      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 init_service() {
  BLEAdvertising* pAdvertising;
  pAdvertising = pServer->getAdvertising();
  pAdvertising->stop();

  // Create the BLE Service
  BLEService *pService = pServer->createService(BLEUUID(SERVICE_UUID));

  // Create a BLE Characteristic
  pCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID,
                      BLECharacteristic::PROPERTY_READ   |
                      BLECharacteristic::PROPERTY_WRITE  |
                      BLECharacteristic::PROPERTY_NOTIFY
                    );
  pCharacteristic->setCallbacks(new MyCallbacks());
  pCharacteristic->addDescriptor(new BLE2902());

  pAdvertising->addServiceUUID(BLEUUID(SERVICE_UUID));

  // Start the service
  pService->start();

  pAdvertising->start();
}

void init_beacon() {
  BLEAdvertising* pAdvertising;
  pAdvertising = pServer->getAdvertising();
  pAdvertising->stop();
  // iBeacon
  BLEBeacon myBeacon;
  myBeacon.setManufacturerId(0x4c00);
  myBeacon.setMajor(5);
  myBeacon.setMinor(88);
  myBeacon.setSignalPower(0xc5);
  myBeacon.setProximityUUID(BLEUUID(BEACON_UUID_REV));

  BLEAdvertisementData advertisementData;
  advertisementData.setFlags(0x1A);
  advertisementData.setManufacturerData(myBeacon.getData());
  pAdvertising->setAdvertisementData(advertisementData);

  pAdvertising->start();
}

void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.println("Initializing...");
  Serial.flush();

  BLEDevice::init(DEVICE_NAME);
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  init_service();
  init_beacon();

  Serial.println("iBeacon + service defined and advertising!");
}

void loop() {
  if (deviceConnected) {
    Serial.printf("*** NOTIFY: %d ***\n", value);
    pCharacteristic->setValue(&value, 1);
    pCharacteristic->notify();
    value++;
  }
  delay(2000);
}

问题排查与解决建议

1. 广播数据被覆盖(核心问题)

代码中先调用init_service()启动了带服务UUID的广播,之后调用init_beacon()设置iBeacon广播,但ESP32的BLE广播配置会被最后一次调用覆盖,且init_service()中添加的服务UUID会破坏iBeacon的标准广播格式——iBeacon要求主广播包仅包含苹果0x4C00厂商ID的制造商特定数据,不能混入服务UUID、设备名称等内容。

修复方法:

  • 删除init_service()中的pAdvertising->addServiceUUID(BLEUUID(SERVICE_UUID));语句
  • 调整初始化逻辑,将服务信息放在扫描响应包中,主广播包仅保留iBeacon数据(示例见下文修正代码)

2. UUID字节序问题

你定义了反转后的BEACON_UUID_REV,但BLEBeacon的setProximityUUID默认接受标准大端序UUID,尝试直接使用原始的BEACON_UUID替换BEACON_UUID_REV,验证是否能被识别。

3. 晶振频率警告处理

该警告一般不会直接导致iBeacon无法识别,但可能影响BLE稳定性。解决方法:

  • 在Arduino IDE的工具 > 晶振频率中选择40MHz
  • 若无效,在代码开头添加宏定义强制指定晶振参数:
#define CONFIG_ESP32_XTAL_FREQ 40

4. 断开重连后的广播恢复

onDisconnect回调中重启广播时,使用的是之前的配置,可能不是iBeacon格式。需在回调中重新设置iBeacon广播数据,或确保初始化时的广播配置为最终iBeacon格式。

修正后的核心代码示例

合并初始化逻辑,将服务信息放入扫描响应包,主广播仅保留iBeacon数据:

void init_beacon_and_service() {
  BLEAdvertising* pAdvertising = pServer->getAdvertising();
  pAdvertising->stop();

  // 初始化BLE服务
  BLEService *pService = pServer->createService(BLEUUID(SERVICE_UUID));
  pCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID,
                      BLECharacteristic::PROPERTY_READ   |
                      BLECharacteristic::PROPERTY_WRITE  |
                      BLECharacteristic::PROPERTY_NOTIFY
                    );
  pCharacteristic->setCallbacks(new MyCallbacks());
  pCharacteristic->addDescriptor(new BLE2902());
  pService->start();

  // 配置iBeacon主广播包
  BLEBeacon myBeacon;
  myBeacon.setManufacturerId(0x4c00);
  myBeacon.setMajor(5);
  myBeacon.setMinor(88);
  myBeacon.setSignalPower(0xc5);
  myBeacon.setProximityUUID(BLEUUID(BEACON_UUID)); // 使用原始UUID

  BLEAdvertisementData advertisementData;
  advertisementData.setFlags(0x1A);
  advertisementData.setManufacturerData(myBeacon.getData());
  pAdvertising->setAdvertisementData(advertisementData);

  // 配置扫描响应包,携带服务UUID和设备名称
  BLEAdvertisementData scanResponseData;
  scanResponseData.setName(DEVICE_NAME);
  scanResponseData.addServiceUUID(BLEUUID(SERVICE_UUID));
  pAdvertising->setScanResponseData(scanResponseData);

  pAdvertising->start();
}

// 修改setup函数,替换原有的init_service()和init_beacon()
void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.println("Initializing...");
  Serial.flush();

  BLEDevice::init(DEVICE_NAME);
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  init_beacon_and_service();

  Serial.println("iBeacon + service defined and advertising!");
}

内容的提问来源于stack exchange,提问作者shutteltje

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 17:18:22