TinySkiff ESP32-S3 Lab · Day 28 of 30

Switch the light
from your phone

Today your words start moving hardware. You wire a single LED, upload a sketch that listens over Bluetooth for two exact commands, and switch the light from across the room — write led_on and it lights, led_off and it goes dark. Yesterday's pipe now carries orders.

About 25 minutesArduino firstMicroPython optionalSame one-LED circuit as Blink
Agent assist code TSK-DAY28-BTLED

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

Six things, most of them old friends from your first circuits. Tap Define on any part you haven't met — 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 that runs your uploaded sketch — its Bluetooth radio is built in.

Official manual image of the ESP32-S3 GPIO extension board.
Manual photo

GPIO extension board

Spreads the pins into rows you can reach and label.

Official manual photo of a red LED with its longer positive leg and shorter negative leg labelled.
Manual photo

LED

The light your phone will switch — it only works one way round.

Official manual photo of a resistor with coloured value bands.
Manual photo

220 Ω resistor

Sits in series with the LED to keep the current gentle.

Official manual image of a jumper wire.
Manual photo

2 jumper wires (M/M)

Two are enough today — the LED's feed and its return to ground.

Official manual screenshot of the Arduino IDE interface.
Manual screenshot

Arduino IDE

Uploads the sketch and opens Serial Monitor.

02 Make the physical circuit

Chart the circuit

The official Freenove diagram is your chart — schematic on top, the same circuit built on a breadboard below. Click it to enlarge. The circuit is the one-LED layout you know from Blink; the command now arrives by radio.

Official Freenove circuit — C Tutorial, Chapter 20 (Bluetooth), page 193.
LED long leg (+) GPIO 2 via 220 Ω This pin obeys the command your phone sends.
LED short leg (−) GND Completes the LED's path back to zero volts.

Mind the LED's legs. The LED only lights one way round — long leg toward GPIO 2 through the 220 Ω resistor, short leg to ground. Unplug USB before you move any wire.

03 One action at a time

Build it

This is the main path — you can finish the day without opening a single field note. Tap each step as you go to keep your place.

0 / 9 done
  1. Seat the ESP32-S3 on the GPIO extension board and keep USB unplugged while you wire.

  2. Place the LED so its long leg (+) is on the GPIO 2 side and its short leg (−) heads toward ground.

  3. Put the 220 Ω resistor in series between GPIO 2 and the LED's long leg.

  4. Compare every wire to the chart, then plug in USB.

  5. Open Sketch_20.2_BluetoothToLed.ino in Arduino IDE and upload it.

  6. Open Serial Monitor at 115200 and look for the "device started" line.

  7. On your phone, open LightBlue and connect to ESP32S3_Bluetooth, exactly as you did on Day 27.

  8. Find the write characteristic, set the format to utf-string, and write led_on — underscore, exact spelling.

  9. Watch the LED light, then write led_off to put it out.

The phone is the helm now.

A word typed in the air just moved a pin. Head to Test & debug to confirm both commands.

04 Read just enough code

Read the code

The BLE plumbing at the top of this sketch is Day 27's, line for line — same service, same name. Today's new idea lives in loop, where the board compares whatever arrived against two known commands and acts. Switch to MicroPython if you'd rather see the same idea in Python — the wiring never changes.

Sketch_20.2_BluetoothToLed.ino
#define LED 2

void setup() {
  pinMode(LED, OUTPUT);
  setupBLE("ESP32S3_Bluetooth");
  Serial.begin(115200);
  Serial.println("\nThe device started, now you can pair it with Bluetooth!");
}

void loop() {
  long now = millis();
  if (now - lastMsg > 100) {
    if (deviceConnected && strlen(rxload) > 0) {
      if (strncmp(rxload, "led_on", 6) == 0) {
        digitalWrite(LED, HIGH);
      }
      if (strncmp(rxload, "led_off", 7) == 0) {
        digitalWrite(LED, LOW);
      }
      Serial.println(rxload);
      memset(rxload,0,sizeof(rxload));
    }
    lastMsg = now;
  }
}
setupBLE("ESP32S3_Bluetooth")The same radio setup as Day 27 — the board advertises under the same name, with the same service underneath.
strncmp(rxload, "led_on", 6) == 0True when the first six characters the phone wrote spell led_on — underscore included. The buffer rxload holds whatever landed in the write characteristic.
digitalWrite(LED, HIGH)The matched command drives GPIO 2 HIGH and the LED lights; led_off drives it LOW again.
Serial.println(rxload)Echoes every received command to Serial Monitor, so you can watch the words arrive as the LED obeys.

05 Understand, don't memorise

The shape of a command

Day 27 gave you a pipe between phone and board. Day 4 gave you digitalWrite. Put them together and you have remote control — and the pattern in today's loop is the skeleton of every protocol you'll ever meet.

Send

Phone writes

LightBlue writes your text into the board's write characteristic.

Receive

Buffer fills

The sketch copies the incoming bytes into rxload.

Compare

Two known words

strncmp checks the buffer against led_on and led_off.

Act

Pin moves

digitalWrite drives GPIO 2 HIGH or LOW and the LED follows.

The model phone text → match a known command → digitalWrite

Why spelling is the whole protocol

The board compares raw characters. led_on with an underscore is a command; anything else is just text that scrolls past, and the LED holds its state.

What the radio adds

BLE only carries the bytes. The meaning — which words count as commands and what they do — lives entirely in the sketch you wrote.

06 Know it worked

Test & debug

The proof is the LED obeying your phone — Serial Monitor backs it up by echoing each command as it lands.

What you should see
LED
  • Write led_on in LightBlue (utf-string format) — the LED lights.
  • Write led_off — the LED goes dark.
  • Any other text leaves the LED exactly as it was — the sketch only acts on its two known commands.

Serial Monitor at 115200 shows "The device started, now you can pair it with Bluetooth!" on boot, then echoes every command the board receives.

If it doesn't
  • LED never reacts? Send the underscore spelling led_on exactly, in utf-string format.
  • LED wired but dead? Long leg to GPIO 2 through the 220 Ω resistor, short leg to GND.
  • Can't find the board? Repeat Day 27's LightBlue steps, and press reset before reconnecting.
  • Monitor blank? Set the baud rate to 115200.

07 Make the idea yours

Try this: grow the protocol

Same working circuit, one new power: you decide what the commands are. It fits inside today's 25 minutes.

Add led_blink

Add a third strncmp branch for led_blink that flashes the LED twice — HIGH, a short delay, LOW, and again. Upload and send your new word.

Rename the commands

Change led_on and led_off to words of your own — keep the character counts in each strncmp honest — and drive the light with your own vocabulary.

Logbook

08 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-DAY28-BTLED

How the agent should behave: guide one physical step at a time, wait for you to confirm, explain terms on request, and always check wiring, board, port, and USB before changing code.

Field note

Shortcut

Prompt copied