0


ESP32之经典蓝牙库BluetoothSerial介绍和实例演示

ESP32之经典蓝牙库BluetoothSerial介绍和实例演示

1.概述

目前ESP32内置了双模蓝牙(蓝牙4.0版本之前都是经典蓝牙,4.0版本成为BLT低功耗蓝牙转为物联网开发。双模指的就是这款芯片两种模式都支持)。
这篇文章介绍ESP32蓝牙的经典模式使用方法,那么就有疑问了,既然有新版本的蓝牙为什么还要介绍旧版本的蓝牙使用那,这就和使用场景有关了,经典蓝牙库简单,BLT库复杂。如果只是实现首发数据那么经典蓝牙更合适。如果对功耗有要求那么可以使用BLT库开发。

2.蓝牙BluetoothSerial库介绍

经典蓝牙模式开发使用

BluetoothSerial

库,这个库在Arduino中已经存在,不需要单独下载,下面就来介绍下这个库常用的函数,以及如何使用这些库开发程序。

2.1.主从机模式介绍

不同的蓝牙设备之间的连接他们都有一个身份,这个身份就是主机还是从机。
下面介绍下两个身份的区别:
主机身份:
主机身份可疑主动搜索从机的蓝牙地址,并且和他们建立连接。一个主机可以同时连接多个从机。

从机身份
从机模式不能搜索其他设备的蓝牙不能主动建立连接,只能被搜索。从设备和主机建立连接后可以和主设备收发数据,从设备可以允许多个主设备配对,但只能允许一台主机连接。

2.2.常用库介绍

1.获取自身蓝牙地址

每个设备的蓝牙都有一个唯一的mac地址,它由6个字节组成。使用

esp_bt_dev_get_address()

函数可以获取本机的蓝牙mac地址。

获取本机蓝牙mac地址示例

#include"esp_bt_main.h"#include"esp_bt_device.h"#include"esp32-hal.h"#include"BluetoothSerial.h"voidsetup(){//设置蓝牙波特率
  Serial.begin(115200);//开启蓝牙btStart();//初始化蓝牙协议esp_bluedroid_init();//开启蓝牙协议esp_bluedroid_enable();}voidloop(){//获取本机蓝牙地址auto address =esp_bt_dev_get_address();if(address){for(int i=0; i<6; i++){// 格式化输出蓝牙6个字节内容
      Serial.printf("%02X", address[i]);if(i<5){
        Serial.print(":");}}
    Serial.println();delay(1000);}}

在Arduino上查看查看蓝牙地址信息时候,需要将波特率调整为115200
在这里插入图片描述

2.建立连接和收发信息函数

函数名称解释BluetoothSerial(void)构造函数bool begin(String localName=String(), bool isMaster=false)初始化蓝牙,从机初始化完后就可以接受主机的连接了;localName:蓝牙的名称,如果为空的话,默认为ESP32;isMater:是否是主机,默认是从机,从机可以被主机连接bool hasClient(void)是否有设备已经连接bool disconnect()关闭当前的spp连接bool isclosed()spp连接是否已经关闭bool isReady(bool checkMaster=false, int timeout=0); voidend(void)/spp信道是否可用,如果checkMaster为true还会同时检测本机是否是主机,不是的话也会返回falsevoidend(void)关闭蓝牙功能bool unpairDevice(uint8 t remoteAddress[])解除指定地址的蓝牙设备的配对

3.收发数据函数

函数名称解释int available(void)有多少数据可以读void setTimeout(int timeoutMS)设置读写的超时时间,默认是0,马上返回int peek(void)读缓冲区第一字节,如果读取错误,返回—1int read(void)读取一个字节,如果读取错误,返回—1size t write(uint8 t c)发送一个字节size_t write(const uint8_t *buffer, size t size)最多发送size字节,返回成功发送的字节 数size_t print()size_t printf()size_t println()三个print系列的函数都是返回实际发送的字节void flush()将数据从缓冲区强制送入信道size t readBytes(char *buffer, size_t length)字节方式读取数据size t readBytesUntil(char terminator, char *buffer, size t length)字节方式读取数据String readstring()字符串方式读取数据String readStringUntil(char terminator)字符串方式读取数据

