ESP32 C3mini与ESP32-WROOM蓝牙连接问题

项目场景:

使用一下代码可以在ESP32-WROOM正常调用蓝牙

from machine import Pin, PWM
from machine import Timer
from time import sleep_ms
import bluetooth

# 全局变量:存储接收到的蓝牙消息
BLE_MSG = ""

class ESP32_BLE():
    def __init__(self, name):
        # 初始化PWM控制LED(引脚8)
        self.led = PWM(Pin(8))
        # 设置PWM频率为1000Hz(修正后的写法)
        self.led.freq(1000)
        # 创建定时器对象(定时器0)
        self.timer1 = Timer(0)
        # 存储蓝牙设备名称
        self.name = name
        # 初始化蓝牙模块
        self.ble = bluetooth.BLE()
        # 激活蓝牙硬件
        self.ble.active(True)
        # 设置蓝牙设备名称
        self.ble.config(gap_name=name)
        # 连接状态标志(新增)
        self.connected_flag = False
        # 初始化设备为断开状态
        self.disconnected()
        # 设置蓝牙中断处理函数
        self.ble.irq(self.ble_irq)
        # 注册GATT服务和特征
        self.register()
        # 开始蓝牙广播
        self.advertiser()

    def connected(self):
        # 设备连接时:
        # 1. 点亮LED(占空比100%)
        self.led.duty(1023)
        # 2. 停止心跳定时器
        self.timer1.deinit()
        # 3. 更新连接状态
        self.connected_flag = True

    def disconnected(self):
        # 设备断开时:
        # 1. 启动心跳定时器(LED闪烁)
        self.timer1.init(period=100, mode=Timer.PERIODIC, callback=lambda t: self.led.duty(500))
        # 2. 更新连接状态
        self.connected_flag = False

    def ble_irq(self, event, data):
        global BLE_MSG
        # 处理不同蓝牙事件:
        if event == 1:       # 设备连接事件
            self.connected()
        elif event == 2:     # 设备断开事件
            self.advertiser()
            self.disconnected()
        elif event == 3:     # 接收到数据事件
            # 读取特征值数据
            buffer = self.ble.gatts_read(self.rx)
            # 解码并存储消息(去除首尾空格)
            BLE_MSG = buffer.decode('UTF-8').strip()

    def register(self):
        # 定义GATT服务和特征:
        service_uuid = '6E400001-B5A3-F393-E0A9-E50E24DCCA9E'  # UART服务
        reader_uuid = '6E400002-B5A3-F393-E0A9-E50E24DCCA9E'  # 可写特征
        sender_uuid = '6E400003-B5A3-F393-E0A9-E50E24DCCA9E'  # 通知特征

        # 配置服务结构(元组嵌套)
        services = (
            (
                bluetooth.UUID(service_uuid),
                (
                    (bluetooth.UUID(sender_uuid), bluetooth.FLAG_NOTIFY),  # 通知特征
                    (bluetooth.UUID(reader_uuid), bluetooth.FLAG_WRITE),    # 写入特征
                )
            ),
        )

        # 注册服务并获取特征对象
        ((self.tx, self.rx,),) = self.ble.gatts_register_services(services)

    def send(self, data):
        # 数据发送前检查连接状态:
        if self.connected_flag:
            try:
                # 发送数据(添加换行符并编码为字节)
                self.ble.gatts_notify(0, self.tx, (data + '\n').encode('utf-8'))
            except OSError as e:
                print("发送失败:", e)
        else:
            print("未连接,跳过发送")

    def advertiser(self):
        # 构造广播数据:
        name = bytes(self.name, 'UTF-8')  # 设备名称
        # 固定广播头部(通用可发现模式)
        adv_data = bytearray(b'\x02\x01\x06')
        # 添加完整设备名称字段
        adv_data.extend(bytes([len(name) + 1, 0x09]))  # 字段长度+类型
        adv_data.extend(name)                          # 设备名称
        # 开始广播(间隔100ms)
        self.ble.gap_advertise(100, adv_data)
        print("广播数据:", adv_data, "\r\n")

