玩转物联网人工智能小车:实现ESP32间蓝牙通信功能
摘要:本文介绍ESP32处理器之间如何进行蓝牙通信
关于蓝牙通信的基本知识在前边已经介绍过了,并且还详细说明了与电脑的连接方法,并通过串口调试终端程序实现了电脑与ESP32模块的交互。如果想了解更基础的内容,请参考之前的文档。
那么在今天所要讲述的是如何实现ESP32之间的蓝牙通信。在进行通信之前,先来了解一下蓝牙设备的主从关系。像前面学习的I2C、SPI、I2S通信协议一样,蓝牙通信技术中也是存在主从设备概念的。蓝牙通信中的主设备通常是指主动发起蓝牙连接的设备,而从设备则是被动接受连接的设备。例如,在手机与蓝牙耳机之间的连接中,手机充当主设备,而耳机则是从设备。在之前进行的ESP32与电脑或者手机的蓝牙通信中,电脑或者手机是主设备,发起蓝牙连接。而ESP32处理器则是从设备,等待主设备发起连接。
主设备负责发起连接请求和管理连接状态,从设备在收到连接请求后进行确认和连接操作。主从设备之间的连接可以是一对一的连接,也可以是一对多的连接,这取决于具体应用场景的需求。
在蓝牙通信中,从设备可以设置一个验证的PIN码,也叫配对码或者密码。其目的是为了放置别人误接入或者恶意接入你的蓝牙设备,是一种安全措施,具体是否使用看个人情况。PIN码为4-16位的数字,可以根据自身情况设置,一般蓝牙耳机的PIN码是“0000”或者“1234”。在ESP32中,需要调用setPin()方法来进行设置,如下所示:
const char *pin = "1234"; SerialBT.setPin(pin); |
主从设备都可以使用这个方法来设置PIN码,从设备使用这个方法设置的时候,就是要求发起链接的设备要输入这个PIN码。而主设备使用这个方法设置的时候,则表示将会使用这个PIN码去建立与从设备的连接。
今天来开发一个双ESP32设备使用蓝牙进行通信的样例程序,有了这个程序,相信大家可以很方便的实现一个蓝牙遥控器,再接入上一期介绍的游戏手柄之后,就可以用蓝牙遥控你的小车了。
这个程序的功能是一个ESP32所为从设备(模拟小车),接受来自主设备的连接请求,在收到主设备发来的字符串信息后,将其转换为大写后再发送回去(这相当于接受主设备的命令,并执行)。而另一个ESP32设备则是主设备(模拟遥控器),建立与从设备的连接后,将串口收到的字符发送给从设备,并显示从设备返回的结果(这相当于发送指令,并查看执行结果)。
下面先看一下蓝牙从机程序,如下所示:
/******************************* ** 蓝牙通信从机测试程序 **** ******************************* ***** 一起玩儿科技 ********** *******************************/
#include "BluetoothSerial.h" #include <ctype.h>
#define USE_PIN const char *pin = "1234";
// 蓝牙名称 String device_name = "ESP32-BT-Slave";
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED) #error Bluetooth is not enabled! Please run `make menuconfig` to and enable it #endif
#if !defined(CONFIG_BT_SPP_ENABLED) #error Serial Bluetooth not available or not enabled. It is only available for the ESP32 chip. #endif
BluetoothSerial SerialBT;
void setup() { Serial.begin(115200); SerialBT.begin(device_name); //蓝牙名称 Serial.printf("设备\"%s\"已启动。\n可以配对与我连接了!\n", device_name.c_str()); #ifdef USE_PIN SerialBT.setPin(pin); Serial.println("启用PIN!"); #endif }
void loop() { if (SerialBT.available()) { char c = SerialBT.read(); Serial.write(c); SerialBT.write(toupper(c)); } delay(20); } |
这个程序除了增加了一个PIN的设置功能外,和之前的程序没有太大的差别,在这里就不进一步的解释了。
下面来看一下蓝牙主机的程序,如下所示:
/******************************* ** 蓝牙通信主机测试程序 **** ******************************* ***** 一起玩儿科技 ********** *******************************/
#include "BluetoothSerial.h"
#define USE_NAME const char *pin = "1234";
#if !defined(CONFIG_BT_SPP_ENABLED) #error Serial Bluetooth not available or not enabled. It is only available for the ESP32 chip. #endif
BluetoothSerial SerialBT;
// 定义从机蓝牙名称 String slaveName = "ESP32-BT-Slave"; // 定义蓝牙主机名称 String myName = "ESP32-BT-Master";
void setup() { bool connected; Serial.begin(115200);
SerialBT.begin(myName, true); Serial.printf("主设备\"%s\"已启动, 请确保从设备已启动!\n", myName.c_str());
#ifndef USE_NAME SerialBT.setPin(pin); Serial.println("启用PIN!"); #endif
connected = SerialBT.connect(slaveName); Serial.printf("正在连接到从设备:\"%s\"\n", slaveName.c_str());
if (connected) { Serial.println("连接成功!"); } else { while (!SerialBT.connected(10000)) { Serial.println("连接失败,请确保从设备已经启动并在范围之内!"); } } // 断开连接 if (SerialBT.disconnect()) { Serial.println("断开成功!"); } // 再次连接 SerialBT.connect(); if (connected) { Serial.println("再次连接成功!"); } else { while (!SerialBT.connected(10000)) { Serial.println("连接失败,请确保从设备已经启动并在范围之内!"); } } }
void loop() { if (Serial.available()) { char c = Serial.read(); Serial.write(c); SerialBT.write(c); } if (SerialBT.available()) { //Serial.write("收到:"); Serial.write(SerialBT.read()); } delay(20); } |
作为主设备的初始化与从设备没什么区别,不一样的是,在初始化之后,主设备要主动的去连接从设备,调用的方法为connect(),其参数为从设备的名称。除了使用从设备的名称与从设备进行连接外,还可以使用从设备的MAC地址与从设备进行连接。
MAC地址(英语:Media Access Control Address),直译为媒体存取控制位址,也称为局域网地址(LAN Address),MAC位址,以太网地址(Ethernet Address)或物理地址(Physical Address),它是一个用来确认网络设备位置的位址。每一个联网的设备都要有一个MAC地址,并且这个地址在同一个局域网内不能与其他设备相同,否则将无法进行正常的通信。
在上面的程序中,连接成功后,又进行了断开和再次连接的测试。后边关于数据收发的处理就不再解释了,之前已经进行过类似的介绍了。
作者:一起玩儿科技