3.ESP32作为从机示例

3.1.最简单的从机发送和接收数据例子

这个例子将ESP32设置为从机,程序中没有使用SPP协议,他不需要密码验证就可以配对连接。

#include"BluetoothSerial.h"

BluetoothSerial SerialBT;//定义一个蓝牙对象voidsetup(){
  Serial.begin(115200);
  SerialBT.begin("ESP32Fish");//蓝牙的名字叫ESP32Fish, 从机模式
  Serial.println("The device started, now you can pair it with bluetooth!");}voidloop(){char buf[129];//判断是否接收到数据if(SerialBT.available()){auto sz = SerialBT.readBytes(buf,128);//从蓝牙接收数据if(sz){
      buf[sz]=0;
      Serial.println(buf);strcat(buf," - Slave");
      SerialBT.write((uint8_t*)buf,strlen(buf));//从蓝牙发送数据}}delay(20);}

1.将程序复制到ArduinoIDE,然后将程序上传到ESP32.
2.这个时候需要拿出手机,开发蓝牙设置搜索名称为

ESP32Fish

蓝牙设备,然后配对。
3.配对成功后,在windows电脑上通过浏览器搜索

Bluetooth Serial Tool

蓝牙调试工具并安装。
4.打开

Bluetooth Serial Tool

工具:

  • 点击Refresh刷新
  • 然后选择蓝牙名称
  • 点击Connect连接
  • 输入内容
  • 点击发送在这里插入图片描述 查看ArduinoIDE窗口接收到了消息在这里插入图片描述

3.2.SPP开启SSP验证最简单例子

开启SSP验证在配对的时候就需要输入验证码才能连接。
下面是开启SSP的函数

//启用SSP认证,配对的时候会主机会产生一个密码发送给从机,我们从机手动确认,主机侧也得确认void enableSSP();
//设置配对认证请求回调函数voidonConfirmRequest(ConfirmRequestCb cb);//设置配对认证结果回调函数voidonAuthComplete(AuthCompleteCb cb);//是否同意连接,true:同意 false:不同意voidconfirmReply(boolean confirm);typedef std: function<void(uint32_t num val)> ConfirmRequestCb;typedef std: function<void(boolean success)> AuthCompleteCb;

关于配对的一些提示:
如果你两台设备配对过了,你的从机改了认证方式,改了蓝牙名,实测两台设备之前还是处于配对状态。

开启SSP验证示例代码

#include"BluetoothSerial.h"

BluetoothSerial SerialBT;//定义一个蓝牙对象//认证请求回调voidBTConfirmRequestCallback(uint32_t numVal){//numVal是主机发来的识别码
  Serial.printf("recv pin: %d \r\n", numVal);//这里要对这个识别码进行判断,是否和主机一样或是是否是我们从机内置的密码//然后再判断是否确定连接,我们这里直接确认了
  SerialBT.confirmReply(true);//SerialBT.confirmReply(false);  //如果要拒绝就用这句}//认证结果回调函数voidBTAuthCompleteCallback(boolean success){if(success)
    Serial.println("Pairing success!!");else
    Serial.println("Pairing failed, rejected by user!!");}voidRecvData(constuint8_t*buffer,size_t size){if(size >0){
    Serial.write(buffer, size);//打印出来
    SerialBT.write(buffer, size);
    SerialBT.println(" - Slave");}}voidsetup(){
  SerialBT.enableSSP();//在begin之前调用
  SerialBT.onConfirmRequest(BTConfirmRequestCallback);
  SerialBT.onAuthComplete(BTAuthCompleteCallback);
  Serial.begin(115200);
  SerialBT.onData(RecvData);//注册接收回调函数
  SerialBT.begin("ESP32Fish");//蓝牙的名字叫ESP32Fish, 从机模式
  Serial.println("The device started, now you can pair it with bluetooth!");}voidloop(){}

上传程序后,删除之前的配对信息,然后重新配对,就会提示输入code码。

在这里插入图片描述

4.ESP32作为主机介绍

4.1.主机常用函数

