ESP32 BLE外设无法被Android手机及Windows笔记本发现的技术求助
ESP32 MicroPython BLE外设无法被Android/Windows设备发现的解决办法
我在ESP32上使用MicroPython搭建BLE服务器,想要实现与中心设备(如智能手机或其他ESP32)的BLE通信,但ESP32无法被Android手机及Windows笔记本发现,以下是我使用的代码:
from machine import Pin from machine import Timer from time import sleep_ms import ubluetooth message = "" class ESP32_BLE(): def __init__(self, name): # Create internal objects for the onboard LED # blinking when no BLE device is connected # stable ON when connected self.led = Pin(2, Pin.OUT) self.timer1 = Timer(0) self.name = name self.ble = ubluetooth.BLE() self.ble.active(True) self.disconnected() self.ble.irq(self.ble_irq) self.register() self.advertiser() def connected(self): self.led.value(1) self.timer1.deinit() def disconnected(self): self.timer1.init(period=100, mode=Timer.PERIODIC, callback=lambda t: self.led.value(not self.led.value())) def ble_irq(self, event, data): global message if event == 1: #_IRQ_CENTRAL_CONNECT: # A central has connected to this peripheral self.connected() elif event == 2: #_IRQ_CENTRAL_DISCONNECT: # A central has disconnected from this peripheral. self.advertiser() self.disconnected() elif event == 3: #_IRQ_GATTS_WRITE: # A client has written to this characteristic or descriptor. buffer = self.ble.gatts_read(self.rx) message = buffer.decode('UTF-8').strip() print(message) def register(self): # Nordic UART Service (NUS) NUS_UUID = '6E400001-B5A3-F393-E0A9-E50E24DCCA9E' RX_UUID = '6E400002-B5A3-F393-E0A9-E50E24DCCA9E' TX_UUID = '6E400003-B5A3-F393-E0A9-E50E24DCCA9E' BLE_NUS = ubluetooth.UUID(NUS_UUID) BLE_RX = (ubluetooth.UUID(RX_UUID), ubluetooth.FLAG_WRITE) BLE_TX = (ubluetooth.UUID(TX_UUID), ubluetooth.FLAG_NOTIFY) BLE_UART = (BLE_NUS, (BLE_TX, BLE_RX,)) SERVICES = (BLE_UART, ) ((self.tx, self.rx,), ) = self.ble.gatts_register_services(SERVICES) def send(self, data): self.ble.gatts_notify(0, self.tx, data + '\n') def advertiser(self): name = bytes(self.name, 'UTF-8') adv_data = bytearray('\x02\x01\x02') + bytearray((len(name) + 1, 0x09)) + name self.ble.gap_advertise(100, adv_data) print(adv_data) print("\r\n") # adv_data # raw: 0x02010209094553503332424C45 # b'\x02\x01\x02\t\tESP32BLE' # # 0x02 - General discoverable mode # 0x01 - AD Type = 0x01 # 0x02 - value = 0x02 # https://jimmywongiot.com/2019/08/13/advertising-payload-format-on-ble/ # https://docs.silabs.com/bluetooth/latest/general/adv-and-scanning/bluetooth-adv-data-basics led = Pin(2, Pin.OUT) but = Pin(0, Pin.IN) ble = ESP32_BLE("ESP32") def buttons_irq(pin): led.value(not led.value()) ble.send('LED state will be toggled.') print('LED state will be toggled.') but.irq(trigger=Pin.IRQ_FALLING, handler=buttons_irq) while True: if message == "STATUS": message = "" print('LED is ON.' if led.value() else 'LED is OFF') ble.send('LED is ON.' if led.value() else 'LED is OFF') sleep_ms(100)
问题分析与修正方案
核心问题
- 广播模式配置错误:原代码中广播Flags设为
0x02(有限可发现模式),仅在短时间内可被扫描,导致大部分设备无法持续发现它。 - 引脚资源冲突:全局和类内重复初始化
Pin(2),可能导致LED控制异常。 - 广播间隔过小:100ms的广播间隔可能被部分系统过滤,降低设备被发现的概率。
修正后的代码
from machine import Pin from machine import Timer from time import sleep_ms import ubluetooth message = "" class ESP32_BLE(): def __init__(self, name): # 板载LED:未连接时闪烁,连接后常亮 self.led = Pin(2, Pin.OUT) self.timer1 = Timer(0) self.name = name self.ble = ubluetooth.BLE() # 确认BLE激活状态,便于排查初始化问题 ble_active = self.ble.active(True) print(f"BLE激活状态: {ble_active}") self.disconnected() self.ble.irq(self.ble_irq) self.register() self.advertiser() def connected(self): self.led.value(1) self.timer1.deinit() def disconnected(self): # 降低闪烁频率,减少资源占用 self.timer1.init(period=500, mode=Timer.PERIODIC, callback=lambda t: self.led.value(not self.led.value())) def ble_irq(self, event, data): global message if event == 1: #_IRQ_CENTRAL_CONNECT: self.connected() elif event == 2: #_IRQ_CENTRAL_DISCONNECT: self.disconnected() self.advertiser() elif event == 3: #_IRQ_GATTS_WRITE: buffer = self.ble.gatts_read(self.rx) message = buffer.decode('UTF-8').strip() print(message) def register(self): # Nordic UART Service (NUS) NUS_UUID = '6E400001-B5A3-F393-E0A9-E50E24DCCA9E' RX_UUID = '6E400002-B5A3-F393-E0A9-E50E24DCCA9E' TX_UUID = '6E400003-B5A3-F393-E0A9-E50E24DCCA9E' BLE_NUS = ubluetooth.UUID(NUS_UUID) BLE_RX = (ubluetooth.UUID(RX_UUID), ubluetooth.FLAG_WRITE) BLE_TX = (ubluetooth.UUID(TX_UUID), ubluetooth.FLAG_NOTIFY) BLE_UART = (BLE_NUS, (BLE_TX, BLE_RX,)) SERVICES = (BLE_UART, ) ((self.tx, self.rx,), ) = self.ble.gatts_register_services(SERVICES) def send(self, data): self.ble.gatts_notify(0, self.tx, data + '\n') def advertiser(self): name = bytes(self.name, 'UTF-8') # 修改Flags为通用可发现模式(0x03 = 通用可发现 + 不支持BR/EDR) adv_data = bytearray(b'\x02\x01\x03') + bytearray((len(name) + 1, 0x09)) + name # 调整广播间隔为300ms,提升跨系统兼容性 self.ble.gap_advertise(300, adv_data) print(f"广播数据: {adv_data}") but = Pin(0, Pin.IN) ble = ESP32_BLE("ESP32_BLE") def buttons_irq(pin): ble.led.value(not ble.led.value()) ble.send('LED状态已切换') print('LED状态已切换') but.irq(trigger=Pin.IRQ_FALLING, handler=buttons_irq) while True: if message == "STATUS": message = "" status_msg = 'LED已开启' if ble.led.value() else 'LED已关闭' print(status_msg) ble.send(status_msg) sleep_ms(100)
关键调整说明
- 将广播Flags改为
0x03,开启通用可发现模式,确保设备持续处于可扫描状态 - 增大广播间隔至300ms,避免被系统过滤
- 移除全局LED引脚初始化,避免资源冲突
- 添加BLE激活状态打印,方便排查初始化故障
- 统一中文提示信息,便于调试
内容的提问来源于stack exchange,提问作者Sahil Chabra09
相关产品推荐
相关产品推荐

