Learning Goals 5 min
Cluster D taught you protocols on a wire. Cluster E takes the wire away. The HC-05 is the classroom Bluetooth module — a small blue PCB that, once paired with your phone, behaves exactly like a UART link over the air. Your sketch sees characters via Serial; your phone sees characters in a terminal app. By the end of this lesson you will:
- Wire an HC-05 to a UNO using SoftwareSerial (so the hardware UART stays free for upload) plus power and a 5 V → 3.3 V level shifter for the module's RX pin.
- Pair your phone to the HC-05 (default PIN 1234) and use a Bluetooth-serial app to send characters that your sketch reads — same code patterns as L01-26.
- Build a Bluetooth-controlled LED:
1from the phone turns it on,0turns it off.
Warm-Up 10 min
Pull out the HC-05. Identify the pins (usually 6, sometimes 4):
| HC-05 pin | What it does |
|---|---|
| EN (or KEY) | Enable/AT mode toggle. Leave floating for normal use; tie HIGH at boot for AT mode (L03-24). |
| VCC | 3.6–6 V power. 5 V from the UNO works fine. |
| GND | Ground. |
| TXD | Module's TX → goes to UNO's SoftwareSerial RX (no level shifter needed; module sends 3.3 V, UNO reads it as HIGH fine). |
| RXD | Module's RX → comes from UNO's SoftwareSerial TX. 5 V is too high for HC-05's 3.3 V input — use a divider or shifter. |
| STATE (optional) | HIGH when paired, LOW when not. Useful for "connection" LEDs. |
Pre-class question
Why does the HC-05's TX → Arduino RX direction not need a level shifter, but the Arduino TX → HC-05 RX direction does?
Reveal
The HC-05 outputs 3.3 V for "HIGH". The UNO's digital pins recognise anything > ~3 V as HIGH, so 3.3 V is detected correctly. No shifter needed.
The UNO outputs 5 V for "HIGH". The HC-05's RX pin is rated for max 3.6 V — feeding 5 V into it can damage the chip. So you need to drop the 5 V signal to ~3.3 V before it hits the HC-05. The cheap fix: a resistor divider (1 kΩ + 2 kΩ). The proper fix: a logic-level shifter breakout.
New Concept · Bluetooth Classic as a wireless UART 25 min
What an HC-05 actually is
Internally: a Bluetooth Classic SoC running Bluetooth's Serial Port Profile (SPP). To your sketch it presents a UART; to your phone it presents a Bluetooth serial endpoint. The radio negotiates the pairing and the encryption; the data layer is plain bytes-in, bytes-out, both directions.
Latency: ~10 ms per byte once paired. Throughput: up to ~10 KB/s with good RSSI. Range: ~10 m indoors. Power: ~30 mA when paired, ~5 mA idle. Plenty for remote-control toys, dashboards, sensor uploads.
HC-05 vs HC-06 vs BLE — quick decoder
| Module | Mode | iOS support? | Use for |
|---|---|---|---|
| HC-05 | Bluetooth Classic (SPP), can be master or peripheral | Limited (iOS Classic apps blocked) | Phone↔Arduino (Android); Arduino↔Arduino |
| HC-06 | Bluetooth Classic (SPP), peripheral only | Limited | Cheap and simple, but can't connect outward |
| HM-10 / BLE | Bluetooth Low Energy (GATT) | Yes | Modern phones, including iOS. Lower throughput. |
| Nano 33 BLE / nRF52 | BLE (Arduino-native) | Yes | Custom BLE characteristics, the "modern" route |
The HC-05 is the cheapest and easiest for Android-based projects. For iOS, jump to L03-26 (ArduinoBLE).
Pairing flow
- Power up the HC-05 (5 V to VCC, GND to GND). The on-board red LED blinks rapidly (~5 Hz) = "not paired, advertising".
- On your Android phone: Settings → Bluetooth → Scan → see "HC-05" in the list → tap → enter PIN
1234(default) or0000(some clones). - Pairing complete. The LED's blink slows to ~once every 2 seconds = "paired".
- Open a Bluetooth-serial app (e.g. "Serial Bluetooth Terminal" for Android). Connect to HC-05. The LED stays solid = "connected".
- Type characters in the app → they appear on the HC-05's TX pin → on the Arduino's SoftwareSerial RX → in
mySerial.read().
Wiring with a resistor divider for RX protection
| HC-05 | UNO / breadboard |
|---|---|
| VCC | 5V |
| GND | GND |
| TXD | UNO D2 (SoftwareSerial RX) directly |
| RXD | UNO D3 → 1 kΩ → HC-05 RXD; HC-05 RXD → 2 kΩ → GND |
The 1 kΩ / 2 kΩ divider takes 5 V from the UNO down to 5 V × (2 / (1+2)) ≈ 3.3 V at the HC-05's RXD. Safe.
Worked Example · Bluetooth-controlled LED 25 min
Step 1 — wire it (with the resistor divider)
HC-05 VCC/GND to UNO 5V/GND. HC-05 TXD → UNO D2 (direct). UNO D3 → 1 kΩ → HC-05 RXD → 2 kΩ → GND. LED + 220 Ω resistor between UNO D6 and GND.
Step 2 — pair your phone
Power the UNO. The HC-05's red LED blinks rapidly. On your phone: Settings → Bluetooth → pair with HC-05 (PIN 1234 or 0000). Open "Serial Bluetooth Terminal" (or equivalent). Tap menu → Devices → tap HC-05. The terminal should connect and the HC-05's LED should slow / go solid.
Step 3 — the sketch
// L03-23 · Bluetooth-controlled LED via HC-05 + SoftwareSerial
#include <SoftwareSerial.h>
const int BT_RX = 2; // UNO RX <- HC-05 TXD
const int BT_TX = 3; // UNO TX -> HC-05 RXD (through 1k/2k divider)
const int LED = 6;
SoftwareSerial bt(BT_RX, BT_TX); // RX, TX
void setup() {
Serial.begin(9600);
bt.begin(9600); // HC-05 default baud
pinMode(LED, OUTPUT);
Serial.println("# Bluetooth LED ready. From phone: '1' = on, '0' = off");
}
void loop() {
if (bt.available()) {
char c = bt.read();
switch (c) {
case '1':
digitalWrite(LED, HIGH);
bt.println("LED ON");
Serial.println("# LED ON");
break;
case '0':
digitalWrite(LED, LOW);
bt.println("LED OFF");
Serial.println("# LED OFF");
break;
default:
bt.print("Unknown: ");
bt.println(c);
}
}
}Two Serials are open simultaneously: Serial (hardware, USB → laptop monitor) and bt (software, D2/D3 → HC-05 → phone). Lessons L03-15 / L03-16 enabled this.
Step 4 — upload and test
Upload the sketch. The terminal app on your phone should be connected to the HC-05. Type 1 → the LED on D6 lights up; the phone shows "LED ON". Type 0 → LED off. Type anything else → "Unknown: x" on the phone.
Step 5 — try the laptop Serial Monitor too
With the sketch running and the phone connected, open the laptop's Serial Monitor at 9600 baud. Press 1 on the phone → you see "# LED ON" on the laptop monitor AND "LED ON" on the phone. Two windows into the same sketch.
Step 6 — extend with a real action
Replace the LED with a servo from L03-01. F = forward 90°, B = backward 90°, S = stop. Now you have a Bluetooth-controlled servo — the foundation for the BLE robot car of L03-28.
#include <Servo.h>
Servo s;
void setup() {
bt.begin(9600);
s.attach(9);
s.write(90);
}
void loop() {
if (bt.available()) {
char c = bt.read();
if (c == 'F') s.write(180);
else if (c == 'B') s.write(0);
else if (c == 'S') s.write(90);
}
}Walk away from your laptop with the phone in hand. The Arduino runs on USB power (or 9 V battery); you control it from up to ~10 m away. First wireless project of the course.
Try It Yourself 15 min
Goal: Send a heartbeat from the Arduino to the phone every 2 seconds: "tick 1", "tick 2", "tick 3", ... Confirm the data flows in both directions, not just phone → Arduino.
Hint
unsigned long lastTick = 0;
int tickCount = 0;
void loop() {
if (millis() - lastTick >= 2000) {
lastTick = millis();
tickCount++;
bt.print("tick ");
bt.println(tickCount);
}
// ... existing read code ...
}Non-blocking timing (L02-35 pattern). The phone's terminal app fills with ticks.
Goal: Bluetooth-controlled RGB LED. Phone sends R, G, or B to set the colour; X turns off. Use the L01-30 RGB LED wiring on PWM pins.
Hint
One channel per colour, analogWrite for brightness. For a richer protocol: R128 sets red brightness to 128 (parse the digits after R, G, B).
Goal: Bidirectional sensor link. Arduino reads a TMP36 temperature every 5 seconds and sends "temp 23.4 C" to the phone. Phone can also send ? at any time to get an immediate reading. Plus set 25 to set a phone-stored alarm threshold (printed back when crossed).
Hint
Use a String buffer to accumulate characters until you see \n. Then parse: starts with "set " → take the number, store as threshold; equals "?" → immediate read; etc. The L01-26 / L01-27 input-parsing patterns apply directly.
Mini-Challenge · Document your Bluetooth API 10 min
Your sketch is now a tiny remote-controlled device. Document its "API" — the commands it accepts — in plain language.
- Open a fresh page in your engineering notebook.
- Title it "[Device Name] · Bluetooth API · v1".
- For each command, list: character/string, what it does, what the device responds with.
- Note: default PIN, baud rate, expected behaviour on power-up.
Example for the LED sketch
Bluetooth LED · API v1 ====================== Pair: PIN 1234, baud 9600. Connect: any Bluetooth serial terminal at 9600 baud. Commands (case-sensitive): '1' Turn LED on. Responds: "LED ON" '0' Turn LED off. Responds: "LED OFF" any Unknown command. Responds: "Unknown: X" Heartbeat: none in v1.
The Bluetooth car (L03-28) will have a richer API — direction, speed, sensors. Documenting at this stage makes it easy to extend later. Same idea as writing a README for your code.
Recap 5 min
The HC-05 is "UART, but wireless". Wire 4 pins (VCC, GND, TX, RX — with a level divider on RX), pair the phone, open a terminal app, and your sketch's SoftwareSerial reads characters that came from your phone. Default PIN 1234 (sometimes 0000); default baud 9600. iOS users need BLE instead — covered in L03-26. The full pattern shape is what you already know — read a character, switch on it, do something — just over the air instead of a USB cable. Tomorrow we learn to talk to the HC-05 itself (not just through it) using AT commands — rename it, change its PIN, change its baud.
- HC-05
- Cheap Bluetooth Classic module with SPP firmware. The classroom Bluetooth standard for Android-based projects.
- SPP (Serial Port Profile)
- A Bluetooth Classic profile that emulates a serial port over the radio link. Your sketch reads/writes bytes; the radio handles delivery.
- Pairing
- The one-time security handshake between phone and module. Establishes a shared key (using the PIN), saved for future quick connections.
- PIN
- The 4-digit number you enter during pairing. Default for HC-05: 1234. Change it for any real project; cover in L03-24.
- SoftwareSerial
- The library that gives you a second UART on any pin pair. Used to talk to the HC-05 without taking pins 0/1 (which would block USB upload).
- Level shifter / resistor divider
- A small circuit that drops a 5 V signal to 3.3 V to protect a 3.3 V chip. Resistor divider (1k + 2k) is the cheapest; dedicated breakouts (TXS0102) are cleaner.
- RSSI (Received Signal Strength Indicator)
- A measure of how strong the Bluetooth radio link is. Larger values (closer to 0) = better signal. Lower values (negative, far from 0) = weak signal.
- Bluetooth Classic vs BLE
- Classic: higher throughput, SPP, NO iOS support. BLE: lower throughput, GATT services / characteristics, full iOS support. Different radios, different APIs.
Homework 5 min
- Save the Bluetooth LED sketch as
bt-led.ino. - Document its API in your notebook (Mini-Challenge above).
- Tomorrow we'll enter AT mode to rename the HC-05 and change its baud / PIN. Bring: the HC-05 still wired up, and have your phone's Bluetooth settings handy so you can re-pair under the new name.
- Read ahead to ARD-L03-24 (AT Commands).
Bring back next class:
- Working bt-led.ino sketch and wiring.
- Bluetooth API page in your notebook.