函数名称介绍BTScanResults* discover(int timeout=0x301280)阻塞方式进行蓝牙设备搜索,未到达超时时间,程序会在该函数上一直等待,形成阻塞bool discoverAsync(BTAdvertisedDeviceCb cb, int timeout=0x301280)事件方式(非阻塞)进行蓝牙设备搜索;cb:回调函数;timeout:超时时间,搜索多少msvoid discoverAsyncStop()取消由discoverAsync启动的蓝牙搜索,并清空回调函数void discoverClear()清空对象保存的搜索结果BTScanResults* getScanResults()获取蓝牙搜索结果bool begin(String localName=String(), bool isMaster=false)初始化蓝牙;localName:蓝牙的名称,如果为空的话,默认为ESP32;isMater:设置为主机,要设置为truebool connect(String remoteName)根据名字连接,速度慢bool connect(uint8 t remoteAddress[], int channel=0, esp_spp_sec_t sec_mask=(ESP_SPP_SEC_ENCRYPT ESP_SPP_SEC_AUTHENTICATE), esp_spp_role_t role=ESP_SPP_ROLE_MASTER)根据MAC地址,速度快bool connected(int timeout=0)是否已成功连接bool hasclient(void)是否有设备已经连接

4.2.阻塞式搜索蓝牙示例

将下面的程序复制到ArduinoIDE,然后上传到ESP3上。打开窗口调试窗口,可以看到它如果搜索到蓝牙设备,则会点亮自身的D2 灯。

#include"BluetoothSerial.h"#include<esp_bt_device.h>#defineLEDPIN2

