Chapter 27 Bluetooth

This chapter mainly introduces how to make simple data transmission through Bluetooth of ESP32-WROVER and mobile phones.

Project 27.1 is classic Bluetooth and Project 27.2 is low power Bluetooth.If you are an iPhone user, please start with Project 27.2.

Project 27.1 Bluetooth Passthrough

Component List

ESP32-WROVER x1

Chapter01_00

Micro USB Wire x1

Chapter08_00

In this tutorial we need to use a Bluetooth APP called Serial Bluetooth Terminal to assist in the experiment. If you’ve not installed it yet, please do so by clicking: https://www.appsapk.com/serial-bluetooth-terminal/ The following is its logo.

../../../_images/Chapter27_00.png

Component knowledge

ESP32’s integrated Bluetooth function Bluetooth is a short-distance communication system, which can be divided into two types, namely Bluetooth Low Energy(BLE) and Classic Bluetooth. There are two modes for simple data transmission: master mode and slave mode.

Master mode

In this mode, works are done in the master device and it can connect with a slave device. And we can search and select slave devices nearby to connect with. When a device initiates connection request in master mode, it requires information of the other Bluetooth devices including their address and pairing passkey. After finishing pairing, it can connect with them directly.

Slave mode

The Bluetooth module in slave mode can only accept connection request from a host computer, but cannot initiate a connection request. After connecting with a host device, it can send data to or receive from the host device.

Bluetooth devices can make data interaction with each other, as one is in master mode and the other in slave mode. When they are making data interaction, the Bluetooth device in master mode searches and selects devices nearby to connect to. When establishing connection, they can exchange data. When mobile phones exchange data with ESP32, they are usually in master mode and ESP32 in slave mode.

../../../_images/Chapter27_01.png

Circuit

Connect Freenove ESP32 to the computer using the USB cable.

../../../_images/Chapter27_02.png

Sketch

Sketch_27.1_SerialToSerialBT

../../../_images/Chapter27_03.png

Compile and upload the code to the ESP32-WROVER, open the serial monitor, and set the baud rate to 115200. When you see the serial printing out the character string as below, it indicates that the Bluetooth of ESP32 is ready and waiting to connect with the mobile phone.

../../../_images/Chapter27_04.png

Make sure that the Bluetooth of your phone has been turned on and Serial Bluetooth Terminal has been installed.

../../../_images/Chapter27_05.png

Click “Search” to search Bluetooth devices nearby and select “ESP32 test” to connect to.

../../../_images/Chapter27_06.png

Turn on software APP, click the left of the terminal. Select “Devices”

../../../_images/Chapter27_07.png

Select ESP32test in classic Bluetooth mode, and a successful connecting prompt will appear as shown on the right illustration.

../../../_images/Chapter27_08.png

And now data can be transferred between your mobile phone and computer via ESP32-WROVER.

Send ‘Hello!’’ from your phone, when the computer receives it, reply “Hi” to your phone.

../../../_images/Chapter27_09.png

Reference

Class BluetoothSerial

This is a class library used to operate BluetoothSerial, which can directly read and set BluetoothSerial. Here are some member functions:

begin(localName,isMaster): Initialization function of the Bluetooth

name: name of Bluetooth module; Data type: String

isMaster: bool type, whether to set Bluetooth as Master. By default, it is false.

available(): acquire digits sent from the buffer, if not, return 0.

read(): read data from Bluetooth, data type of return value is int.

readString(): read data from Bluetooth, data type of return value is String.

write(val): send an int data val to Bluetooth.

write(str): send an Srtring data str to Bluetooth.

write(buf, len): Sends the first len data in the buf Array to Bluetooth.

setPin(const char *pin): set a four-digit Bluetooth pairing code. By default, it is 1234

connet(remoteName): connect a Bluetooth named remoteName, data type: String

connect(remoteAddress[]): connect the physical address of Bluetooth, data type: uint8-t.

disconnect(): disconnect all Bluetooth devices.

end(): disconnect all Bluetooth devices and turn off the Bluetooth, release all occupied space

Project 27.2 Bluetooth Low Energy Data Passthrough

