Arduino library 路 Communication

ESP32 BluetoothSerial: a wireless serial port to a phone

BluetoothSerial makes the classic ESP32 look like an HC-05: a Bluetooth Classic serial port (the SPP profile) that an Android terminal app or a PC can pair with. In code it is a Stream, so SerialBT.print(), SerialBT.available() and SerialBT.read() work exactly like Serial鈥檚, and the classic bridge sketch copies bytes both ways between the two.

Built in on Mokxi: #include <BluetoothSerial.h> and it builds, with nothing to install. Free, and no account needed.

What BluetoothSerial (ESP32 core) does

It only exists on the original ESP32 chip. The ESP32-S3, C3 and C6 have Bluetooth Low Energy only, so on those boards the header refuses to build and you need the BLE library instead. iPhones do not offer SPP to apps either, which is why iOS projects use BLE even on a classic ESP32.

Pairing defaults to "just works". To require a code, call disableSSP() and setPin() before begin() for a legacy PIN, or enableSSP() with a confirm callback for the six-digit numeric comparison. register_callback() reports connects, disconnects and incoming data as SPP events.

Library Manager nameBluetoothSerial (ESP32 core)
AuthorEspressif
Include#include <BluetoothSerial.h>
BoardsESP32 DevKit, ESP32-DevKitC V4, LOLIN32 Lite, Wemos D1 R32, Cheap Yellow Display, TTGO T-Display
In the simulatorSimulated: it runs against the part the way it does on the bench.

Install it

It builds on ESP32 DevKit, ESP32-DevKitC V4, LOLIN32 Lite, Wemos D1 R32, Cheap Yellow Display, TTGO T-Display.

In Mokxi it is built in: #include <BluetoothSerial.h> and the sketch compiles, with no download, no zip and no Library Manager.

On a real board it comes with the board package (Espressif), so the Arduino IDE has it as soon as the board is installed: there is nothing to add from the Library Manager.

ESP32 DevKit 路 ESP32-DevKitC V4 路 LOLIN32 Lite 路 Wemos D1 R32 路 Cheap Yellow Display 路 TTGO T-Display

The calls you will use

In the order a sketch meets them.

BluetoothSerial SerialBT

The Bluetooth serial port object, declared once at the top of the sketch.

SerialBT.begin("ESP32test")

Starts Bluetooth and makes the board discoverable under that name. Returns false if the stack could not start.

SerialBT.available()

How many bytes the phone has sent that are waiting to be read.

if (SerialBT.available()) {
  char c = SerialBT.read();
  if (c == '1') digitalWrite(LED_PIN, HIGH);
  if (c == '0') digitalWrite(LED_PIN, LOW);
}

SerialBT.println("Temperature: 21.5")

Sends text to the connected device, like Serial.println(). Nothing is sent while no device is connected.

SerialBT.hasClient()

True while a device is connected, for showing the link state or skipping sends.

SerialBT.setPin("1234")

Sets a legacy PIN. Call SerialBT.disableSSP() and then setPin() before begin(), or the phone pairs without asking for it.

SerialBT.register_callback(callback)

Registers a function for SPP events: ESP_SPP_SRV_OPEN_EVT when a device connects, ESP_SPP_CLOSE_EVT when it leaves, ESP_SPP_DATA_IND_EVT when data arrives.

SerialBT.enableSSP()

Turns on secure simple pairing with numeric comparison; pair it with onConfirmRequest() and confirmReply() to accept the code.

Example: ESP32 Bluetooth serial lamp

On the ESP32 DevKit V1. It runs in the browser exactly as printed.

sketch.ino 路 ESP32 DevKit V1
// Bluetooth lamp: the ESP32's own Bluetooth serial port switches an LED.
//
// Simulated Bluetooth: a phone in Mokxi, not a real radio. Press Run, open
// the Bluetooth tab, pair with ESP32-Lamp and connect, then send on, off or
// status. The same sketch runs unchanged on a real ESP32 with the "Serial
// Bluetooth Terminal" app on a phone.

#include "BluetoothSerial.h"

BluetoothSerial SerialBT;
const int kLed = 4; // an LED and a resistor to ground

void onBluetooth(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
{
    if (event == ESP_SPP_SRV_OPEN_EVT) {
        Serial.println("A phone connected.");
        SerialBT.println("Hello from ESP32-Lamp. Send on, off or status.");
    } else if (event == ESP_SPP_CLOSE_EVT) {
        Serial.println("The phone disconnected.");
    }
}

void setup()
{
    Serial.begin(115200);
    pinMode(kLed, OUTPUT);
    pinMode(LED_BUILTIN, OUTPUT);
    SerialBT.register_callback(onBluetooth);
    SerialBT.begin("ESP32-Lamp");
    Serial.println("ESP32-Lamp is ready: pair with it from the Bluetooth tab.");
}

void loop()
{
    // The blue LED on the board shows whether a phone is connected.
    digitalWrite(LED_BUILTIN, SerialBT.hasClient() ? HIGH : LOW);

    if (SerialBT.available()) {
        String line = SerialBT.readStringUntil('\n');
        line.trim();
        line.toLowerCase();
        Serial.print("Phone sent: ");
        Serial.println(line);
        if (line == "on") {
            digitalWrite(kLed, HIGH);
            SerialBT.println("The lamp is on.");
        } else if (line == "off") {
            digitalWrite(kLed, LOW);
            SerialBT.println("The lamp is off.");
        } else if (line == "status") {
            SerialBT.println(digitalRead(kLed) ? "The lamp is on." : "The lamp is off.");
        } else if (line.length() > 0) {
            SerialBT.println("Send on, off or status.");
        }
    }
    delay(20);
}

Open it in the editor, wired and ready to run 路 ESP32 Bluetooth serial lamp: the project page

Common errors and how to fix them

Serial Bluetooth not available or not enabled. It is only available for the ESP32 chip.

The board is an ESP32-S3, C3 or C6, which have no Bluetooth Classic. Use a classic ESP32 DevKit for BluetoothSerial, or rewrite the sketch with the BLE library, which those chips do support.

The iPhone cannot see the board

iOS does not let apps use the Bluetooth serial profile, so a classic ESP32 running BluetoothSerial never appears there. Use an Android phone or a PC, or switch the project to BLE for iPhone users.

Sketch too big after adding BluetoothSerial

Bluetooth Classic plus WiFi can overflow the default app partition. Choose a larger partition scheme such as Huge APP in the board settings, or drop the library you are not using.

Try BluetoothSerial (ESP32 core) without installing anything

Open the example, change the sketch, and keep your version in a free account.