Mind+V2 通信扩展库|经典蓝牙:手机遥控就这么简单
做嵌入式项目时,串口几乎是最常见的调试和通信手段:打印程序状态、查看传感器数据,或者向开发板发送简单指令,通常都离不开它
通常来说我们会使用USB串口,毕竟他和烧录往往是同一个接口,实际使用上也十分便捷
不过USB串口也有一个很明显的问题
需要一根线
当开发板装在小车上、放在较远的位置,或者已经安装进作品内部时,再拖着一根USB数据线就不太方便了
如果只是想发送一些简单控制指令,或者查看开发板返回的数据,有没有一种更轻量的无线方式?
经典蓝牙就是其中一种很合适的方案
一、从有线串口到无线串口
在经典蓝牙中,可以通过类似串口的方式在两个设备之间持续收发数据
对程序来说,它很像把原来的串口通信换成了一条无线链路:

对LED控制、小车遥控、舵机调节、传感器数据回传这类数据量不大的项目来说,这种通信方式已经足够实用
不过,在开始使用之前,还需要先区分两个经常被混在一起的概念:经典蓝牙(ClassicBluetooth) 和 低功耗蓝牙(BLE)
二、经典蓝牙和BLE有什么区别?
我们平时说的“蓝牙”并不是一种单一的通信方式,在嵌入式项目中,最常接触到的主要是下面两类:
| 类型 | 全称 | 典型用途 | 数据特点 |
|---|---|---|---|
| 经典蓝牙 | Classic Bluetooth / BR / EDR | 蓝牙音箱、无线串口、手机遥控 | 适合持续连接和连续数据传输 |
| 低功耗蓝牙 | BLE, Bluetooth Low Energy | 手环、传感器信标、配网 | 功耗低,通常通过GATT服务交换数据 |
两者虽然都属于蓝牙技术,但通信模型并不相同
BLE 通常围绕 Service、Characteristic 和 GATT 进行数据读写,更适合低功耗设备和传感器场景
而经典蓝牙可以通过 SPP(Serial PortProfile) 等方式建立类似串口的数据通道,连接建立后,开发板和手机可以像使用串口一样持续收发文本或字节数据,因此特别适合遥控、调试和简单的数据传输
这篇文章先从经典蓝牙入手,教会大家在掌控板或者萤火虫ESP32上跑通这个模块~
三、准备工作
3.1 支持主板型号
首先我们需要明确一个点:什么板子支持经典蓝牙
ESP32 是一个系列,不同型号的无线能力差很多,其中不少型号压根没有经典蓝牙
| 芯片型号 | 经典蓝牙 | 低功耗蓝牙 | 备注 |
|---|---|---|---|
| ESP32(含 WROOM / WROVER 等常见模组) | 支持 | 支持 | 最普遍的一款,两种模式都全 |
| ESP32-S2 | 不支持 | 不支持 | 没有蓝牙功能 |
| ESP32-S3 | 不支持 | 支持 | 只有 BLE,最容易被误判 |
| ESP32-C3 | 不支持 | 支持 | 只有 BLE |
| ESP32-C6 | 不支持 | 支持 | 只有 BLE,另有 802.15.4 |
| ESP32-H2 | 不支持 | 支持 | 只有 BLE |
| ESP32-P4 | 不支持 | 不支持 | 无射频模块 |
这里我也在硬件清单列出了Mind+中支持的主板型号:
- 掌控板(注意 掌控板V3 不支持哦,他是ESP32-S3核心只能BLE通信)
- FireBettle ESP32
- FireBettle ESP32-E
- 其他通用ESP32核心开发板

如果你的主控并不在以上怎么办?可以期待Mind+V2 通信扩展库的后两篇文章 BLE 以及 ESP-NOW,这两个协议覆盖几乎所有Mind+上的主控~
3.2 推荐app
这里推荐配套软件 BT AIO 终端 作为手机软件和主控进行通信:

在文末也附上了一样的压缩包,解压以后在手机上安装即可:

另外,iPhone 用不了这条路:iOS 从系统层面就不开放 SPP(串口协议),所以经典蓝牙串口 APP 基本只有 Android 版本,苹果设备上做无线串口,只能走 BLE
3.3 Mind+V2 扩展库加载
我们直接在Mind+的模块扩展中搜索 经典蓝牙 即可:

四、积木说明
4.1 经典蓝牙 初始化 名称为 " "

这个积木负责把蓝牙功能打开,方框里填的名字就是手机搜索列表里显示的设备名
几个要点:
- 整个程序里只执行一次,放在「程序开始」下面
- 把它塞进重复执行的循环里会让蓝牙反复重启,手机端会看到设备连上又断开
- 名字建议用英文或数字,别超过 20 个字符,中文名在部分安卓机上会显示成乱码,属于系统层面的编码问题
- 名字最好带点辨识度,教室或工位附近同时有好几块板子在跑,一堆 "ESP32" 里根本分不清哪块是自己的,写成 "ESP32-LED-A" 这种就省事了
程序上传运行后,手机打开蓝牙搜索,列表里就能看到这个名称
4.2 经典蓝牙 已连接?