if __name__ == "__main__":
    # 创建蓝牙对象(设备名"ESP32BLE")
    ble = ESP32_BLE("ESP32BLE")
    # 初始化LED控制(再次确认引脚)
    led = PWM(Pin(8))

    while True:
        # 连接状态指示灯逻辑
        if ble.connected_flag:
            ble.send('LED is OFF.')  # 周期性发送状态
            sleep_ms(1000)
        
        # 处理接收的命令:
        if BLE_MSG == 'LED ON':
            print("收到命令:", BLE_MSG)
            # 渐亮效果
            for i in range(0, 1023):
                led.duty(i)
                sleep_ms(3)
            BLE_MSG = ""
            print("LED已打开")
            ble.send('LED is ON.')  # 发送确认信息
        
        elif BLE_MSG == 'LED OFF':
            print("收到命令:", BLE_MSG)
            # 渐灭效果
            for i in range(1023, -1, -1):
                led.duty(i)
                sleep_ms(3)
            BLE_MSG = ""
            print("LED已关闭")
            ble.send('LED is OFF.')
        
        sleep_ms(100)  # 主循环延时

问题描述

但是在ESP32 C3mini平台上提示

错误代码128
 


原因分析:

大佬回复:

128报错是通信报错,因为蓝牙是虚拟串口的形式发送信息,所以当你的self.tx是0的时候,它实际上使用的是uart0,也就是esp32S3的repl口,这个口肯定是没法用的,所以你需要把self.tx改成1,这样他就会使用uart1,就和原本的uart0不冲突了
我不知道这个对不对,因为tx口是由系统自己分配的。

下面是我的分析,结合AI:

更改以下函数,esp32 mini即可正常使用

 def send(self, data):
        # 数据发送前检查连接状态:
        if self.connected_flag:
            try:
                # 发送数据(添加换行符并编码为字节)
                self.ble.gatts_notify(1, self.tx, (data + '\n').encode('utf-8'))
            except OSError as e:
                print("发送失败:", e)
        else:
            print("未连接,跳过发送")
为什么 WROOM 能工作而 C3 失败
1. 连接句柄的本质
  • 连接句柄(Connection Handle) 是 BLE 协议栈为每个活跃连接分配的唯一标识符(类似 TCP 的端口号)

  • 取值范围:0x0000 ~ 0xFFFF(实际使用中通常从 0 或 1 开始)

  • 0xFFFF 是保留值,表示无效连接

2. 不同芯片的分配策略
芯片型号协议栈实现首连接句柄多连接支持
ESP32-WROOMNimBLE (传统)0
ESP32-C3Bluedroid (新版)1

为什么参数为 1 可以,0 不行

1. 当使用 gatts_notify(1, ...)
  • ESP32-C3:正确匹配首个连接的句柄 1(Bluedroid 协议栈特性)

  • ESP32-WROOM:实际会忽略无效句柄 1,但:

    • 旧协议栈自动回退到唯一连接句柄 0

    • 表现出 "错误参数但能工作" 的假象

2. 当使用 gatts_notify(0, ...)
  • ESP32-C3:0 是无效连接句柄 → 触发 OSError: 128

  • ESP32-WROOM:0 是有效句柄 → 正常工作

ESP32是一款由Espressif Systems开发的低成本、低功耗的系统级芯片(SoC),具备Wi-Fi和蓝牙功能,广泛应用于物联网(IoT)项目中。在使用ESP32进行蓝牙通信时,它支持经典蓝牙(BR/EDR)和低功耗蓝牙(BLE)两种模式。其中,SPP(Serial Port Profile)是一种基于蓝牙的串口通信协议,用于模拟传统的串口通信。 如果你在使用ESP32连接蓝牙SPP后发现连接会断开,可能有以下几个原因: 1. 通信不稳定:可能是由于设备之间的物理距离过远或存在干扰导致通信不稳定,进而导致连接断开。 2. 数据溢出:如果设备之间传输的数据量过大或处理不及时,可能会导致内部缓冲区溢出,从而引起连接断开。 3. 蓝牙协议栈问题:软件上的bug或者协议栈配置不当可能导致连接异常。 4. ESP32固件问题:固件版本可能存在问题或者不支持某些特定的蓝牙设备,需要更新或检查固件。 5. 电源问题:电源不稳定可能会导致ESP32重启或进入低功耗模式,从而断开对方设备的连接。 为了解决这个问题,可以尝试以下步骤: - 检查ESP32蓝牙设备之间的物理距离,尽量减少干扰。 - 确保ESP32端的缓冲区大小足够,并及时处理接收到的数据。 - 检查并更新ESP32蓝牙协议栈和固件到最新版本。 - 查看ESP32的日志信息,分析断开的具体原因,可能是软件错误或配置问题- 确保ESP32的电源供应稳定,避免在使用过程中发生重启。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一月千帆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值