ESP32 Arduino Bluetooth classic: Getting started

In this article, we will check how to get started using Bluetooth classic on the Arduino core, running on the ESP32. The tests of this ESP32 tutorial were performed using a DFRobot’s ESP-WROOM-32 device integrated in a ESP32 FireBeetle board.

 

Introduction

In this article, we will check how to get started using Bluetooth classic on the Arduino core, running on the ESP32.

At the time of writing, there aren’t yet higher level abstractions available on the Arduino core to use the Bluetooth classic functionality provided by the IDF (official ESP32 development framework) lower level APIs. Thus, we are going to use those lower level APIs to get started with Bluetooth.

As mentioned before, we are going to use the Arduino environment to program the ESP32. This is possible since we can call IDF APIs from the Arduino core, pretty much like we do to use FreeRTOS in this environment.

Note however that higher level and simpler to use functions should be arriving to the Arduino core soon. For example, at the time of writing, there’s this pull request open from Copercini that implements a UART to Bluetooth classic bridge for the ESP32, which provides a very high level API much similar to the Serial interface that’s available in the Arduino libraries.

Nonetheless, knowing how to use the lower level APIs is always an advantage because it not only allows us to better understand what happens under the hood but also because these APIs tend to be much more flexible.

The code we are going to analyze in this tutorial is going to be based on the previously mentioned Pull Request, which also uses the IDF API under the hood.

In this example, we will simply start the Bluetooth interface and make the ESP32 discoverable from other Bluetooth enabled devices.

The tests of this ESP32 tutorial were performed using a DFRobot’s ESP-WROOM-32 device integrated in a ESP32 FireBeetle board.


IDF’s Bluetooth architecture

Before we start with the code, it is important to understand a bit more about how Bluetooth works on The ESP32. This will help us understand why we are calling some of the functions in our code. A very good document to get started is this Espressif’s Bluetooth architecture description.

In general, the Bluetooth protocol has two main stacks, one on top of the other [1][2]. The lower level stack is called the controller stack and the higher level is called the host stack [1][3].

These two stacks are implemented independently because the communication interface between them is well defined [4].

The controller stack is responsible for handling the exchange of Bluetooth packets between devices and to manage the radio interface [5]. The host stack deals with higher level data [5].

One interesting thing to mention is that the host stack can be implemented on the same device of the controller stack or in a different one, and both scenarios are supported by the ESP32 [1].

In IDF, the available host stack is Bluedroid, for both Bluetooth classic and Bluetooth low energy [1].

In our application, we will have both the controller and the host stack running on the ESP32.


Getting the binary of the Bluetooth library

In order to be able to use the full Bluetooth functionality, we need to have the core compiled with some additional configurations, as indicated in the Pull Request mentioned on the introductory section.

At the time of writing, this was not available on the Arduino core yet, which is why the PR included a new version of the compiled BT lib.

When the PR is merged, the procedure from this section should no longer be needed. Nonetheless, for those who are following the tutorial before that, this will explain how to get that binary and where to place it

So, go to the files changed section of the mentioned PR and look for the libbt.a file. It should have a “Binary file not shown” message instead of displaying any content. On the right side, click the “view” button, as highlighted in figure 1.

ESP32 Arduino Bluetooth download binary

Figure 1 – Viewing the binary file.

On the new page, simply click the “download” button (highlighted in figure 2), and the file should get transferred to your computer.

ESP32 Arduino Bluetooth binary download button

Figure 2 – Downloading the binary file.

To finalize, go to your ESP32 installation (where you have installed the Arduino core for the ESP32) and place the file in the following directory:

tools/sdk/lib/libbt.a

It will ask you to replace the existing file. You can make a copy of the old one before proceeding with the replace, so you can revert the changes if needed.

As mentioned, this is only needed if the version of the Arduino core you are working with still doesn’t have the latest binary (which is the case at the time of writing this article). If you can compile the code below without getting any error, then you shouldn’t need to do the procedure from this section.

Also, make sure you are using the latest version of the Arduino core, since the Bluetooth classic functionality has arrived very recently.

If you have followed the procedure indicated in the GitHub page of the Arduino core to install it, then you can check here the update section. If you know how to use Git in the command line, you can simply pull the latest version of the master branch.


