ESP32 Bluetooth: Using the BTstack library

The objective of this ESP32 tutorial is to explain how to get started with the Bluetooth functionalities that are supported by the ESP32 hardware. The Bluetooth tests of this tutorial were performed using a DFRobot’s ESP-WROOM-32 module, integrated in a ESP32 FireBeetle board.


The objective of this ESP32 tutorial is to explain how to get started with the Bluetooth functionalities that are supported by the ESP32 hardware.

We are going to use the BlueKitchen’s BTstack library, which can be obtained from GitHub here. You can also read more about this library on its website. BTstack supports both Bluetooth Classic and Bluetooth Low Energy, making it a versatile choice to use.

This library has ports for many platforms, as can be seen here. Fortunately, the ESP32 is one of the supported microcontrollers. You can check at the GitHub page the setup guide for the ESP32, although we are also going to cover it on this tutorial.

We will be using the ESP32 IDF in order to use the BTstack library. If you don’t have IDF configured, please follow Espressif’s guide here. Setting up IDF is relatively straightforward since the guide is very comprehensive and most of the tools are already compiled for us. Nonetheless, using it is not so easy as the Arduino core.

Note that the BTstack exposes a very low level API. Although it gives us much more control over the functionalities, it is also more complex to use and it needs some knowledge about the Bluetooth stack. So, we are going to start with a very simple example that will start the Bluetooth on our ESP32 and make it discoverable for other Bluetooth devices.

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

Setting up the BTStack

As said in the introductory section, using the BTstack library requires a previous installation of the ESP32 IDF tool. If you have followed Espressif’s guide, then you should have installed msys32 somewhere on your computer.

In my case, I have my IDF folder under C:/msys32/home/myUser/esp/esp-idf. So, what we need to do next is getting the BTstack library from GitHub. You can either clone it using Git or manually download it from the GitHub page.

Note the download button in figure 1, which allows to get a copy of the libraries. In my case, I’ve manually downloaded it.

Download BTStack

Figure 1 – Downloading BTstack library from GitHub.

Then you need to save it on your msys32 working environment. In my case, I have it on the same folder of the IDF project, in C:/msys32/home/myUser/esp/.

Once you have it on your working folder, open the msys32 terminal and navigate to the BTstack project folder. Then, still using the command line, navigate to the /port/esp32 folder. You can use the cd (change directory) command to navigate on the folders of the project.

In that directory, you need to run the following command for the project example folders to be created [1]:


On that same directory, you should now have a lot folders with different examples from BTstack. In order to create our new program easily, we are going to copy one of these example folders and use most of the configurations already defined. So, make a copy the spp_counter folder in the same directory and rename it hello_world.

Then, enter on the new hello_world folder and after that on the main folder. There, you should have a file called spp_counter.c. Rename it to hello_world.c.

Finally, you can open the file and clear its contents, since we are going to write the code on the next section.

The code

On the top of our file, we will need to have the include for the btstack.h file, which contain some configurations and initialization. We will not change that file for this simple tutorial.

#include "btstack.h"

Now we are going to move on to the main function, which is called btstack_main. There we will put our Bluetooth code. In this simple tutorial, it will mainly consist on some initialization.

