上一节课我们学了蓝牙BLE通信,实现了手机和ESP32的数据互传。今天我们把蓝牙和舵机结合起来------用手机APP远程控制舵机转动!
不需要WiFi,不需要插线,手机打开蓝牙,点一下按钮,舵机就转到指定角度。智能小车转向、机器人关节、摄像头云台......这些应用都可以用这个方案实现。
今天这节课,我们就用ESP32 + 蓝牙BLE + 舵机,做一个手机遥控的舵机控制系统!
第一步:找到课程,看看成品效果
打开逗脑IDE,点击顶部 "文档" ,在 "课程" → "ESP32 + MicroPython" 分类下,找到蓝牙控制舵机这节课。

打开课件,你会看到本节课的最终效果:手机通过蓝牙连接ESP32,发送指令后,舵机精准地转到0°、90°、180°,或者可以微调角度。

第二步:手机APP准备
本节课使用安卓手机上的蓝牙调试APP(如"蓝牙工坊",其他支持BLE的APP也可以)。
APP需要具备以下功能:
- 搜索并连接BLE设备
- 向特征值写入数据
- 创建自定义快捷按键(方便发送预设指令)

第三步:动手写代码------ESP32端
python
from machine import Pin, Timer, PWM
from time import sleep_ms
import bluetooth
BLE_MSG = ""
class ESP32_BLE():
def __init__(self, name):
self.led = Pin(2, Pin.OUT)
self.timer1 = Timer(0)
self.name = name
self.ble = bluetooth.BLE()
self.ble.active(True)
self.ble.config(gap_name=name)
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 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):
service_uuid = '6E400001-B5A3-F393-E0A9-E50E24DCCA9E'
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):
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)
# 按键中断
def buttons_irq(pin):
led.value(not led.value())
print('LED is ON.' if led.value() else 'LED is OFF')
ble.send('LED is ON.' if led.value() else 'LED is OFF')
if __name__ == "__main__":
ble = ESP32_BLE("ESP32BLE")
but = Pin(0, Pin.IN)
but.irq(trigger=Pin.IRQ_FALLING, handler=buttons_irq)
led = Pin(2, Pin.OUT)
# 舵机初始化(GPIO15)
p15 = PWM(Pin(15))
p15.freq(50)
duty_num = 1638
p15.duty_u16(1638) # 初始0度
# 0度 p15.duty_u16(1638)
# 90度 p15.duty_u16(4915)
# 180度 p15.duty_u16(8192)
while True:
if BLE_MSG == 'read_LED':
print(BLE_MSG)
BLE_MSG = ""
print('LED is ON.' if led.value() else 'LED is OFF')
ble.send('LED is ON.' if led.value() else 'LED is OFF')
elif BLE_MSG:
print("接收到的信息:>>%s<<" % BLE_MSG)
if BLE_MSG == "!B11:": # 按下app上数字1
duty_num += 100
if duty_num > 8192:
duty_num = 8192
p15.duty_u16(duty_num)
elif BLE_MSG == "!B219": # 按下app上数字2
duty_num -= 100
if duty_num < 1638:
duty_num = 1638
p15.duty_u16(duty_num)
elif BLE_MSG == "!B516": # 按下app上up键
p15.duty_u16(4915) # 转到90度
duty_num = 4915
elif BLE_MSG == "!B714": # 按下app上left键
p15.duty_u16(8192) # 转到180度
duty_num = 8192
elif BLE_MSG == "!B813": # 按下app上right键
p15.duty_u16(1638) # 转到0度
duty_num = 1638
BLE_MSG = ""
sleep_ms(100)
代码核心逻辑:
| 指令 | 对应操作 | 效果 |
|---|---|---|
!B11: |
按下APP上数字1 | 角度+100(微调增大) |
!B219 |
按下APP上数字2 | 角度-100(微调减小) |
!B516 |
按下APP上up键 | 转到90° |
!B714 |
按下APP上left键 | 转到180° |
!B813 |
按下APP上right键 | 转到0° |
📌 关键点: 每个按键对应一个特定的指令字符串(如
!B516),ESP32收到后执行对应的角度控制。
第四步:保存运行,手机连接蓝牙
保存代码到开发板,命名 ble_servo.py

点击运行按钮,ESP32开始广播BLE信号。
步骤1:连接蓝牙
打开手机APP,搜索到名为 "ESP32BLE" 的设备,点击连接。

步骤2:连接成功
连接成功后,APP显示日志:
> 正在连接...
> 连接成功,等待发现服务
> 连接成功,正在发现服务...
> 连接成功,并发现服务
> [6e400003] 通知已开启

详细的蓝牙连接步骤,可以看上一篇文章
第五步:发送指令,控制舵机转动
步骤3:输入操作指令,点击写入
在APP底部选择写入目标 6E400002 ,输入指令(如 !B516),点击 "写入"。

ESP32收到后: 舵机立刻转动到90°,终端打印接收到的信息。
第六步:创建快捷按键,一键控制
每次手动输入指令太麻烦?APP支持创建快捷按键,把常用指令做成按钮,点一下就能发送。
步骤4:创建按键,点击按键控制舵机
在APP中创建三个按键(上、左、右),分别对应:
| 按键名称 | 编码内容 | 对应角度 |
|---|---|---|
| 上 | !B516 |
90° |
| 左 | !B714 |
180° |
| 右 | !B813 |
0° |

创建完成后,APP上会出现 "上"、"左"、"右" 三个按键。
点击"上" → 舵机转到90°
点击"左" → 舵机转到180°
点击"右" → 舵机转到0°
连续点击日志:
11:04:36.828> [6e400002] !B516
11:04:38.266> [6e400002] !B714
11:04:39.661> [6e400002] !B813

指令与角度对照表
| APP操作 | 发送指令 | ESP32执行 | 舵机角度 |
|---|---|---|---|
| 数字1 | !B11: |
duty_num += 100 | 微调增大 |
| 数字2 | !B219 |
duty_num -= 100 | 微调减小 |
| 上 | !B516 |
duty_u16(4915) |
90° |
| 左 | !B714 |
duty_u16(8192) |
180° |
| 右 | !B813 |
duty_u16(1638) |
0° |
蓝牙控制舵机能做什么?
| 应用场景 | 用途 |
|---|---|
| 遥控小车 | 手机控制前轮转向 |
| 摄像头云台 | 手机控制摄像头上下左右转动 |
| 机器人关节 | 手机控制机械臂角度 |
| 智能窗帘 | 手机控制窗帘开合 |
| 航模控制 | 手机控制机翼舵面 |
全程回顾
| 步骤 | 操作 | 效果 |
|---|---|---|
| 找到课程 | 文档→课程→ESP32+MicroPython→蓝牙控制舵机 | 了解项目原理 |
| 打开代码 | 点击"打开"按钮 | 代码进入编辑器 |
| 保存运行 | Ctrl+S → 选择ESP32 → 运行 | ESP32开始广播 |
| 连接蓝牙 | 手机APP搜索"ESP32BLE"并连接 | 连接成功 |
| 发送指令 | 向6E400002写入"!B516" | 舵机转到90° |
| 创建按键 | 添加上/左/右三个快捷按键 | 一键控制 |
| 点击按键 | 点击"左"按键 | 舵机转到180° |
