ESP32S蓝牙04
我们先了解一下蓝牙的另一种状态BLE(低功耗蓝牙),BLE需要在Android API18版本以上,也就是安卓4.3版本以上才有的。
BLE之所以被称为低功耗蓝牙,就是需要通讯的时候才握手,数据传输完成后,就断开连接。而在这个通讯传输的过程中,主动方是客户端,都是由客户端发起连接请求、收发数据、断开连接等控制;相反,服务器端是被动的一方,服务器方随时做好了被连接的准备,并对连接请求作出响应,仅此而已。
先看一个简单的实用例子吧,手机用蓝牙连接小车,并发送控制指令,控制着小车的行驶状态。所以,在手机端需要的是一个控制小车行走的客户端APP,小车上面的接收端是ESP32,是服务器端,在接收到指令后,控制小车车轮电机的转动和转向,从而实现小车的运动。
- 手机APP制作
我们还是使用APPInventor 2在线编辑的模式制作手机APP,需要注意的是,我们这里使用的蓝牙组件是“低功耗蓝牙”。低功耗蓝牙只有一个,他既可以设置成服务器,也可以设置成客户端,具体就看后面的逻辑程序设计了。
制作完界面的组件设计后,可以制作逻辑程序。这里我们准备设置成客户端,主要的任务就是搜索蓝牙服务器信号,发送握手连接的请求,收发数据。我们需要一个定时器,帮助我们不断地尝试发送控制指令。这个部分没有写,只写了手动发送按钮的功能。
- ESP32S接收控制
ESP32S的接收的服务器端也要做成BLE,而BLE低功耗蓝牙的程序,在米思琪中是没有支持的,所以要改用的是Arduino IDE来编辑程序,代码也比较简单。
ESP32S通电后,直接初始化一个蓝牙服务器,并设置成可供别的蓝牙设备搜索、连接的状态。当手机控制端(客户端)发送连接请求、并连接成功后,当接收到从手机APP传来的控制指令后:直接把这个指令返回到手机APP(这样手机APP就可以知道自己之前发送的那条消息已经发送成功,以及ESP32S接收到指令后改变了小车的状态),这样手机APP就能知道小车的当前行驶状态了;同时把接收到的指令做进一步处理,通过串口发送到电脑显示(或者你也可以让指令显示在液晶屏,根据指令改变小车行驶状态)。
// 包含所必需的库
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
BLEServer *pServer = NULL;
BLECharacteristic *pTxCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;
char BLEbuf[32] = {0};
String data = "";
// 定义收发服务的UUID(唯一标识)
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
// RX串口标识
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
// TX串口标识
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string rxValue = pCharacteristic->getValue();
if (rxValue.length() > 0) {
Serial.println("*********");
//接收数据
Serial.print("Received Value: ");
for (int i = 0; i < rxValue.length(); i++){
Serial.print(rxValue[i]);
}
Serial.println();
data =rxValue.c_str();
//Serial.println(data);
Serial.println("*********");
Serial.println();
}
}
};
// setup()在复位或上电后运行一次:
void setup() {
Serial.begin(115200);
Serial.println("1- Download and install an BLE scanner app in your phone");
Serial.println("2- Scan for BLE devices in the app");
Serial.println("3- Connect to MyESP32");
Serial.println("4- Go to CUSTOM CHARACTERISTIC in CUSTOM SERVICE and write something");
Serial.println("5- See the magic =)");
// 初始化蓝牙设备
BLEDevice::init("MyESP32");
// 为蓝牙设备创建服务器
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
// 基于SERVICE_UUID来创建一个服务
BLEService *pService = pServer->createService(SERVICE_UUID);
pTxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY
);
pTxCharacteristic->addDescriptor(new BLE2902());
BLECharacteristic * pRxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
BLECharacteristic::PROPERTY_WRITE
);
pRxCharacteristic->setCallbacks(new MyCallbacks());
// 开启服务
pService->start();
// 开启通知
pServer->getAdvertising()->start();
Serial.println("Waiting a client connection to notify...");
Serial.println();
}
// loop()一直循环执行:
void loop() {
if (deviceConnected==1&data.length()>0) {
memset(BLEbuf, 0, 32);
memcpy(BLEbuf, data.c_str(), 32);//数据赋值
Serial.println(BLEbuf);
pTxCharacteristic->setValue(BLEbuf); //收到数据后返回数据
pTxCharacteristic->notify();
data = ""; //返回数据后进行清空,否则一直发送data
}
// 没有新连接时
if (!deviceConnected && oldDeviceConnected) {
// 给蓝牙堆栈准备数据的时间
delay(500);
pServer->startAdvertising();
// 重新开始广播
Serial.println("start advertising");
oldDeviceConnected = deviceConnected;
}
// 正在连接时
if (deviceConnected && !oldDeviceConnected) {
// 正在连接时进行的操作
oldDeviceConnected = deviceConnected;
}
}
关键代码解读:
// 定义收发服务的UUID(唯一标识)
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
// RX串口标识
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
// TX串口标识
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
BLE低功耗蓝牙需要设置独特的标识UUID,ESP32S开发板通电后,向外不停地广播一个服务器及服务器的UUID,然后手机客户端就可以通过搜索并选择这个服务器的UUID,选择和这块开发板握手连接。
我们可以注意到,在开发板驱动程序这里设置的一些UUID标志,在手机控制APP的逻辑代码中也要一一对应的,否则就无法握手、无法通讯了。
- 真机测试
我们把这个手机控制的APP下载到手机并安装。
给ESP32S连接到电脑(接通电源),并在Arduino IDE中打开串口监视器,注意选择波特率为115200。
打开手机,取消手机中原来已配对的蓝牙设备,重新搜索,发现这个开发板的蓝牙信号。特别特别地注意了,不要配对(因为这时候的ESP32S广播的是BLE低功耗蓝牙的服务,而手机默认的配对是传统的BT蓝牙服务。所以即使你选择配对的话,手机也会告诉你需要专用的软件才能配对的)
在手机中打开控制APP,然后选择扫描——蓝牙列表——连接,会发现连接成功。然后你就可以按动手机中的方向按钮,开发板也能收到响应的控制指令,并把指令传递到串口监视器中显示出来。
有了这个,只要稍加修改,手机控制的ESP32S蓝牙小车就要成功了。