Component List

ESP32-WROVER x1

Chapter01_00

Micro USB Wire x1

Chapter08_00

Circuit

Connect Freenove ESP32 to the computer using the USB cable.

../../../_images/Chapter27_10.png

Sketch

Sketch_27.2_BLE

../../../_images/Chapter27_11.png

Serial Bluetooth

Compile and upload code to ESP32, the operation is similar to the last section.

First, make sure you’ve turned on the mobile phone Bluetooth, and then open the software.

../../../_images/Chapter27_12.png

Click “Search” to search Bluetooth devices nearby and select “ESP32 test” to connect to.

../../../_images/Chapter27_13.png

Turn on software APP, click the left of the terminal. Select “Devices”

../../../_images/Chapter27_14.png

Select BLUETOOTHLE, click SCAN to scan Low Energy Bluetooth devices nearby.

../../../_images/Chapter27_15.png

Select”ESP32-Bluetooth”

../../../_images/Chapter27_16.png

Lightblue

If you can’t install Serial Bluetooth on your phone, try LightBlue.If you do not have this software installed on your phone, you can refer to this link:https://apps.apple.com/us/app/lightblue/id557428110#?platform=iphone.

../../../_images/Chapter27_17.png

Step1. Upload the code of Project27.2 to ESP32.

Step2. Click on serial monitor.

../../../_images/Chapter27_18.png

Step3. Set baud rate to 115200.

../../../_images/Chapter27_19.png

Turn ON Bluetooth on your phone, and open the Lightblue APP.

../../../_images/Chapter27_20.png

In the Scan page, swipe down to refresh the name of Bluetooth that the phone searches for. Click ESP32_Bluetooth.

../../../_images/Chapter27_21.png

Click “Receive”. Select the appropriate Data format in the box to the right of Data Format. For example, HEX for hexadecimal, utf-string for character, Binary for Binary, etc. Then click SUBSCRIBE.

../../../_images/Chapter27_22.png

Back to the serial monitor on your computer. You can type anything in the left border of Send, and then click Send.

../../../_images/Chapter27_23.png

And then you can see the mobile Bluetooth has received the message.

../../../_images/Chapter27_24.png

Similarly, you can select “Send” on your phone. Set Data format, and then enter anything in the sending box and click Write to send.

../../../_images/Chapter27_25.png

And the computer will receive the message from the mobile Bluetooth.

../../../_images/Chapter27_25.png

And now data can be transferred between your mobile phone and computer via ESP32-WROVER.

The following is the program code:

 1/**********************************************************************
 2  Filename    : BLE_USART
 3  Description : Esp32 communicates with the phone by BLE and sends incoming data via a serial port
 4  Auther      : www.freenove.com
 5  Modification: 2024/06/19
 6**********************************************************************/
 7#include "BLEDevice.h"
 8#include "BLEServer.h"
 9#include "BLEUtils.h"
10#include "BLE2902.h"
11
12BLECharacteristic *pCharacteristic;
13bool deviceConnected = false;
14uint8_t txValue = 0;
15long lastMsg = 0;
16String rxload="Test\n";
17
18#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" 
19#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
20#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
21
22class MyServerCallbacks: public BLEServerCallbacks {
23    void onConnect(BLEServer* pServer) {
24      deviceConnected = true;
25    };
26    void onDisconnect(BLEServer* pServer) {
27      deviceConnected = false;
28      //pServer->getAdvertising()->start();  //Reopen the pServer and wait for the connection.
29    }
30};
31
32class MyCallbacks: public BLECharacteristicCallbacks {
33    void onWrite(BLECharacteristic *pCharacteristic) {
34      String rxValue = pCharacteristic->getValue();
35      if (rxValue.length() > 0) {
36        rxload="";
37        for (int i = 0; i < rxValue.length(); i++){
38          rxload +=(char)rxValue[i];
39        }
40      }
41    }
42};
43
44void setupBLE(String BLEName){
45  const char *ble_name=BLEName.c_str();
46  BLEDevice::init(ble_name);
47  BLEServer *pServer = BLEDevice::createServer();
48  pServer->setCallbacks(new MyServerCallbacks());
49  BLEService *pService = pServer->createService(SERVICE_UUID); 
50  pCharacteristic= pService->createCharacteristic(CHARACTERISTIC_UUID_TX,BLECharacteristic::PROPERTY_NOTIFY);
51  pCharacteristic->addDescriptor(new BLE2902());
52  BLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RX,BLECharacteristic::PROPERTY_WRITE);
53  pCharacteristic->setCallbacks(new MyCallbacks()); 
54  pService->start();
55  pServer->getAdvertising()->start();
56  Serial.println("Waiting a client connection to notify...");
57}
58
59void setup() {
60  Serial.begin(115200);
61  setupBLE("ESP32_Bluetooth");
62}
63
64void loop() {
65  long now = millis();
66  if (now - lastMsg > 100) {
67    if (deviceConnected&&rxload.length()>0) {
68        Serial.println(rxload);
69        rxload="";
70    }
71    if(Serial.available()>0){
72        String str=Serial.readString();
73        const char *newValue=str.c_str();
74        pCharacteristic->setValue(newValue);
75        pCharacteristic->notify();
76    }
77    lastMsg = now;
78  }
79}

