ESP32 Arduino Serial over Bluetooth: Receiving data

In this tutorial we will check how to receive data on a serial connection operating over Bluetooth classic. The tests of this ESP32 tutorial were performed using a DFRobot’s ESP-WROOM-32 device integrated in a ESP32 FireBeetle board.



In this tutorial we will check how to receive data on a serial connection operating over Bluetooth classic.

This tutorial will be very simple since we are going to use the BluetoothSerial library for the Arduino core, which exposes a very high level API much similar to the regular wired serial interface.

Note that, at the time of writing, the code of the mentioned library had just been merged to the Arduino Master branch, so you may need to get the latest changes from there. You can check here how to update your Arduino core version.

The tutorial shown here was based on the Arduino core BluetoothSerial library example, which can be see seen here. It’s a really good example to get started, which I encourage you to try.

If you want to know a little bit more of the lower level Bluetooth functionalities, you can check the Related Posts section at the end of this tutorial, which includes some tutorials on how to use the IDF Bluetooth API on the Arduino core.

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

The code

We start our code by including the BluetoothSerial.h library, which makes available the Bluetooth related functionalities we will need.

#include "BluetoothSerial.h"

Next we will need an object of class BluetoothSerial. We will use this object to initialize the Bluetooth stacks (controller and host) and to established the serial communication over Bluetooth.

This object works very similarly to the Serial extern variable we use to establish a regular wired serial communication.

BluetoothSerial SerialBT;

Moving on to the Arduino setup function, we start by opening a wired serial connection, so we can print the content we receive via Bluetooth.


Next we call the begin method of the BluetoothSerial object, to initialize the Bluetooth interface. This method will handle all the lower level initialization, so we can use the Bluetooth functionality without having to worry about what happens under the hood.

As input, the begin method receives the name we want to assign to the ESP32, which will be shown to other Bluetooth enabled devices when performing a scan.

As output, the method returns a Boolean value indicating if the initialization was correctly performed. Thus, to confirm everything executed fine, we will do an error check wrapping the begin method call.

Note that we are not going to take in consideration the result of this call in the main loop function, which will assume that everything went fine. Nonetheless, for a final robust code, you should handle error situations and act accordingly.

    Serial.println("An error occurred initializing Bluetooth");

Now, on the Arduino main loop, we will handle the received data. Our flow will be very simple and will consist on reading available bytes one by one from the Bluetooth connection and printing them to the wired serial connection.

To check if there are bytes available, we can use the available function of the BluetoothSerial object. This function behaves like the Arduino serial available function, which returns the number of bytes available for reading.

For curiosity, the current implementation of the BluetoothSerial.h uses a FreeRTOS queue under the hood to store the received bytes, which can be seen by analyzing the source code.

Thus, the available method calls the uxQueueMessagesWaiting function, which returns the number of messages available on the queue, which correspond to the number of bytes. If you want to learn more about this FreeRTOS function and how to use it, please check here.

Also, take in consideration that the size of FreeRTOS queues is specified at their creation and in the case of this library it is initialized with 256.

So, in order to get the bytes available, we will start by polling the BluetoothSerial object with the mentioned available method. Since we are going to read the bytes one by one and the ESP32 may have received more, we will poll it in a while loop.

// Handling code here

In order to get a byte, if it is available, we simply need to call the read method of the BluetoothSerial object. This will return the value of the byte as an integer.

Note: At the time of writing and by analyzing the source code, this method call is returning 0 when no data is available. Nonetheless, for the wired serial connection implementation, this function returns -1. I’ve opened this GitHub issue to track the correction.

In its implementation, the read method calls the FreeRTOS xQueueReceive function You can also check a tutorial for this functionality here.

In order to write a byte to the wired serial connection, we simply need to call the write method, passing as input the byte to write. To avoid having to declare an intermediate variable, we can directly pass to the write method the return of the BluetoothSerial read method.


To finalize, we make a small delay between each iteration of the Arduino loop, so we are not constantly polling for incoming bytes. You can check the full source code below.

#include "BluetoothSerial.h"

BluetoothSerial SerialBT;