The code

We will start by including the libraries needed to access the Bluetooth functionality. The first library we need is the esp_bt_main.h. You can check the implementation file in IDF here.

This library will make available the functions we need to initialize the Bluedroid stack.

#include "esp_bt_main.h"

Additionally, we will need the esp_gap_bt_api.h library (implementation file here). This library will expose the API needed to use the functionalities of the Generic Access Profile (GAP), which defines how devices find each other and how they establish a connection  using the Bluetooth protocol [6].

Without configuring this, even if we initialized the Bluedroid stack, the device would not be discoverable, since that part of the Bluetooth protocol is handled by this profile.

#include "esp_gap_bt_api.h"

Next we will handle the initialization of the two Bluetooth stacks (controller and host). Since, as mentioned, this code is based on the existing Pull Request for the Arduino core, we will be keeping the same name of the initializing function used there. We will latter call it from the Arduino setup function.

static bool _init_bt(){
...
}

Inside this function, the first thing we need to do is initialize the controller stack. We can do it using the btStart function defined here.

This function takes no arguments and returns true if the the controller was correctly initialized and false otherwise.

if(!btStart()){
    Serial.println("Failed to initialize controller");
    return false;
}

Next we will initialize the Bluedroid stack. This is done with a call to the esp_bluedroid_init function.

This function takes no arguments and returns a value of type esp_err_t (defined here). In case of success, it will return ESP_OK.

if (esp_bluedroid_init()!= ESP_OK) {
    Serial.println("Failed to initialize bluedroid");
    return false;
}

After the initialization, we need to enable the Bluedroid stack. We do it with a call to the esp_bluedroid_enable function. This function also takes no arguments and returns ESP_OK in case of success.

if (esp_bluedroid_enable()!= ESP_OK) {
    Serial.println("Failed to enable bluedroid");
    return false;
}

Now that we have initialized and enabled both stacks, we need to set our ESP32 as discoverable. Otherwise, we will not be able to find it from other devices.

We do this by calling the esp_bt_gap_set_scan_mode function. This function receives as input the scan mode, which is an enum of type esp_bt_scan_mode_t.

We will use the value ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE, which means the device is set to be both discoverable and connectable.

esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);

This completes the code for the Bluetooth initialization. Now we simply need to call it from the Arduino setup function and our device should become discoverable. You can check the final source code below.

#include "esp_bt_main.h"
#include "esp_gap_bt_api.h"

static bool _init_bt()
{
  if (!btStart()) {
    Serial.println("Failed to initialize controller");
    return false;
  }

  if (esp_bluedroid_init()!= ESP_OK) {
    Serial.println("Failed to initialize bluedroid");
    return false;
  }

  if (esp_bluedroid_enable()!= ESP_OK) {
    Serial.println("Failed to enable bluedroid");
    return false;
  }

  esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);

}

void setup() {
  _init_bt();
}

void loop() {}


Testing the code

To test the code, simply compile it and upload it to your ESP32 using the arduino IDE. Once the procedure finishes, the ESP32 should be visible from other Bluetooth enabled devices, as shown in figure 1.

ESP32 Arduino Bluetooth classic getting started

Figure 1 – ESP32 discoverable from an Android smartphone.

Note that what appears in the image is the address of the device, since we didn’t configure a name for the device. Depending on the device from where you are doing the search, it may display the Bluetooth address of the ESP32 or other generic name.

Please note that this is a  very simple getting started example, so it only makes the device discoverable. Don’t try to pair it since it won’t work.


Related content


Related posts


References

[1]https://www.espressif.com/sites/default/files/documentation/esp32_bluetooth_architecture_en.pdf

[2] https://atadiat.com/en/micros/e-why-its-called-bluetooth-stack/

[3] http://dev.ti.com/tirex/content/simplelink_cc2640r2_sdk_1_35_00_33/docs/ble5stack/ble_user_guide/html/ble-stack/overview.html

[4] https://developer.apple.com/library/content/documentation/DeviceDrivers/Conceptual/Bluetooth/BT_Bluetooth_Basics/BT_Bluetooth_Basics.html#//apple_ref/doc/uid/TP30000997-CH214-CHDJHFEF

