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

树莓派Pico W基于aioble的BLE连接频繁中断问题求助

环境与问题

我正在使用MicroPython(v1.22.2)结合aioble库,为树莓派Pico W开发蓝牙低功耗(BLE)外设应用,中央设备为运行bluepy库的树莓派3 B+。目前遇到BLE连接在10-20秒后反复中断的问题,外设会发送传感器状态(开/关)通知,中央设备能正常接收这些通知。

具体现象简化如下:

  • 中央设备连接到外设;
  • 外设发送若干条通知;
  • 连接突然中断。
外设端代码片段
# Bluetooth GATT setup
_DOOR_SERVICE_UUID = bluetooth.UUID('12345678-1234-5678-1234-56789abcdef0')
_DOOR_STATE_UUID = bluetooth.UUID('12345678-1234-5678-1234-56789abcdef1')
_ADV_APPEARANCE_GENERIC_DOOR_SENSOR = const(768)
_ADV_INTERVAL_MS = 250_000

door_service = aioble.Service(_DOOR_SERVICE_UUID)
door_state_characteristic = aioble.Characteristic(door_service, _DOOR_STATE_UUID, read=True, notify=True)
aioble.register_services(door_service)
...
...
# Bluetooth advertising task
async def peripheral_task():
    global current_connection
    while True:
        if not current_connection:
            print("No Connection, attempting to advertise")
            try:
                async with await aioble.advertise(
                    _ADV_INTERVAL_MS,
                    name="DoorSensor",
                    services=[_DOOR_SERVICE_UUID],
                    appearance=_ADV_APPEARANCE_GENERIC_DOOR_SENSOR,
                ) as connection:
                    current_connection = connection
                    print("Connection from", connection.device)
                    await connection.disconnected()
            except asyncio.CancelledError as e:
                print(f"Cancelled: {str(e)}")
                current_connection = None
            except Exception as e:
                print(f"Unhandled exception: {str(e)}")
            finally:
                current_connection = None
        else:
            if not current_connection.is_connected():
                print("lost connection")
            print("connected")
            await asyncio.sleep(1)
...
# loop which checks door state and notifies central
...
    if current_connection:
        door_state_characteristic.notify(current_connection, _encode_door_state(1))
    await asyncio.sleep(1)
中央端代码
from bluepy.btle import Peripheral, DefaultDelegate

class MyDelegate(DefaultDelegate):
    def __init__(self):
        DefaultDelegate.__init__(self)

    def handleNotification(self, cHandle, data):
        print("Notification from Handle: {}".format(cHandle))
        state = int.from_bytes(data, byteorder='little')
        print("Door State Changed:", "Open" if state else "Closed")

def connect_to_sensor():
    peri = Peripheral("D8:3A:DD:9E:82:B1", "public")
    peri.setDelegate(MyDelegate())

    print("Connected to device")

    # Get service and characteristic
    svc = peri.getServiceByUUID("12345678-1234-5678-1234-56789abcdef0")
    ch = svc.getCharacteristics("12345678-1234-5678-1234-56789abcdef1")[0]

    print("Service and characteristic found")

    # Correct CCCD UUID for enabling notifications
    cccd_uuid = "00002902-0000-1000-8000-00805f9b34fb"
    cccd = ch.getDescriptors(forUUID=cccd_uuid)[0]
    cccd.write(b"\x01\x00", True)  # Enable notifications

    print("Subscribed to notifications")

    return peri

p = None

while True:
    if p:
        try:
            if p.waitForNotifications(1.0):
                continue
            print("Waiting for notifications...")
        except Exception as e:
            print(f"got some weird error\n{e}")
            p = None
    elif not p:
        p = connect_to_sensor()
        
p.disconnect()
已尝试的解决措施
  • 在外设脚本中实现重连策略,中断后立即重启广播;
  • 在外设和中央脚本中添加异常处理,捕获并记录连接或通知处理过程中的错误。
预期结果
  • 中断后立即重启广播,使中央设备能近乎持续地重连;
  • 通过详细错误日志揭示中断原因,帮助定位并解决问题。
当前仍存在的问题
  • 重连策略虽能快速恢复,但导致无规律的反复中断与重连循环,难以定位根因;
  • 错误日志未显示具体异常,仅输出"Cancelled:"无额外详情。
外设端输出
No Connection, attempting to advertise
Connection from Device(ADDR_PUBLIC, e4:aa:ea:fb:e0:32, CONNECTED)
It's open # notification
It's open # notification
Cancelled: 
No Connection, attempting to advertise
Connection from Device(ADDR_PUBLIC, e4:aa:ea:fb:e0:32, CONNECTED)
It's open # notification
Cancelled: 
No Connection, attempting to advertise
Connection from Device(ADDR_PUBLIC, e4:aa:ea:fb:e0:32, CONNECTED)
It's open # notification
It's open # notification
使用bluetoothctl测试

在Ubuntu 22.04机器上用bluetoothctl测试显示,是外设主动断开连接而非中央设备。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 21:24:57