Most people associate the ESP family of microcontrollers with WiFi, which makes sense, as they�ve become the go-to solution for getting your project online quickly and easily. However, while WiFi capability might be the star of the show, the ESP32 is also equipped with Bluetooth. It�s just that we don�t see it being used as frequently.
If you�re interested in using Bluetooth on the ESP32, this tutorial is an excellent starting point.
About ESP32 Bluetooth
The ESP32 supports dual-mode Bluetooth, which means it supports both Bluetooth Classic and Bluetooth Low Energy (BLE). While these two protocols share many important things such as architecture, and both operate in 2.4 GHz ISM (Industrial, Scientific, and Medical) band, they�re quite different from each other.
Bluetooth Classic
The original Bluetooth technology�what we�re familiar with from our smartphones linking to our wireless earbuds�is now known as Bluetooth Classic. If you�ve ever used Bluetooth-to-Serial-Bridge modules like the HC-05 or HC-06 with an Arduino, you�ve unknowingly used Bluetooth Classic.
Bluetooth Classic is designed for continuous two-way data transfer with high application throughput (up to 3 Mbps); highly effective, but only for short distances. It uses over 79 channels in the 2.4 GHz ISM band.
This type of Bluetooth is mainly employed in projects where you need to continuously stream data like audio streaming or file transfer.
This tutorial will teach you how to use Bluetooth Classic on the ESP32.
Bluetooth Low Energy (BLE)
Bluetooth LE, originally marketed as Bluetooth Smart and commonly referred to as just BLE, is designed for very low power operation while maintaining a similar communication range. However, BLE is much more than a low-power version of Bluetooth Classic. BLE operates in the same radio spectrum range as Bluetooth Classic, but uses a different set of 40 channels at a lower data rate (up to 1 Mbps).
It�s well-suited for IoT projects where power consumption is a main concern�for example, a project where you need to wake up the device periodically, gather sensor data, transmit it using Bluetooth, and then return to sleep mode.
As using ESP32 BLE is a little more complicated than using Bluetooth Classic, we�ve covered that in a separate tutorial.
Bluetooth Classic vs. BLE
BLE is primarily used to save power, but there are actually several important differences.
Power Consumption: Bluetooth Classic typically consumes more power (around 1 W), while BLE is designed for low power consumption (typically between 0.01 and 0.5 W), making it suitable for battery-powered devices that need to operate for extended periods.
Data Transfer Rates: Bluetooth Classic provides higher data rates than BLE, making it suitable for projects that require continuous and high-speed data transmission, while BLE is optimized for short bursts of data transmission.
Range: Both BLE and Classic can cover up to 100 meters, but the exact distance varies depending on the environment and implementation.
Latency: Bluetooth Classic connections have a latency of up to 100 ms, while BLE connections have a latency of 6 ms. Keep in mind that lower is better.
Compatibility: Bluetooth Classic is more prevalent in older devices, while BLE is commonly used in modern smartphones and other gadgets.
Take a look at the table below that compares BLE and Bluetooth Classic in more detail.
Bluetooth Classic | Bluetooth Low Energy (BLE) | |
Data Rate | 1 Mbps for BR2-3 Mbps for EDR | 500 kbps � 1 Mbps |
Frequency Band | 2.4 GHz ISM band | 2.4 GHz ISM band |
Number of Channels | 79 Channels with 1 MHz spacing | 40 Channels with 2 MHz spacing |
Communication Range | 8 m up to 100 m | 8 m up to 100 m |
Power Consumption | High (up to 1 W) | Low (0.01 W up to 0.5 W) |
Device Pairing is Mandatory? | YES | NOT Mandatory |
Supported Topologies | Point-to-Point (1:1) | Point-to-Point (1:1)Broadcast (1:many)Mesh (many:many) |
Modulation Technique | GFSK?/4 DQPSK8 DPSK | GFSK |
Latency | 35ms | 2-16ms (Avg. 9ms) |
ESP32 Bluetooth Protocol Stack
Before we proceed, it�s important to understand the Bluetooth protocol stack. This will help you understand why we�re using certain functions in our code.
Basically, the Bluetooth protocol stack is split into two parts: a �host stack� and a �controller stack�.
The host is the main CPU that runs a Bluetooth stack. ESP-IDF currently supports two host stacks. The BLUEDROID-based stack (default) supports Bluetooth Classic as well as BLE. On the other hand, the Apache NimBLE-based stack is BLE only.
The controller stack controls the Bluetooth radio. It acts, essentially, like a data pipeline: serial data that it receives is passed out the Bluetooth connection, and data coming in from the Bluetooth side is passed out the host.
The VHCI interface (software-implemented virtual HCI interface) enables communication between the host and the controller.
For more information, check out Espressif�s Bluetooth architecture description.
Bluetooth Serial Sketch
Now let�s program the ESP32 so that it can communicate with our smartphone and exchange data with it.
We will be using the Arduino IDE to program the ESP32, so please ensure you have the ESP32 add-on installed before you proceed:
Open your Arduino IDE, and go to File > Examples > BluetoothSerial > SerialtoSerialBT. The following code should load.
#include "BluetoothSerial.h"
#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("ESP32test"); //Bluetooth device name
Serial.println("The device started, now you can pair it with bluetooth!");
}
void loop() {
if (Serial.available()) {
SerialBT.write(Serial.read());
}
if (SerialBT.available()) {
Serial.write(SerialBT.read());
}
delay(20);
}
Once you have uploaded the sketch, open the serial monitor at baud rate 115200. You should see a message saying: �The device started, now you can pair it with bluetooth!�.
Code Explanation:
This code establishes two-way serial Bluetooth communication between two devices. The code begins by including the BluetoothSerial.h library, which provides the necessary functionalities for serial operations over Bluetooth.
#include "BluetoothSerial.h"
The next piece of code checks if Bluetooth is properly enabled.
#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
Next, an object of the BluetoothSerial class, named SerialBT
, is created. This initializes the Bluetooth stack on the ESP32 and handles the transmission and reception of data. You can check out the implementation file for this class here. Internally, this class uses IDF�s Bluetooth Classic API.
BluetoothSerial SerialBT;
In the setup, a serial communication is established at a baud rate of 115200.
Serial.begin(115200);
Following that, the begin()
method of the BluetoothSerial object is called, taking care of the lower-level initialization of the Bluetooth stack. This method accepts a string input containing the desired Bluetooth device name. This name is visible to other Bluetooth-enabled devices during their discovery process. By default, it�s called ESP32test
, but you can rename it and give it a unique name.
Note that this method returns a Boolean value, indicating whether the initialization succeeded or not. For now, we have not checked that value, but for a robust code you should always include error checks.
SerialBT.begin("ESP32test"); //Bluetooth device name
The loop section allows bidirectional data transfer between the Serial Monitor and the ESP32 Bluetooth serial.
The first if
statement checks if there is any data available on the standard serial port (like when you send data from a serial monitor on a PC). If data is available, it is read using Serial.read()
and sent over the Bluetooth serial connection using SerialBT.write()
. So, any data you send from your computer via the serial port is forwarded to the connected Bluetooth device.
if (Serial.available()) {
SerialBT.write(Serial.read());
}
The next if
statement checks if there�s any data available from the Bluetooth serial connection (like when a paired Bluetooth device sends some data). If data is available, it is read using SerialBT.read()
and sent to the Serial Monitor using Serial.write()
. So, any data received from the Bluetooth device is forwarded to your Serial Monitor.
if (SerialBT.available()) {
Serial.write(SerialBT.read());
}
Connecting to the Android Phone
Let�s set up a wireless connection between the ESP32 and an Android phone. The process may vary depending on the device, but the general steps are quite similar.
1. Make sure the ESP32 is powered up and ready to establish a connection.
2. Now, swipe down from the top of your Android phone�s screen and make sure Bluetooth is turned on.
3. Touch and hold the Bluetooth icon, then tap �Pair new device� and wait a few seconds.
4. Tap the name of the Bluetooth device you want to pair with your device (in our case, ESP32test). Follow any on-screen instructions.
5. For the next steps in this tutorial, you need a Bluetooth Terminal application installed on your smartphone. We recommend using the Android app �Serial Bluetooth Terminal,� available in the Play Store.
6. After installing, launch the �Serial Bluetooth Terminal� app. Click on the icon in the top left corner and choose �Devices�.
7. You should see a list of devices you�ve previously paired with. Select �ESP32test� from this list.
8. You should get a �Connected� message. That�s it! Your smartphone is now successfully paired with the ESP32 and ready to communicate.
9. Now, type something in the input box located at the bottom of the app, for example, �Hi!�
10. You should instantly receive that message in the Arduino IDE Serial Monitor.
11. You can also exchange data between your Serial Monitor and your smartphone. Type something in the Serial Monitor�s top input box and press the �Send� button.
12. You should instantly receive that message in the Serial Bluetooth Terminal App.
ESP32 Project: Bluetooth-Controlled Relay
Let�s create a simple project that lets you control relays wirelessly using Bluetooth. This can be useful for home automation, smart lighting, security systems, and other similar applications.
Wiring
Connect the relay module to the ESP32 as depicted in the following diagram. The diagram shows the wiring for a 2-channel relay module; wiring for a different number of channels is similar.
ESP32 Code
Once you are done with the wiring, try the below sketch.
#include "BluetoothSerial.h"
#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
// GPIO where relay is connected to
const int relayPin = 5;
// Handle received messages
String message = "";
// Create BluetoothSerial object
BluetoothSerial SerialBT;
void setup() {
// Begin serial communication with Arduino and Arduino IDE (Serial Monitor)
Serial.begin(115200);
// Initialize relayPin as an output
pinMode(relayPin, OUTPUT);
digitalWrite(relayPin, HIGH);
// Initialize the Bluetooth stack
SerialBT.begin("ESP32test"); //Bluetooth device name
Serial.println("The device started, now you can pair it with bluetooth!");
}
void loop() {
if (SerialBT.available()){
char incomingChar = SerialBT.read();
if (incomingChar != '\n'){
message += String(incomingChar);
}
else{
message = "";
}
Serial.write(incomingChar);
}
// Check received message and control output accordingly
if (message == "on"){
digitalWrite(relayPin, LOW);
}
else if (message == "off"){
digitalWrite(relayPin, HIGH);
}
delay(20);
}
Testing the Code
Once you have uploaded the sketch, open the serial monitor at baud rate 115200 and press the EN button. You should see a message saying: �The device started, now you can pair it with bluetooth!�.
Launch the Serial Bluetooth Terminal app and connect to your ESP32.
Now, as you type �on� in the input box at the bottom of the app, the relay should activate instantly. Likewise, typing �off� will deactivate the relay immediately.
Additionally, you will receive these messages in the Arduino IDE Serial Monitor for monitoring purposes.
The app offers several macros that you can customize to save default messages. For instance, you can associate M1 with the �on� message and M2 with the �off� message. This way, you can easily control the relay using the predefined macros, adding an extra layer of convenience to your project.