The Physical Layer: UART Mechanics and Wiring Requirements
When makers search for "Arduino Bluetooth," they are usually looking at UART-to-Bluetooth bridge modules like the HC-05 (Classic SPP), HC-06, or HM-10 (BLE 4.0). These modules do not speak SPI or I2C; they rely on asynchronous serial (UART) to shuttle bytes between the microcontroller's TX/RX pins and the 2.4GHz RF transceiver. Understanding the physical layer is where 90% of bench failures originate.
Bus Mechanics and Module Specifications
| Module / Protocol | Wires (Min) | Speed (Baud) | Addressing | Max Distance |
|---|---|---|---|---|
| HC-05 (Classic SPP) | 4 (VCC, GND, TX, RX) | 9600 (Data) / 38400 (AT) | MAC Address / Pairing PIN | ~10 meters (Class 2) |
| HM-10 (BLE 4.0) | 4 (VCC, GND, TX, RX) | 9600 (Default) | UUID / GATT Services | ~30 meters (Line of sight) |
| ESP32 (Native BLE) | 0 (Internal Bus) | N/A (Internal) | UUID / MAC / NimBLE Stack | ~50+ meters (with antenna) |
Physical Wiring and Pull-Up Requirements
The most common mistake on the bench is ignoring logic level thresholds. The Arduino Uno (ATmega328P) outputs 5V on its TX pin. The HC-05 RX pin is technically 3.3V tolerant via an onboard LDO, but the HM-10 is strictly a 3.3V device. Feeding 5V into an HM-10 RX pin will permanently brick the module's silicon.
The Voltage Divider: You must step down the Arduino TX (5V) to the Module RX (3.3V). Use a 1kΩ resistor in series with the TX line, and a 2kΩ resistor pulling the module's RX pin to GND. The Module TX (3.3V) can connect directly to the Arduino RX (5V) pin, as 3.3V exceeds the ATmega's 2.0V high-level threshold.
Pull-Up Requirements: The HC-05 features a KEY (or EN) pin. To force the module into AT command mode for configuration, the KEY pin must be pulled HIGH (3.3V) before power is applied. A 10kΩ pull-up resistor to the 3.3V rail is standard practice here. If left floating, the module defaults to transparent data mode.
Minimal Working Exchange: Code and Circuit
Below is a minimal, robust echo server using Arduino's SoftwareSerial library. This allows you to keep the hardware serial port (pins 0 and 1) free for debugging via the USB Serial Monitor.
Wiring Map (Arduino Uno to HC-05):
- Arduino 5V → HC-05 VCC
- Arduino GND → HC-05 GND
- Arduino Pin 10 → 1kΩ Resistor → HC-05 RXD (with 2kΩ to GND)
- Arduino Pin 11 → HC-05 TXD
#include <SoftwareSerial.h>
// Pin definitions for SoftwareSerial
const int BT_RX_PIN = 10; // Connects to HC-05 TXD
const int BT_TX_PIN = 11; // Connects to HC-05 RXD via voltage divider
SoftwareSerial BTSerial(BT_RX_PIN, BT_TX_PIN);
void setup() {
// Initialize hardware serial for USB debugging
Serial.begin(9600);
while (!Serial) { ; } // Wait for serial port (Leonardo/Micro only)
// Initialize Bluetooth serial at default HC-05 data baud rate
BTSerial.begin(9600);
Serial.println("Bluetooth UART initialized. Waiting for connection...");
}
void loop() {
// Forward data from Bluetooth module to USB Serial Monitor
if (BTSerial.available()) {
char c = BTSerial.read();
Serial.print(c);
}
// Forward data from USB Serial Monitor to Bluetooth module
if (Serial.available()) {
char c = Serial.read();
BTSerial.print(c);
}
}
Protocol Selection: Distance, Speed, and Device Count
Choosing the right protocol depends entirely on your topology and power constraints. Here is the decision framework for 2026 embedded designs:
- Choose Classic SPP (HC-05) when: You need a simple 1-to-1 serial pipe, you are connecting to legacy Android devices or Windows PCs via virtual COM ports, and power consumption (50mA idle) is not a concern. SPP does not work natively with iOS due to Apple's MFi restrictions.
- Choose BLE (HM-10 or ESP32) when: You need iOS compatibility, low power (microamps in sleep), or 1-to-many broadcasting (beacons). BLE requires parsing GATT (Generic Attribute Profile) services and characteristics, which adds software complexity but enables secure, structured data exchange.
- Choose ESP32 Native when: You are starting a new project. An ESP32 DevKit V1 costs roughly $5 and includes native BLE 4.2 and WiFi. Using an Arduino Uno ($25) plus an HC-05 ($8) is now largely a legacy educational exercise. The Espressif ESP-IDF Bluetooth API or the Arduino-BLE library provides vastly superior range and throughput.
Debugging the Bus: Sniffing and Classic Failures
When the serial monitor spits out garbage characters or the module refuses to pair, you are dealing with one of three classic physical or data-link failures.
1. The Baud Rate Mismatch
If your serial output looks like `ÿÿÿ`, your baud rates do not match. The HC-05 has two distinct baud rates: 9600 bps for transparent data mode, and 38400 bps for AT command mode. If you send `AT+BAUD` at 9600 while the KEY pin is held high, the module will ignore you. Fix: Ensure your `SoftwareSerial.begin()` matches the module's current state (38400 for AT configuration, 9600 for normal data).
2. Address Clash and Pairing Lockouts
If your phone cannot discover the HC-05, the module is likely already connected to a previously paired device in the room, or it was accidentally configured as a "Master" instead of a "Slave" via AT commands. Fix: Send `AT+ROLE=0` to force slave mode, and `AT+CMODE=0` to restrict pairing to a specific bound MAC address, or `AT+CMODE=1` to allow any device.
3. Sniffing the TX/RX Lines
If the microcontroller code is failing silently, you need to sniff the bus. Do not guess. Connect a cheap $10 USB-to-TTL adapter (like an FTDI FT232RL breakout) to the Bluetooth module's TX pin. Open a terminal on your PC at the correct baud rate. If you see the module transmitting data to the FTDI adapter, but the Arduino isn't receiving it, your voltage divider is miswired or your `SoftwareSerial` pins are swapped (a remarkably common mistake, as TX must always connect to RX).
Arduino Bluetooth FAQ
Why is my Arduino Bluetooth module flashing rapidly but not connecting?
A rapidly flashing LED (typically 2-5 times per second) on an HC-05 or HC-06 means the module is powered, in slave mode, and waiting for a pairing request. Once a device successfully pairs and opens the serial socket, the LED will transition to a slow, double-blink pattern. If it never slows down, your phone is either not sending the correct pairing PIN (default is usually `1234` or `0000`), or the module is configured to only accept a specific MAC address that isn't your phone.
How do I wire a 5V Arduino to a 3.3V HM-10 BLE module safely?
You must use a logic level converter or a resistor voltage divider. Wire the Arduino TX (5V) through a 1kΩ resistor to the HM-10 RX pin, and place a 2kΩ resistor between the HM-10 RX pin and GND. This drops the 5V signal down to a safe ~3.33V. The HM-10 TX pin (3.3V) can wire directly to the Arduino RX pin, as the ATmega328P will reliably read 3.3V as a logic HIGH.
Can I use the Arduino Serial Monitor and Bluetooth at the same time?
Yes, but only if you use `SoftwareSerial` for the Bluetooth module and reserve the hardware `Serial` (pins 0 and 1) for the USB Serial Monitor. If you wire the Bluetooth module directly to pins 0 and 1, the USB-to-serial chip (ATmega16U2) will fight the Bluetooth module for control of the line, resulting in corrupted data and failed uploads. Always disconnect Bluetooth from pins 0 and 1 when flashing new code via USB.
Why does my HC-05 enter AT mode automatically and ignore my phone?
This happens when the KEY (or EN) pin is left floating or accidentally pulled HIGH. The HC-05 checks the state of the KEY pin exactly once during the boot sequence. If it reads HIGH, it boots into AT command mode at 38400 baud and ignores all standard Bluetooth pairing requests. Ensure the KEY pin is tied to GND (or left completely disconnected if your breakout board has an internal pull-down) during normal operation.