Define the specified UUID number for BLE vendor.

1#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" 
2#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
3#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

Write a Callback function for BLE server to manage connection of BLE.

1class MyServerCallbacks: public BLEServerCallbacks {
2    void onConnect(BLEServer* pServer) {
3      deviceConnected = true;
4    };
5    void onDisconnect(BLEServer* pServer) {
6      deviceConnected = false;
7      //pServer->getAdvertising()->start();  //Reopen the pServer and wait for the connection.
8    }
9};

Write Callback function with BLE features. When it is called, as the mobile terminal send data to ESP32, it will store them into reload.

 1class MyCallbacks: public BLECharacteristicCallbacks {
 2    void onWrite(BLECharacteristic *pCharacteristic) {
 3      String rxValue = pCharacteristic->getValue();
 4      if (rxValue.length() > 0) {
 5        rxload="";
 6        for (int i = 0; i < rxValue.length(); i++){
 7          rxload +=(char)rxValue[i];
 8        }
 9      }
10    }
11};

Initialize the BLE function and name it.

1setupBLE("ESP32_Bluetooth");

When the mobile phone send data to ESP32 via BLE Bluetooth, it will print them out with serial port; When the serial port of ESP32 receive data, it will send them to mobile via BLE Bluetooth.

 1long now = millis();
 2if (now - lastMsg > 100) {
 3  if (deviceConnected&&rxload.length()>0) {
 4      Serial.println(rxload);
 5      rxload="";
 6  }
 7  if(Serial.available()>0){
 8      String str=Serial.readString();
 9      const char *newValue=str.c_str();
10      pCharacteristic->setValue(newValue);
11      pCharacteristic->notify();
12  }
13  lastMsg = now;
14}

The design for creating the BLE server is:

  1. Create a BLE Server

  2. Create a BLE Service

  3. Create a BLE Characteristic on the Service

  4. Create a BLE Descriptor on the characteristic

  5. Start the service.

  6. Start advertising.

 1void setupBLE(String BLEName){
 2  const char *ble_name=BLEName.c_str();
 3  BLEDevice::init(ble_name);
 4  BLEServer *pServer = BLEDevice::createServer();
 5  pServer->setCallbacks(new MyServerCallbacks());
 6  BLEService *pService = pServer->createService(SERVICE_UUID); 
 7  pCharacteristic= pService->createCharacteristic(CHARACTERISTIC_UUID_TX,BLECharacteristic::PROPERTY_NOTIFY);
 8  pCharacteristic->addDescriptor(new BLE2902());
 9  BLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RX,BLECharacteristic::PROPERTY_WRITE);
10  pCharacteristic->setCallbacks(new MyCallbacks()); 
11  pService->start();
12  pServer->getAdvertising()->start();
13  Serial.println("Waiting a client connection to notify...");
14}

Project 27.3 Bluetooth Control LED

In this section, we will control the LED with Bluetooth.

Component List

ESP32-WROVER x1

