TinySkiff ESP32-S3 Lab · Day 27 of 30

Talk to your phone
over radio

Today the cable stops being the only path. The ESP32-S3's built-in Bluetooth Low Energy radio becomes a short-range text line — you type in Serial Monitor and the words land on your phone, then your phone answers back the same way.

About 25 minutesArduino firstMicroPython optionalBring your phone
Agent assist code TSK-DAY27-BLE

Hand this to an agent so it can pull the lesson packet and coach you step by step.

01 First, know the pieces

What you need

Just the board and its USB cable from the kit — plus your phone. Today's extra tool is a free app called LightBlue (iOS App Store or Google Play) that speaks BLE and lets you see exactly what the board broadcasts. Tap Define on anything unfamiliar — the answer opens as a field note you can read and dismiss without losing your place.

Official manual photo of the ESP32-S3 development board.
Manual photo

ESP32-S3 board

The brain — and today, the radio.

Official manual screenshot of the Arduino IDE interface.
Manual screenshot

Arduino IDE

Uploads the sketch and opens Serial Monitor.

Official manual page showing the BLE data pass-through sketch and Serial Monitor output.
Manual sketch

Official sketch

Sketch_20.1_BLE_USART.ino

02 One action at a time

Build it

Two ends today — the board end in Serial Monitor and the phone end in LightBlue. Tap each step as you go to keep your place; you can finish without opening a single field note.

0 / 10 done
  1. On your phone, install the free LightBlue app from the iOS App Store or Google Play, and turn Bluetooth on. (On Android, Serial Bluetooth Terminal also works if you already have it.)

  2. Plug the ESP32-S3 into your computer with a data-capable USB cable.

  3. Open Sketch_20.1_BLE_USART.ino in Arduino IDE — the BLE libraries ship with the ESP32 board package, so there is nothing extra to install.

  4. Press Upload, then open Serial Monitor and set the baud rate to 115200.

  5. Watch for Waiting a client connection to notify... — the board is now broadcasting its name.

  6. In LightBlue, open the Scan page, swipe down to refresh, and tap ESP32S3_Bluetooth. BLE devices are opened inside a GATT app like this — the name never shows up in your phone's Settings→Bluetooth pairing list.

  7. To hear the board, open the characteristic ending 0003, set Data Format to utf-string, and tap Subscribe.

  8. Type a line in Serial Monitor's send box and press Enter — it appears on the phone.

  9. To talk back, open the characteristic ending 0002, set Data Format to utf-string, type a message, and tap Write.

  10. Watch your message appear in Serial Monitor.

Radio contact.

Your board and your phone are trading text with no cable between them. Head to Test & debug for what each end should show.

03 Read just enough code

Read the code

The sketch is about seventy lines; the parts that matter fit here. A helper called setupBLE() builds the radio's public face — it creates the service with a write characteristic for phone→board and a notify characteristic for board→phone, then starts advertising. The BLE libraries ship with the ESP32 board package, so it compiles as-is.

Sketch_20.1_BLE_USART.ino
#include "BLEDevice.h"
#include "BLEServer.h"

#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

void setup() {
  Serial.begin(115200);
  setupBLE("ESP32S3_Bluetooth");
}

void loop() {
  long now = millis();
  if (now - lastMsg > 100) {
    if (deviceConnected&&rxload.length()>0) {
        Serial.println(rxload);
        rxload="";
    }
    if(Serial.available()>0){
        String str=Serial.readString();
        const char *newValue=str.c_str();
        pCharacteristic->setValue(newValue);
        pCharacteristic->notify();
    }
    lastMsg = now;
  }
}
setupBLE("ESP32S3_Bluetooth")The helper shown in the full sketch. It creates the service with a write characteristic for phone→board and a notify characteristic for board→phone, then starts advertising this name.
#define CHARACTERISTIC_UUID_RX …UUIDs are the fixed names each side looks up to find the right data lane — this trio is the widely adopted Nordic UART set.
Serial.println(rxload)Whatever the phone wrote arrives in rxload and prints straight to Serial Monitor.
pCharacteristic->notify()Pushes whatever you typed in Serial Monitor out over the radio to every subscribed phone.

04 Understand, don't memorise

A serial pipe over radio

BLE organises everything a device offers into services, and each service into characteristics — small named mailboxes the phone can read, write, or subscribe to. Today's service holds exactly two, one for each direction.

Advertise

The board calls out

The sketch broadcasts the name ESP32S3_Bluetooth so nearby phones can find it.

Connect

The phone answers

LightBlue opens a connection and finds the service by its UUID.

Write in

Phone → board

Text written to the characteristic ending 0002 lands in the sketch and prints to Serial Monitor.

Notify out

Board → phone

Text typed in Serial Monitor is pushed through the characteristic ending 0003 to every subscriber.

Useful model one write lane in + one notify lane out = a two-way text pipe

Why the long UUIDs

A UUID is a name long enough that nobody else's gadget will ever share it by accident. This particular trio is the Nordic UART set — a convention so common that serial-over-BLE apps recognise it on sight.

Why you must subscribe

A notify characteristic only sends to phones that asked. Subscribing is how the phone says "keep me posted" — until then, the board's messages have nowhere to go.

05 Know it worked

Test & debug

Success and recovery sit side by side, so you never have to go hunting when something looks off.

What you should see
Serial Monitor115200 baud
Waiting a client connection to notify...hello from the phone

The waiting line prints once at start-up. After you connect and write from the phone, each message appears as its own line — a stray `Test` right after connecting is just the sketch's starter value.

If it doesn't
  • ESP32S3_Bluetooth never appears in LightBlue? Power-cycle the board and swipe down to rescan — it starts advertising at boot. Look for it inside the app; BLE devices skip the phone's Settings→Bluetooth pairing list.
  • Nothing arrives on the phone? Open the characteristic ending 0003 and tap Subscribe first — notifications only flow to subscribers.
  • Garbled symbols on the phone? Set the characteristic's Data Format to utf-string.
  • Nothing lands in Serial Monitor? Confirm 115200 baud, and that you're writing to the characteristic ending 0002.
  • Can't reconnect after a disconnect? Press the board's reset button, then rescan — this sketch advertises once at boot, a known quirk.

06 Make the idea yours

Try this: name your boat, find the edge

Same working sketch, two experiments — one line of code, then a walk. It fits inside today's 25 minutes.

Fly your own name

Change setupBLE("ESP32S3_Bluetooth") to setupBLE("YourBoatName"), re-upload, and rescan in LightBlue — your board now broadcasts under its own flag.

Find the range edge

Stay subscribed on the phone and walk to the far end of your home while a helper (or a repeated send) keeps messages coming from Serial Monitor. Note where they stop arriving.

Logbook

07 Learn it with a hand on the tiller

Coach me through it

Every lesson ships with a code and a machine-readable packet, so an agent can guide you with full context.

Lesson code

TSK-DAY27-BLE

How the agent should behave: work one end at a time — board side in Serial Monitor, phone side in LightBlue — confirm the waiting line before touching the app, and treat subscribe, data format, and reset-after-disconnect as the first checks.

Field note

Shortcut

Prompt copied