自学读本:跟着读、照着做,卡住就问 AI
你好,我是吴老师。
这份是给你自己读的——不用等我讲,你一段一段往下看,看到让你停下来的地方,就照着做一遍。看不懂的整段复制给 AI,加一句"请一次只解释一个概念,讲完问我一个小问题"。
读完之后,你应该能:说出 BLE 靠"广播+扫描"互相认识;用"文件夹/文件"解释服务和特征值;亲手让板子扫描出周围的 BLE 设备;用电脑 Python 脚本读写板子的特征值(开关灯/读温度/看电量)。
用时:60–90 分钟。准备:板子、数据线、Skill 已接入的 WorkBuddy;demo01/03 不需要电脑,demo02 需要一台开了蓝牙的教室电脑(装一次
pip install bleak)。
一、板子能"不联网"就和别人说话吗?
过去几课,板子跟别人说话都要先连 WiFi(17 连路由器、18 局域网、19 上互联网)。
问题来了:如果身边没有路由器、没有 WiFi,两块板子还能说话吗?
能。你的无线耳机、手环、鼠标都在用这个答案——蓝牙。今天用它的低功耗版本 BLE(Bluetooth Low Energy),让板子当一回"手环",跟教室电脑用 BLE 说话。
悬念:板子不连 WiFi、不插网线,电脑打开蓝牙就能发现它、还能读写它的数据。中间到底发生了什么?
二、BLE 世界里,设备怎么"认识"?
WiFi 靠"连同一个路由器"认识。BLE 只有两件事:
- 广播:设备不停喊"我在这,我是 XXX"(像举着灯牌晃)
- 扫描:别的设备竖起耳朵听,把喊话的记下来(像观众找灯牌)
先让板子当"观众":
请使用课程的 esp32s3-touchboard-hardware-dev Skill,
烧录本课配套程序 assets/codes/demo01_ble_scan_radar:
板子变成"蓝牙雷达",每 5 秒扫一次,把正在广播的设备按信号强弱列出来
(名字 + RSSI)。烧录后告诉我你扫到了什么。
打开教室电脑蓝牙,按 BOOT 让板子立刻扫一次。
| 我观察到的现象 | 勾选 |
|---|---|
| 列表里出现电脑/其他设备的名字 | |
| 每台设备后面有负数 RSSI(如 -58dBm) | |
| 板子拿远一点再扫,RSSI 更负了 | |
| 电脑蓝牙一关,它就从列表消失 |
为什么板子没连上它们,却"知道"它们在?因为每台开着蓝牙的设备都在不停广播,板子只是听见了。
代码关键:
BLEDevice::getScan()->start(...)让板子开始"听";每台设备带名字和 RSSI(信号强度,越接近 0 越近)。
三、把"耳朵"和"嘴"分开看
扫描是"耳朵","嘴"呢?让一两块板子闭嘴喊话:
请给一两块板子改烧录 assets/codes/demo03_ble_advertise_card:
它只做一件事——不停广播自己(默认 AI-PAD-6)。
让旁边跑 demo01 雷达的板子扫一扫,看会不会多出 AI-PAD-6。
demo01 = 观众(扫描),demo03 = 演员(广播)。广播自己不需要对方同意——你喊你的,谁听见算谁的。
⚠️ 比喻有边界:"广播像喊话"是指它单向、公开、省电(不是真的大喊);RSSI 只能比较远近(墙/人会干扰),量不出"正好 3 米"。
改一个条件:把 demo03 顶部的 AD_NAME 改成别的名字,重烧。旁边雷达屏上这个名字立刻变了——广播里喊什么,由喊的人决定。
四、听见了,然后呢?——服务与特征值
光认识没用,你要能读写它的数据。BLE 把数据组织得像文件夹:
- 服务 像文件夹(这块板子是一个"教室灯"文件夹)
- 特征值 像文件夹里的文件:能读的(温度/电量)、能写的(开关)、会自己变还"通知"你的(电量)
让板子当"教室灯",把三个文件摆出来:
请改烧录 assets/codes/demo02_ble_light_server:
板子广播自己叫 ESP32-LIGHT,身上三个特征值:
开关(可写):写"1"灯亮、写"0"灯灭
电量(可读+通知):每秒自己变,变了通知电脑
温度(可读):每次读都会变
烧录后告诉我板子显示什么。
板子屏幕有一盏大灯(灭的)。电脑不装 App、不连 WiFi,用一小段 Python 当遥控器:
pip install bleak # 只装一次
python pc/ble_light_peer.py # 在 assets/codes/pc/ 目录下
它会自动找到 ESP32-LIGHT 并连上。然后:
| 按键 | 我预测板子会怎样 | 实际看到 |
|---|---|---|
w(写"1") | 自己填 | 实验后填 |
x(写"0") | 自己填 | 实验后填 |
r(读温度) | 自己填 | 实验后填 |
b(盯 3 秒电量) | 自己填 | 实验后填 |
回答:这次板子和电脑之间有 WiFi 吗?有网线吗? 都没有。BLE 的"连接"不过是:先听见你(广播+扫描)→ 翻开你的文件夹(服务)→ 读读写写里面的文件(特征值)。
两个代码名:
- 服务端
createCharacteristic(..., PROPERTY_WRITE/READ/NOTIFY)= 在文件夹里放一个文件,贴标签说"能写/能读/会通知";- 电脑端
read_gatt_char(读文件)/write_gatt_char(写文件)。BLE 通信不是"发一条消息过去"那么自由,而是大家都按"文件夹+文件"的规矩来(这套规矩叫 GATT)。
五、一条完整的"蓝牙认识-读写"链路
BLE 设备怎么互相读写(最小闭环):
广播:每个设备不停喊"我在这,我叫 XXX"
扫描:想找设备的板子竖起耳朵听,记下名字和 RSSI
连接:听到后去敲门,自动配对(just works,不用输密码)
服务 = 文件夹,特征值 = 文件
能读的文件:电脑 read_gatt_char 拿走值
能写的文件:电脑 write_gatt_char 写进值
会变的文件:一变就 notify 通知订阅过的人
没有 WiFi、没有网线——靠的就是蓝牙这根"近处的线"
一句记牢:BLE 用"广播+扫描"让人互相发现,用"服务+特征值"让人互相读写;省电、近距、小数据,是给智能灯、手环、遥控准备的。
六、故障排查:电脑连不上板子怎么办
| 现象 | 观察还是推测? | 下一步 |
|---|---|---|
| 脚本打印"没找到板子" | 观察 | 推测广播没被听到 → 板子真在跑 demo02?屏幕"广播中"? |
| 板子"广播中"但电脑找不到 | 观察 | 距离/遮挡 → 放 1 米内;Windows 蓝牙开了吗? |
| 能连上但读写报错 | 观察 | UUID 对不上 → 电脑脚本与板子代码的 UUID 一致吗? |
| "配对框都没弹就失败" | 观察 | Windows 蓝牙驱动问题 → 换 USB 蓝牙口 |
老规矩:"电脑找不到板子"是观察,"板子没广播"是推测。 用另一块跑 demo01 雷达的板子反扫它,雷达也看不到才是真没广播。
七、过关检查
不看 AI,自己说:
- BLE 靠哪两件事"认识"?广播/扫描分别像生活里的什么?
- RSSI 越大越接近 0 说明什么?能量出"正好 3 米"吗?
- 服务和特征值像文件夹里的什么?举例一个"能写"、一个"会通知"的特征值。
- demo02 写"1"灯亮——这条路上有 WiFi 或路由器吗?
- BLE 适合传大文件吗?为什么?
- 想让板子"电量掉到 20% 才通知一次",该改谁?
八、还能玩什么
| 方向 | 想法 | 继续想 |
|---|---|---|
| 蓝牙雷达屏 | 加"信号最强"高亮,最近的设备跳出来 | 怎么把远近做成游戏? |
| 智能灯三件套 | 可读亮度 + 可写开关 + 可通知温度 | 电脑一次把三个都读回来? |
| BLE 遥控器 | 电脑按键,板子翻 PPT / 换图 | 除了开关还能让板子做什么? |
| 谁是广播王 | 多块板同时广播,雷达屏排信号榜 | 挤在一起会互相干扰吗? |
下一课预告:ESP-NOW——不要路由器、不要文件夹,两块板子直接点对点喊话。