BluetoothSerial SerialBT;//定义一个蓝牙对象voidsetup(){pinMode(LEDPIN, OUTPUT);digitalWrite(LEDPIN,LOW);
  Serial.begin(115200);//初始化蓝牙,设置蓝牙名称和主机模式if(!SerialBT.begin("ESP32Fish2", true)){
    Serial.println("BT begin failed.");return;}delay(1500);//阻塞式发现设备auto ret = SerialBT.discover(10000);if(ret ==NULL){
    Serial.println("discover failed");return;}//如果搜到蓝牙设备就点亮esp32板子上D2led灯digitalWrite(LEDPIN, HIGH);//输出搜索到的设备名称int count = ret->getCount();
  Serial.printf("count: %d\r\n", count);for(int i=0; i<count; i++){auto dev = ret->getDevice(i);if(dev){auto name = dev->getName();//nameauto rssi = dev->getRSSI();//rssiauto cod = dev->getCOD();//codauto address = dev->getAddress();
      Serial.printf("dev %d: %s [%s]\r\n", i, name.c_str(), address.toString().c_str());}}}voidloop(){// put your main code here, to run repeatedly:}

4.3.非阻塞式搜索蓝牙示例

下面是非阻塞式搜索蓝牙示例,在示例中使用了

AsyncTimer

库,需要使用ArduinoIDE安装下这个库。
程序不会阻塞在搜索蓝牙过程中,在搜索过程中可以运行其他的任务。

#include"BluetoothSerial.h"#include<AsyncTimer.h>#defineLEDPIN2

BluetoothSerial SerialBT;//定义一个蓝牙对象
AsyncTimer t;//获取设备信息voidAdvertised(BTAdvertisedDevice* pDevice){auto name = pDevice->getName();//nameauto rssi = pDevice->getRSSI();//rssiauto cod = pDevice->getCOD();//codauto address = pDevice->getAddress();
  Serial.printf("dev : %s [%s]\r\n", name.c_str(), address.toString().c_str());}voidsetup(){pinMode(LEDPIN, OUTPUT);digitalWrite(LEDPIN,LOW);
  Serial.begin(115200);//初始化蓝牙设备,设置名称和主机模式if(!SerialBT.begin("ESP32Fish2", true)){
    Serial.println("BT begin failed.");return;}delay(1500);//非阻塞式搜索蓝牙设备信息if(SerialBT.discoverAsync(Advertised)){
    Serial.println("find start...");}else{
    Serial.println("find error");return;}//10s后取消搜索
  t.setTimeout([]{
    Serial.println("find stop...");
    SerialBT.discoverAsyncStop();},10000);}voidloop(){
  t.handle();//这里可以在搜索的时候同时干其它事}

4.4.非ssp模式双蓝牙收发送信息

下面的示例演示了主从机两个ESP32开发板通过蓝牙互相发送信息的过程,这个代码中省去了搜索蓝牙的代码如果需要这个功能,可以复制上面搜索蓝牙的代码。

1.从机模式

将代码上传到ESP32开发板,然后在调试窗口查看输出的蓝牙地址。

#include"BluetoothSerial.h"#include<esp_bt_device.h>#defineLEDPIN2

BluetoothSerial SerialBT;//定义一个蓝牙对象//定义一个接收信息方法voidRecvData(constuint8_t*buffer,size_t size){if(size >0){
    Serial.write(buffer, size);//打印出来
    SerialBT.write(buffer, size);
    SerialBT.println(" - Slave");}}voidsetup(){pinMode(LEDPIN, OUTPUT);

  Serial.begin(115200);
  SerialBT.onData(RecvData);//注册接收回调函数
  SerialBT.begin("ESP32Fish1");//蓝牙的名字叫ESP32Fish, 从机模式auto address =esp_bt_dev_get_address();//获取本机的蓝牙mac地址if(address)//找到地址了{for(int i=0;i<6;i++){
        Serial.printf("%02X", address[i]);if(i<5)
          Serial.print(":");}
      Serial.println();}

  Serial.println("The device started, now you can pair it with bluetooth!");}voidloop(){//判断是否有设备连接if(SerialBT.hasClient()){digitalWrite(LEDPIN, HIGH);}else{digitalWrite(LEDPIN, LOW);}delay(200);}
2.主机模式

下面的程序需要将

uint8_t clientAddress

蓝牙地址改为上面从机输出的蓝牙地址
然后将程序上传到另一个ESP32开发板。

#include"BluetoothSerial.h"#defineLEDPIN2

BluetoothSerial SerialBT;//定义一个蓝牙对象/*将这个蓝牙地址改为你的从机输出的蓝牙地址,这里省去了搜索蓝牙的功能,
因此需要手动配置从机的蓝牙地址进行连接。如果需要搜索蓝牙功能,
可以复制上面搜索蓝牙的代码。
*/uint8_t clientAddress[]{0xCC,0x7B,0x5C,0x24,0xC1,0x46};// 蓝牙接收到的信息voidRecvData(constuint8_t*buffer,size_t size){if(size >0){
    Serial.write(buffer, size);//打印出来
    Serial.println();}}voidsetup(){
  Serial.begin(115200);pinMode(LEDPIN, OUTPUT);
  SerialBT.onData(RecvData);//注册接收回调函数//初始化蓝牙设备,设置名称和主机模式if(!SerialBT.begin("ESP32Fish2", true)){
    Serial.println("BT begin failed.");return;}auto start =millis();//指定名称连接//if(!SerialBT.connect("ESP32Fish1"))//根据搜索到的蓝牙地址连接if(!SerialBT.connect(clientAddress)){
    Serial.println("connect failed");return;}auto end =millis();

  Serial.printf("Connect successed: %d \r\n", end-start);}voidloop(){//判断蓝牙设备是否已连接if(SerialBT.connected()){digitalWrite(LEDPIN, HIGH);auto sz = SerialBT.println("Hello");
      Serial.println(sz);}else{digitalWrite(LEDPIN, LOW);}delay(500);}

在主机和从机调试窗口可以看到他们连接成功后互相发送信息。
在这里插入图片描述

4.5.ssp模式双蓝牙收发送信息

1.从机模式
#include"BluetoothSerial.h"#include<esp_bt_device.h>#defineLEDPIN2