返回真假值的判断型积木,用在条件里
它的典型用法是给发送操作加一道保险:蓝牙没连上的时候往缓冲区写数据是没有意义的,数据会直接丢掉,程序也不会报错,白白调试半天
写数据之前顺手判断一下,能省掉不少困惑
4.3 经典蓝牙 有数据可读?

返回真假值,用来检查接收缓冲区里有没有还没被取走的数据
配套用法是把它放进循环:数据到了开发板不会自动跳进变量里,得主动去取
跳过这一步直接调用读取积木,缓冲区空着的时候取出来的东西是无效的,程序逻辑就会变得莫名其妙
4.4 经典蓝牙 读取一个字符
从缓冲区取走一个字符,取完这个字符就从缓冲区里消失了
手机发 Hello,连续调用五次,会依次拿到:
H
e
l
l
o
单字符协议用起来很顺手:约定 A 开灯、B 关灯,手机按一个键发一个字母,开发板读到就直接分派动作,不需要纠结换行符
指令表越长,这种写法的优势越明显,一个字符就是一条命令,手机端一个按钮对应一个字母,协议简单到不需要文档
4.5 经典蓝牙 读取一行字符串
一次取走一整行,遇到换行符就认为这行结束了
手机发 Hello Mind+ 加一个换行,程序一次就能拿到完整的 Hello Mind+,不用自己拼字符,文本类数据、带参数的指令,都更适合用这个
换行符 是个硬性条件:读取一行的动作会一直等到换行符出现才返回,手机端 APP 如果不发换行符,程序就一直等在那儿
APP在设置里有切换换行符选项,右上角-Newline 即可看到 LF、CR+LF 或者 none

4.6 经典蓝牙 发送数据 " "

往当前连接的设备发内容,发什么就是什么,末尾不补任何字符
手机端收到的就是 Button A Pressed 这串字符本身。需要把多条数据拼在同一个显示行里的时候,用这个比用「发送一行」合适
4.7 经典蓝牙 发送一行 " "

同样是发数据,区别在于它会在末尾自动补一个换行符
手机端看到的是一行独立的 Hello,光标自动换到下一行。如果接收端也用「读取一行字符串」来读,这个换行符就是那一行的结束标记,两边正好配上
周期性上报数据用这个积木体验最好,连续发送温度、湿度、光照,手机端会整整齐齐地排成三行
4.8 经典蓝牙 写入原始字节 0x

发一个字节的原始数据,方框里填十六进制值,范围 0x00 到 0xFF
适用场景是自定义二进制协议:跟某个特定模块对接、需要下发固定的字节指令、或者要严格控制每一字节的内容
往串口屏、老式工控设备发指令时经常要用到
只是发文字或数字,用前两个发送积木就够了,原始字节属于需要精细控制的场合才动用的工具,开始就上它容易把调试搞复杂
五、示例程序
5.1 双向串口通信示例
前面已经介绍了经典蓝牙的基本用法,下面通过一个简单的 双向串口通信示例 把发送、接收和连接状态判断组合起来
连接成功后,手机发送的数据会被输出到电脑串口;电脑串口输入的数据,也会通过经典蓝牙发送到手机,从而形成一条双向的数据通道
这一程序也在附件可以直接下载,这里以掌控板为例:

程序流程如下:
- 将串口波特率设置为 115200,并将经典蓝牙设备名称设置为
CB-ESP32-TEST - 等待手机连接蓝牙。未连接时,串口持续输出
waiting...,方便观察当前连接状态 - 蓝牙连接成功后,向手机发送一次 “已成功连接!”
- 在主循环中持续检查两侧的数据:
- 蓝牙有数据可读时:读取手机发送的一行字符串,并输出到串口;
- 串口有数据可读时:读取电脑串口收到的数据,并通过经典蓝牙发送给手机
- 每轮循环等待
0.1秒,避免程序过于频繁地轮询
这样就实现了最基本的:
手机 → 蓝牙 → ESP32 → USB 串口
以及反方向的:
电脑串口 → ESP32 → 蓝牙 → 手机
手机上我们可以打开BT AIO 终端:

选中对应的设备:

然后比如说我们在Mind+的串口监视区域输入: 这是一条从电脑发送的信息:)

手机可以看到对应的信息,同时我们可以回复一句:

同样的在电脑上就可以看到信息了:

5.2 蓝牙串口控制板载LED
同样的我们也可以修改其中的发送逻辑:

在我们手机端输入全部开灯后就可以看见板载的三个LED亮起了!

六、总结
到这里,经典蓝牙扩展库的基本使用就介绍完了
掌握发送、接收和连接状态判断这几个核心积木后,就可以根据自己的项目需求继续扩展出更多玩法,比如说两块板子通过蓝牙串口互相发送信息、通过蓝牙控制串口屏....对于手机遥控、小车控制、传感器数据回传、无线串口调试这类需要持续双向通信的项目,经典蓝牙依然是一种简单、直接而且很好上手的方案
本文主要介绍的是 Classic Bluetooth(经典蓝牙),如果项目更加关注低功耗、传感器数据交互,或者需要使用 GATT 服务与特征值,那么 BLE 会更加合适,后续我也会继续介绍 Mind+ 中 BLE 和 ESP-NOW 扩展库的使用方式