int btstack_main(int argc, const char * argv[]){
// ...

Next, we need to call the l2cap_init function, which makes the setup of L2CAP and registers it with the HCI layer [2].

On the Bluetooth stack, L2CAP (Logical Link Control and Adaptation Protocol) provides connection oriented and connectionless data services to the protocols built on upper layers [3]. One of the responsibilities of this layer is to provide multiplexing between the higher layer protocols, enabling multiple applications to utilize the same lower layer links [3].

The mentioned HCI (Host Controller Interface) layer provides a uniform interface for accessing the Bluetooth hardware capabilities [4].


Next we need to call the sdp_init function, which sets up SDP (Service Discovery Protocol). This layer allows advertising services and discovering services provided by other Bluetooth devices.


In the next steps,  we will configure some settings of GAP (Generic Access Profile). GAP is a profile from the Bluetooth stack that defines how devices find each other and how they establish a connection [5].

Keeping this in mind, we will first make the device discoverable by calling the gap_discoverable_control function, passing as input the value 1. This way, we will be able to discover the ESP32 from other Bluetooth devices.


We will also set the name of the device, by calling the gap_set_local_name function and passing as input the name that we want to set. We will call it “Hello world”. Note that this needs to be defined before the Bluetooth stack starts [2].

gap_set_local_name("Hello world");

Finally, we call the hci_power_control function to turn on the the power of the hardware Bluetooth controller. It receives as input a variable of HCI_POWER_MODE enum. In this case, since we want to turn it on, we should pass HCI_POWER_ON.

The final code is shown bellow.

#include "btstack.h"

int btstack_main(int argc, const char * argv[]){


    gap_set_local_name("Hello world");


    return 0;

Testing the code

First of all, we need to set the correct configurations to upload the code for our FireBeetle ESP32 board. To access the configurations menu, go the the msys32 command line and on the hello_world directory hit the following command:

 make menuconfig 

Note that this is a IDF specific command and not a BTstack particularity. A menu like the one shown in figure 2 should pop.

ESP32 IDF MenuConfig

Figure 2 – ESP32 IDF menu config.

Navigate to serial flasher config entry and hit enter. There you should put the board’s specific configurations needed to upload the program. For the FireBeetle board / ESP-WROOM-32 module, you should put the ones shown in figure 3.

ESP32 FireBeetle IDF Flash configurations

Figure 3 – ESP32 FireBeetle board flash configurations.

Note that on the default serial port entry you should put you device’s serial port, which may differ from mine. If you are coming from a Arduino background, then using the Arduino IDE to find the port of your device is a simple way to do it.

Note that you can also find at the Arduino IDE the flashing configurations for your board if it is already supported in the Arduino environment. It can be found under the tools menu. You can also find a lot of board’s configurations here.

After configuring, go to the save button and hit enter to save the content and then go to exit. Back on the msys32 command line, with your board connected to the PC, hit the following command do compile and flash the code:

 make flash 

The code should now start to compile. Note that the first time it compiles it may take  a while. After being compiled, the flashing to the ESP32 should start automatically. After the procedure is finished, it should end up like shown in figure 4.

ESP32 btstack flashing with IDF

Figure 4 – Upload of the code finished.

To make sure the code is executing, you can send the following command on the terminal to open a serial monitor tool.

 make monitor 

Other alternative is using the Arduino IDE serial monitor. In my case I was having some problems with the msys32 monitor, so I used the Arduino IDE to confirm that the board was indeed running the Bluetooth program. A message like the one shown in figure 5 should be printed on the console.

BTstack Arduino IDE output

Figure 5 – Output of the BTstack hello world program on Arduino IDE.

Note that you may need to reset the board with the onboard reset button or unplug and replug the power because after uploading a program the board sometimes stays in download mode.

It’s important to take in consideration that the output we see on the command line printed to the serial port was not defined in our code. It is defined on a file on hello_world/components/btstack/main.c. You can confirm in that file that there are indeed the prints defined, in the app_main function.

Finally, you can try to find the ESP32 from some Bluetooth device. In my case, I’m finding it from my computer, as shown in figure 6. Note that I’m on a laptop with Bluetooth classic, so we don’t need a BLE device to find the ESP32.

ESP32 BT Classic device finding it

Figure 6 – Finding the ESP32 as a Bluetooth device.

Related content








40 Replies to “ESP32 Bluetooth: Using the BTstack library”

  1. Pingback: techtutorialsx
  2. Great! Would you help me to clear some confusion:

    So this BTstack library is different from the BT library in esp-idf, right? because I have seen that the BTlib in esp-idf is pretty limited that no classic BT and it cannot connect to more than one BLE peripheral. and they keep saying that they will improve it. So now I am confused if BTstack is much mature library why don’t they use it? and make it included within esp-idf?

    Does BTstack library support connecting to more than 1 BLE peripheral?

    Thanks a lot even if you could not help me understanding this BT mess

    1. Hi! Yes this library is from BlueKitchen and not from Espressif (the makers of the ESP32):

      I decided to start exploring this one precisely due to the limitation on the Bluetooth features on IDF.

      Well I think it may be related to licensing. As can be seen in the GitHub page of BTstack, the library is free for no commercial use:

      But it’s just a guess.

      I haven’t yet played with BLE and I’m still in the early stages of exploring the library. I will share more information if I found out. But one place where you can also look for information is in the library google groups discussion:!forum/btstack-dev

      Hope to share more content on BTStack soon!

      Best regards,
      Nuno Santos

  3. Hi, Nuno from Lisboa
    many thanks for your clear advisory on using bt stack on esp32.
    I tried it … and it runs. I’m using a Wemos LoLin32.
    Ok, then let’s go on to the next bt advisory on esp32 8-))
    Greetings from Fulda, Germany from Peter

    1. Hi Peter! Thank you very much for the feedback 🙂 I’m planning on writing some more tutorials as soon as I have some time.

      Best regards,
      Nuno Santos

  4. Reblogged this on Intelligent Toasters and commented:
    Mad props to antepher and his awesome techtutorialsx blog. Just when I’d given up hope that the ESP32 would resolve my Bluetooth woes, he points out that BTStack is a pretty capable stack for embedded and has a port for the ESP32 already! I’m eternally grateful…thank you!

    1. Thank you very much for sharing and for the feedback 🙂 This is indeed a very good library. Although it is very low level, it offers a wide range of functionalities and great flexibility.
      But all the credits should go to the BlueKitchen team for bringing this to us, I’m just the guy who makes some tutorials 🙂

      Best regards,
      Nuno Santos

  5. I’ll double the thanks of the previous post. I had given up trying to figure out how to make ESP32 work for me given the lack of clarity about BT. I had not yet found a way to get RFCOMM to work on ESP32, and now, not only can I get that to work, but all of my code is much more straightforward. Great library and great tutorials.

    1. Hi! Thanks for the feedback, I’m glad it is working for you 🙂

      It is indeed a great library from the BlueKitchen team, I’m planning to do some more posts about it in the future.

      Hopefully we will start see more content about BT for the ESP32 around the web soon.

  6. Great tutorials ! With this sample I am able to find it on my macbook pro (and pair with it), but unable to find it on my iPhone 6 and iPhone 6S for some reason.

    Looking for some pointers on exposing the ESP32 as an iBeacon. You wouldn’t happen to have a tutorial on that ? Tried the ble_adv sample in esp32-IDF but doesn’t show up in my Nordic nrfConnect app as a beacon.

    1. Hi! Thank you very much 🙂

      Does the iPhone support all the profiles of Bluetooth Classic? I’ve been able to find and pair the ESP with my Huawei Ascend P6, so I don’t have any other clue of what may be happening.

      Nonetheless, most likely there have already been people experimenting with those versions, so a good place to ask is at the btstack git page:

      Please let us know if you find an answer, so it may help others with the same problem.

      Unfortunately I haven’t yet played with iBeacon functionalities. I’m planning on doing more tutorials on the btstack library, but meanwhile I’ve been investigating some other stuff.

      If I test something related, I will share here in the blog.

      Best regards,
      Nuno Santos

  7. Great tutorial!
    But I have one (probably very simple) problem – during compile I got an error: “btstack.h: No such file or directory”. How to fix this?

    1. I’ve solved that already. In this tutorial, instead of “./” there should be “./” – this integrates the stack with IDF and automatically creates examples.

      1. Hi! I’m glad you have solved the problem 🙂 I think at the time of writing the script was called “”, there was most likely a change in the name.

        Thanks for the warning!

        Best regards,
        Nuno Santos

        1. I do agree, the script to run is now named “”. will only copy the example in the current folder without placing the source code into the esp32 folder.
          Thank you very munch for the tutorial, Loïc

          1. Hi! Thanks for the warning 🙂 I really need to go back to using the library, there’s plenty of stuff that I wanted to test, but time is so short 🙂

            Best regards,
            Nuno Santos

  8. This was GREAT! I too was able to pair to the ‘Hello World’ device with my Moto after following your steps.Implemented on the Wemos Lolin32 with integrated OLED. Thank You Very Much!

  9. heyyaa… my name is ankit..
    i have done many example on this..
    but i want to use my esp32 as beacon scanner..
    can u help me with this,..
    using esp-idf how can i scan other beacons

  10. Great job! Now let me ask you something. I’ve tried to put my own tasks running in the spp_streamer sample as if the btstack_main was the “app_main” from ESP-IDF normal entry point but it crashed. BTstack owns the control of tasks so I couldn’t do that. How to use the BT SPP functionalities as just one more task of your system, integrated in it? Thanks!

    1. Hi!

      Thank you very much for the feedback 🙂

      Unfortunately at the time I did not explore much how to integrate BTstack in the “regular” IDF flow so I’m not sure what is the best way to do it.

      BTstack is very powerful but is actually quite complex. At the time I’ve spent a good amount of time just figuring out the basics and then I ended up getting caught in other areas.

      Nonetheless, since that time, IDF has released support for Bluetooth Classic on their own Bluedroid stack.

      Although some basic features are still missing (for example, pairing pins), it is already possible to do a lot of stuff, such as exchanging data with the SPP profile.

      Not sure if you are an Arduino core user, but the support has also already reached it.

      Nonetheless, it is much more easy to integrate and there are plenty of examples, so most likely it will be easier for you to use the BT functionalities as a regular task.

      I have already a couple of tutorials on using the IDF APIs on the Arduino core, but it should be pretty straightforward to use them on IDF. Let me know if you need the links.

      Hope this helps 🙂

      Best regards,
      Nuno Santos

  11. Great job, I got to know about BTstack from your posts. Let me ask you something. Do you know how to integrate the btstack functionalities into a regular program without being hooked by btstack_main, I mean, using your own app_main? I’ve tried to put tasks to run in the spp_stream sample but it crashed because btstack owns the main thread and controls tasks. Thanks!

    1. Hi! Thank you very much 🙂

      Unfortunately I just investigated the basics of BTstack and then got caught on other ESP32 functionalities, so I did not explore how to integrate it in the regular IDF flow.

      Nonetheless, from that time, support to Bluetooth classic has arrived to the “official” IDF bluetooth stack, which I found much simpler to use.

      I’ve a couple of posts about it on the Arduino core using the lower level IDF API, it should be easy to adapt to use on IDF.

      Let me know if you need the links for those posts 🙂

      Best regards,
      Nuno Santos

  12. Hi Nuno,

    all your tutorials are really good.
    Do you know is it possible to do an inquiry / search for other devices from ESP32 BT classic? I want to use it as a master and handle a connection to a specific device.

    Thanks in advance

    1. Hi Mauricio,

      Thank you very much for the feedback, I’m glad you are finding the tutorials useful 🙂

      Unfortunately I never had the chance to explore BTstack much further and since Espressif released the new version of IDF with Bluetooth Classic support, I’ve been focusing more on the Bluedroid stack, since it is officially supported by them.

      Nonetheless, I recall seeing some examples in BTStack that might be what you are looking for. More precisely, there was a sdp_general_query example that I think allowed to query the services available on other devices.

      This was one of the examples that were created on the examples folder when setting up btstack on IDF.

      Hope this can help you get in the right track 🙂

      Best regards,
      Nuno Santos

  13. Hello,
    you’re tutorial is really good.
    i’m not an expert in esp32 and i’m french so my english is not …..

    actually i programme my esp32 with the arduino IDE
    i think that you don’t use this methode.

    Is it possible to use BTStack with the arduino IDE
    did you have link, tuto for this

    thanks a lot for you’re website, he is really usefull

      1. Hi!

        Thank you very much for sharing!

        Let us know if you succeeded and were able to make it work, since it would certainly be very useful to many people who are looking to use btstack on the Arduino core 🙂

        Best regards,
        Nuno Santos

    1. Hi!

      Thank you very much for the feedback 🙂

      Unfortunately I’m not aware how to make BTStack work in the Arduino core, although I’ve seen a couple of people claiming it is possible in some forums.

      My recommendation if to ask around on the GitHub page of the Arduino core, since it is the best place to find someone who already did it.

      Note however that currently the Arduino core already supports some functionalities of Bluetooth classic, such as emulating serial communication over Bluetooth.

      Not sure if this is what you are looking for, but it may be worth taking a look at what is already available on the Arduino core, since it has a much higher level and simpler to use API.

      Best regards,
      Nuno Santos

Leave a Reply