BluetoothSerial SerialBT;//定义一个蓝牙对象//认证请求回调voidBTConfirmRequestCallback(uint32_t numVal){//numVal是主机发来的识别码
  Serial.printf("recv pin: %d \r\n", numVal);
  SerialBT.confirmReply(true);}//认证结果回调函数voidBTAuthCompleteCallback(boolean success){if(success)
    Serial.println("Pairing success!!");else
    Serial.println("Pairing failed, rejected by user!!");}voidRecvData(constuint8_t*buffer,size_t size){if(size >0){
    Serial.write(buffer, size);//打印出来
    SerialBT.write(buffer, size);
    SerialBT.println(" - Slave");}}voidsetup(){pinMode(LEDPIN, OUTPUT);
  SerialBT.enableSSP();//在begin之前调用
  SerialBT.onConfirmRequest(BTConfirmRequestCallback);
  SerialBT.onAuthComplete(BTAuthCompleteCallback);
  Serial.begin(115200);
  SerialBT.onData(RecvData);//注册接收回调函数
  SerialBT.begin("ESP32Fish1");//蓝牙的名字叫ESP32Fish, 从机模式auto address =esp_bt_dev_get_address();//获取本机的蓝牙mac地址if(address)//找到地址了{for(int i=0;i<6;i++){
        Serial.printf("%02X", address[i]);if(i<5)
          Serial.print(":");}
      Serial.println();}

  Serial.println("The device started, now you can pair it with bluetooth!");}voidloop(){if(SerialBT.hasClient()){digitalWrite(LEDPIN, HIGH);}else{digitalWrite(LEDPIN, LOW);}delay(200);}
2.主机模式
#include"BluetoothSerial.h"#include<AsyncTimer.h>#defineLEDPIN2

BluetoothSerial SerialBT;//定义一个蓝牙对象/*将这个蓝牙地址改为你的从机输出的蓝牙地址,这里省去了搜索蓝牙的功能,
因此需要手动配置从机的蓝牙地址进行连接。如果需要搜索蓝牙功能,
可以复制上面搜索蓝牙的代码。
*/uint8_t clientAddress[]{0xCC,0x7B,0x5C,0x24,0xC1,0x46};
AsyncTimer t;//认证请求回调voidBTConfirmRequestCallback(uint32_t numVal){
  Serial.print("发送code");//numVal是主机发来的识别码
  Serial.printf("recv pin: %d , (y|n) \r\n", numVal);int num =0;while(true){if(Serial.available()){int ch = Serial.read();if(ch=='Y'|| ch=='y'){
        Serial.println("yes");
        SerialBT.confirmReply(true);break;}elseif(ch=='N'|| ch=='n'){
        Serial.println("no");
        SerialBT.confirmReply(false);break;}if(num++>=20)break;}delay(500);}}//认证结果回调函数voidBTAuthCompleteCallback(boolean success){if(success)
    Serial.println("Pairing success!!");else
    Serial.println("Pairing failed, rejected by user!!");}//接收信息voidRecvData(constuint8_t*buffer,size_t size){if(size >0){
    Serial.write(buffer, size);//打印出来
    Serial.println();}}voidsetup(){
  Serial.begin(115200);pinMode(LEDPIN, OUTPUT);//启用SSP协议
  SerialBT.enableSSP();//设置配对认证请求回调函数
  SerialBT.onConfirmRequest(BTConfirmRequestCallback);//设置配对认证结果回调函数
  SerialBT.onAuthComplete(BTAuthCompleteCallback);
  SerialBT.onData(RecvData);//注册接收回调函数if(!SerialBT.begin("ESP32Fish2", true)){
    Serial.println("BT begin failed.");return;}auto start =millis();if(!SerialBT.connect("ESP32Fish1")){
    Serial.println("connect failed");return;}auto end =millis();

  Serial.printf("Connect successed: %d \r\n", end-start);}voidloop(){
  t.handle();if(SerialBT.hasClient()){digitalWrite(LEDPIN, HIGH);
     
    SerialBT.print("Hello");}else{digitalWrite(LEDPIN, LOW);}delay(2000);}

打开调试窗口,会出现一个验证码,然后在主机的调试窗口发送 y 就可以连接,返送n就拒绝连接。

标签: 网络 物联网 esp32

本文转载自: https://blog.csdn.net/m0_38039437/article/details/140766480
版权归原作者 Bruce小鬼 所有, 如有侵权,请联系我们删除。

“ESP32之经典蓝牙库BluetoothSerial介绍和实例演示”的评论:

还没有评论