void setup() {

    Serial.println("An error occurred initializing Bluetooth");

void loop() {




Testing the code

To test the code, simply compile it and upload it to your ESP32 using the Arduino IDE. Then, when the procedure finishes, open the serial monitor using the COM port for the wired connection.

If you see no error message, then the Bluetooth was correctly initialized. If you start a Bluetooth scan with your computer, you should see the ESP32. Pair with it if you haven’t already done so.

Once the pairing finishes, you should have a new COM port available. On Windows 8, it is possible to check it on the Device Manager. If you need more help with the pairing procedure, please check this previous post.

Now, in order to establish the serial communication with the ESP32 over Bluetooth, we will need an additional serial monitor, so we can send the data to the device.

Although we can open a new instance of the Arduino IDE and open a new terminal for the Bluetooth emulated COM port, I’ve been experiencing some crashes with it, so I will be using Putty. Amongst many other features, Putty allows to establish serial connections.

You can give it a try with using two instances of the Arduino IDE since it may be related to my local environment, but if you run into crashes my recommendation is to change to Putty to send the data.

After downloading and opening putty, configure it like is shown in figure 1, on the left. As can be seen, we need to select “Serial” in the connection type radio. After that, put the COM port detected by your computer for the Serial over Bluetooth and select a speed of 115200. Note that other speeds will also work.

ESP32 Arduino Bluetooth Serial PuTTY.png

Figure 1 – Connection using Putty and the Arduino IDE serial monitor.

By default, Putty will not echo the characters inserted in the serial interface and will send them as soon as they are clicked. If you want a behavior more similar to the Arduino IDE where we can type some characters and only send them after clicking enter, then use the configurations of figure 2, before establishing the connection.

As shown, you need to go to the Terminal tab and select “Force On” in both “Local echo” and “Local line editing” options.

Putty activate serial terminal echo.png

Figure 2 – Changing Putty serial configurations to echo inputted chars and wait for enter to send them.

After that you can start sending data to the Bluetooth serial connection, which should be printed in the wired serial connection, as shown in figure 3.

ESP32 Arduino Bluetooth Serial receiving data

Figure 3 – Echoing the Serial over Bluetooth received data.


Related posts



12 Replies to “ESP32 Arduino Serial over Bluetooth: Receiving data”

  1. Thank you for your tutorials. I’ve been working on integrating a bluetooth serial port profile on a project and this has been a great help.
    I have a quick question about this: does the BluetoothSerial library handle SDP advertising? And if not, is it possible to use btstack alongside this library to do so? (Or to do it some other way)

    Although I can get this example to work fine, I have a desktop application where I want to be able to scan for available services, but it’s not able to list services offered by the ESP32 (while it does see other devices’ services just fine).

    I am a beginner in all things bluetooth and it is possible that my issue is due to the desktop-side libraries used (Qt and its bluetooth backend on Linux, which I believe is BlueZ), but it seems more likely to me that I am missing something about SDP on the ESP32 side.

    Thanks for any advice you may have!

    Liked by 1 person

    1. Hi! Thank you very much for the feedback 🙂

      I’m not sure if the library is handling the advertisement, I haven’t yet checked it from any client discovering services.

      Nonetheless, from the architecture document below, it seems that currently some profiles are already using the SDP functionalities, but there is no API for us to use:

      Unfortunately, they don’t specifically mention SPP (Serial Port Profile, the one used by the BluetoothSerial library) as using it.

      Nonetheless, in IDF, there seems to be an API in the GAP profile to get the remote services of a device (didn’t tested it yet tough):

      So hopefully, it is a matter of time until there are APIs for us to advertise services.

      I’m not aware on how to make BTStack working on the ESP32, on the Arduino core. But even if it possible, my guess is that it both Bluedroid (the stack used in IDF and consequently on the Arduino core) wouldn’t be able to cohexist, but it is just a guess.

      Nonetheless, one thing you can do is asking around the ESP32 arduino core GitHub if someone has successfully been able to work with BTstack on the Arduino core.

      You can do a quick test with another desktop library to make sure the problem is on the ESP32. In this tutorial, on the Python section, you can check a very simple code using the PyBluez library:

      Hope this helps getting you on the right track 🙂 If you discover something more, please share with us, I’m also interested in SDP working on the Arduino core.

      Best regards,
      Nuno Santos


      1. Thank you so much for your detailed reply!
        I suppose I will be patient, and hope that an API for advertisement is added to IDF. From there it seems like it would be easy to add it to the Arduino library.

        For now I can at least detect the ESP’s address and connect to it (knowing the port to connect to), so I have at least a working demo to work on while I wait for the API to be expanded 🙂

        Liked by 1 person

        1. You’re welcome 🙂 Yes after things land in IDF, they usually quickly get to the Arduino core.

          I will also be checking IDF and try to do some tutorials as soon as they launch the new APIs for advertisement.

          Best regards,
          Nuno Santos


  2. Hello, Thank you for this techtutorialsx
    But I can not pair. Windows 10 needs a pin code, on the serial : I have
    [0;31mE (59526) BT: btm_sec_conn_req
    [0;31mE (59684) BT: btm_sec_connected
    ASSERT_WARN(1 9), in lc_task.c at line 5054

    And when I try the code #1442, I have
    [0;31mE (99708) BT: SDP – Rcvd L2CAP disc cfm, unknown CID: 0x40
    [0;31mE (103696) BT: bta_gattc_mark_bg_conn unable to find the bg connection mask for: 00:00:3a:69:af:e2[0m
    (update already done in ..Arduino\hardware\espressif\esp32\tools)
    Can you help me?

    Liked by 1 person

    1. Hi! You’re welcome 🙂

      Unfortunately I cannot be of much assistance since I never experienced that issue and I don’t have any windows 10 machine to test.

      At the time I wrote these tutorials, I didn’t find any way to set a pair pin o the ESP32, neither on the Arduino core or IDF.

      My suggestion is that you post your issue on the Arduino core GitHub page, since most likely someone else already tested it on Windows 10 and may have a solution.

      I hope that the support for setting a pairing pin arrives quickly since it is a very useful feature.

      Hope this helps getting you in the right track.

      Best regards,
      Nuno Santos


    1. Hi!

      I’m not sure, unfortunately never tried to do it.

      I think the HC.06 works as slave in the communication and it is not possible to change it. So, in theory, if you can make the ESP32 operate as master, you may be able to connect both of them.

      Nonetheless, I’ve never explored these roles on the ESP32 and if we can configure them.

      My suggestion is to ask around the ESP32 Arduino core git hub page, so someone there may already been able to do it.

      Let us know if you find any solution, it would be very interesting 🙂

      Best regards,
      Nuno Santos


  3. I do not know where to find BluetoothSerial.h for installation into Arduino IDE and use with ESP 32 ???
    Github shows the BluetoothSerial.h but no download etc… no ccp-file…
    Where do I get it ?

    Liked by 1 person

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s