Chapter01_00

GPIO Extension Board x1

Chapter01_01

Micro USB Wire x1

Chapter08_00

Breadboard x1

Chapter01_02

LED x1

Chapter01_03

Resistor 220Ω x1

Chapter01_04

Jumper M/M x2

Chapter01_05

Circuit

Connect Freenove ESP32 to the computer using a USB cable.

Schematic diagram

Chapter27_27

Hardware connection

If you need any support, please feel free to contact us via: support@freenove.com

Chapter27_28

Sketch

Sketch_27.3_Bluetooth_Control_LED

../../../_images/Chapter27_29.png

Compile and upload code to ESP32. The operation of the APP is the same as 27.1, you only need to change the sending content to “led_on” and “led_off” to operate LEDs on the ESP32-WROVER.

Data sent from mobile APP:

../../../_images/Chapter27_30.png

Display on the serial port of the computer:

../../../_images/Chapter27_31.png

The phenomenon of LED

../../../_images/Chapter27_32.png

Attention

If the sending content isn’t “led-on’ or “led-off”, then the state of LED will not change. If the LED is on, when receiving irrelevant content, it keeps on; Correspondingly, if the LED is off, when receiving irrelevant content, it keeps off.

The following is the program code:

 1/**********************************************************************
 2  Filename    : SerialToLED
 3  Description : The phone controls esp32's led via bluetooth.
 4                When the phone sends "led_on," ESP32's LED lights turn on.
 5                When the phone sends "led_off," ESP32's LED lights turn off.
 6  Auther      : www.freenove.com
 7  Modification: 2024/06/19
 8**********************************************************************/
 9#include "BluetoothSerial.h"
10#include "string.h"
11#define LED 2
12BluetoothSerial SerialBT;
13char buffer[20];
14static int count = 0;
15void setup() {
16  pinMode(LED, OUTPUT);
17  SerialBT.begin("ESP32test"); //Bluetooth device name
18  Serial.begin(115200);
19  Serial.println("\nThe device started, now you can pair it with bluetooth!");
20}
21
22void loop() {
23  while(SerialBT.available())
24  {
25    buffer[count] = SerialBT.read();
26    count++;
27  }
28  if(count>0){
29    Serial.print(buffer);
30    if(strncmp(buffer,"led_on",6)==0){
31      digitalWrite(LED,HIGH);
32    }
33    if(strncmp(buffer,"led_off",7)==0){
34      digitalWrite(LED,LOW);
35    }
36    count=0;
37    memset(buffer,0,20);
38  }
39}

Use character string to handle function header file.

1#include "string.h"

Define a buffer to receive data from Bluetooth, and use “count” to record the bytes of data received.

1char buffer[20];
2static int count = 0;

Initialize the classic Bluetooth and name it as “ESP32test”

1SerialBT.begin("ESP32test"); //Bluetooth device name

When receive data, read the Bluetooth data and store it into buffer array.

1while(SerialBT.available())
2{
3  buffer[count] = SerialBT.read();
4  count++;
5}

Compare the content in buffer array with “led_on” and “led_off” to see whether they are the same. If yes, execute the corresponding operation.

1if(strncmp(buffer,"led_on",6)==0){
2  digitalWrite(LED,HIGH);
3}
4if(strncmp(buffer,"led_off",7)==0){
5  digitalWrite(LED,LOW);
6}

After comparing the content of array, to ensure successful transmission next time, please empty the array and set the count to zero.

1count=0;
2memset(buffer,0,20);

Reference

strncmp() functions are often used for string comparisons, which are accurate and stable.

int strncmp(const char *str1, const char *str2, size_t n)

str1: the first string to be compared

str2: the second string to be compared

n: the biggest string to be compared

Return value: if stir1>str2, then return value>0.

If return value is 0, then the contents of str1 and str2 are the same.

If str1< str2, then return value<0.

Function memset is mainly used to clean and initialize the memory of array

void *memset(void *s, int c, unsigned long n)

Function memset() is to set the content of a certain internal storage as specified value.

*s: the initial address of the content to clear out.

c:to be replaced as specified value

n: the number of byte to be replaced