[5] https://en.wikipedia.org/wiki/List_of_Bluetooth_protocols#Controller_stack

[6] https://bluekitchen-gmbh.com/btstack/protocols/

14 thoughts on “ESP32 Arduino Bluetooth classic: Getting started”

  1. Pingback: ESP32 Arduino Bluetooth Classic: Controlling a relay remotely | techtutorialsx

  2. Pingback: ESP32 Arduino Bluetooth Classic: Controlling a relay remotely | techtutorialsx

  3. Mauro Bilotti

    Thanks a lot, Very helpful!! Probably I will post a few questions since I’m starting with the Esp32 development. Thanks in advance!

    1. Hi!

      You’re welcome, I’m glad you found the content useful and thanks for the feedback 🙂

      Feel free to ask 🙂

      And good luck with your learning process on the ESP32 development!

      Best regards,
      Nuno Santos

  4. Mauro Bilotti

    Thanks a lot, Very helpful!! Probably I will post a few questions since I’m starting with the Esp32 development. Thanks in advance!

    1. Hi!
      You’re welcome, I’m glad you found the content useful and thanks for the feedback 🙂
      Feel free to ask 🙂
      And good luck with your learning process on the ESP32 development!
      Best regards,
      Nuno Santos

  5. My English is not very good. I’m sorry for that. ble or classic … I want to protect the device with a password. Not every phone can connect.

    I don’t want to keep you busy … Is there a way to do this? An example link you can share?

    thank you…

      1. If you were, in terms of power management, would you choose a product like cc2541 for bluetooth or esp32?

        Not broadcast, but I want to use it as a recipient. It needs to work with a battery like 10.000 mAh for about 6 months.

        cc2541 seems to be better in terms of power management. Today I asked a question to their firm, I would like to know your opinion …

        “My question; Related to cc2541. A few sentences will suffice. I’m looking for a power mode. At this feature; can be connected to receive data. But a power mode with little power consumption until connected. So do not periodically sleep or wake up.

        Assumption example; when there is data reception or transmission, typically> 15mAh. But when there is no data reception or sending <1mAh but it can still be connected. So he can be seen from the phone.

        Is it possible ?"

        Thanks…

        1. Hi!

          Unfortunately I’ve never worked much in the power management area, so I’m not the best person to answer to your question. :/

          Nonetheless, maybe some of the readers might already have analyzed that in more depth than I did and can share their opinion 🙂

          Best regards,
          Nuno Santos

  6. My English is not very good. I’m sorry for that. ble or classic … I want to protect the device with a password. Not every phone can connect.
    I don’t want to keep you busy … Is there a way to do this? An example link you can share?
    thank you…

      1. If you were, in terms of power management, would you choose a product like cc2541 for bluetooth or esp32?
        Not broadcast, but I want to use it as a recipient. It needs to work with a battery like 10.000 mAh for about 6 months.
        cc2541 seems to be better in terms of power management. Today I asked a question to their firm, I would like to know your opinion …
        “My question; Related to cc2541. A few sentences will suffice. I’m looking for a power mode. At this feature; can be connected to receive data. But a power mode with little power consumption until connected. So do not periodically sleep or wake up.
        Assumption example; when there is data reception or transmission, typically> 15mAh. But when there is no data reception or sending <1mAh but it can still be connected. So he can be seen from the phone.
        Is it possible ?"
        Thanks…

        1. Hi!
          Unfortunately I’ve never worked much in the power management area, so I’m not the best person to answer to your question. :/
          Nonetheless, maybe some of the readers might already have analyzed that in more depth than I did and can share their opinion 🙂
          Best regards,
          Nuno Santos

  7. Pingback: ESP32 Arduino Serial over Bluetooth: Client disconnection event – techtutorialsx

  8. Pingback: ESP32 Arduino Serial over Bluetooth: Client disconnection event – techtutorialsx

  9. Pingback: ESP32 Arduino Serial over Bluetooth: Get client address – techtutorialsx

  10. Pingback: ESP32 Arduino Serial over Bluetooth: Get client address – techtutorialsx

Leave a Reply to Mauro BilottiCancel reply

Discover more from techtutorialsx

Subscribe now to keep reading and get access to the full archive.

Continue reading