Component · Comms

HC-05 Bluetooth Module

The HC-05 adds Bluetooth serial to a robot—pair it with your phone to drive the robot or stream data, using the same TX/RX pins as a wired link.

What it is

The HC-05 is the simplest way to make a robot wireless. It’s a Bluetooth module that behaves like a serial cable with no cable: your microcontroller reads and writes bytes on its TX/RX pins exactly as it would over USB, but the other end is a phone or laptop paired over Bluetooth. Send an F from a phone app and your robot drives forward—no Wi-Fi, no network, no accounts.

Labelled diagram of an HC-05 Bluetooth module: a blue breakout board carrying a metal-shielded Bluetooth radio can with corner rivets, a zig-zag PCB antenna, a status LED, and a 6-pin header (EN, VCC, GND, TXD, RXD, STATE) along the bottom for serial connection.
The module turns a Bluetooth link into a plain serial connection—cross TX/RX to the microcontroller and it looks just like a wired cable. Download SVG

How it works

The HC-05 implements the Bluetooth Serial Port Profile (SPP). Once paired, everything the module receives over the air appears on its TX pin, and everything you send to its RX pin goes over the air to the paired device. Your code just uses the serial port—Serial.read() / Serial.print()—and the wireless link is invisible. Configuration (name, baud, master/slave role) is done with AT commands in a separate command mode, but for most robots the defaults work out of the box.

When to use it

Reach for an HC-05 when you want to command or monitor a robot without a tether:

  • Phone-controlled robots — a Bluetooth app sends drive commands the robot reads over serial and turns into motor control.
  • Live telemetry — stream sensor values or odometry back to a laptop while the robot runs.
  • Wireless tuning — adjust parameters on the fly instead of re-flashing.

If the robot already uses an ESP32, you don’t need an HC-05—the ESP32 has Bluetooth and Wi-Fi built in. The HC-05 is the add-on that gives an Arduino Uno the same wireless trick.

Wiring and gotchas

  • Cross the serial lines: module TX → board RX, module RX → board TX. Getting this backwards is the #1 “it won’t connect” cause.
  • Divide the RX pin down to 3.3 V from a 5 V board like the Uno.
  • Free the hardware serial port while uploading code, or use a software-serial pin pair—the module and the USB programmer can’t share the Uno’s one hardware UART.
  • Pair first (PIN usually 1234/0000); the onboard LED shows connection state.

Pinout

Pin Name What it does
1 EN / KEY Held HIGH at power-on to enter AT command mode
2 VCC 3.6–6 V. The breakout regulates to 3.3 V internally
3 GND Ground
4 TXD Module transmits. Goes to the microcontroller’s RX
5 RXD Module receives. 3.3 V logic — divide a 5 V signal
6 STATE HIGH when a device is connected. Genuinely useful, usually ignored

The STATE pin deserves better than it gets. A robot that reads it knows when its phone has walked out of range, which is the difference between stopping safely and driving into a wall while waiting for a command that will never arrive.

Wiring it to an Arduino

The two mistakes here account for most “it will not connect” reports.

HC-05 Arduino Uno Note
VCC 5 V The onboard regulator handles it
GND GND
TXD Pin 10 (SoftwareSerial RX) Module TX → board RX. Cross them
RXD Pin 11 via divider (SoftwareSerial TX) Board TX → module RX, through 2:1 divider
EN Leave open Only needed for AT mode
STATE Any digital pin Optional connection check

Cross the serial lines

TX talks, RX listens. Two devices that both talk on the wire you connected achieve nothing, and there is no error — the module pairs fine, the LED goes solid, and no data ever moves. Module TX goes to board RX. Module RX goes to board TX.

Divide the RX line

RXD is a 3.3 V input and an Arduino Uno drives 5 V. Two resistors:

Arduino TX ──── 1 kΩ ──┬── HC-05 RXD
                        │
                      2 kΩ
                        │
                       GND

TXD needs no divider in the other direction — the module’s 3.3 V output clears the Uno’s 3.0 V high threshold.

Do not use pins 0 and 1

The Uno has one hardware UART and the USB programmer already owns it. Wire the module there and uploads fail while it is connected, serial monitor output goes to the module, and debugging becomes impossible. Use SoftwareSerial on two other pins.

Minimal working code

#include <SoftwareSerial.h>

SoftwareSerial bt(10, 11);      // RX (from module TX), TX (to module RX)
const int STATE_PIN = 8;

void setup() {
  Serial.begin(115200);         // USB, for debugging
  bt.begin(9600);               // HC-05 default in data mode
  pinMode(STATE_PIN, INPUT);
}

void loop() {
  // Lose the link, stop the robot. Do this before reading commands.
  if (digitalRead(STATE_PIN) == LOW) { stopMotors(); }

  if (bt.available()) {
    char c = bt.read();
    switch (c) {
      case 'F': driveForward();  break;
      case 'B': driveBackward(); break;
      case 'L': turnLeft();      break;
      case 'R': turnRight();     break;
      case 'S': stopMotors();    break;
    }
    Serial.print("cmd: "); Serial.println(c);   // echo to USB for debugging
  }
}

The connection check at the top of the loop is the part most tutorials leave out, and it is the part that stops a runaway. Bluetooth range is about 10 m and walls cut it sharply; a robot that keeps executing its last command after the link drops will keep going until it hits something.

AT command mode

Changing the module’s name, baud rate or PIN needs AT mode, and entering it has a specific sequence that nothing about the module makes obvious.

  1. Power the module off.
  2. Hold EN HIGH (or press and hold the small button, if your board has one).
  3. Power it on while EN is held.
  4. The LED now blinks slowly — roughly once every two seconds — rather than rapidly.
  5. Talk to it at 38400 baud, not 9600, with both newline and carriage return.
AT                    -> OK
AT+NAME=LineBot       -> OK      set the name shown when pairing
AT+PSWD="1234"        -> OK      set the pairing PIN (quotes on newer firmware)
AT+UART=115200,0,0    -> OK      data-mode baud rate
AT+ROLE=0             -> OK      0 = slave (normal), 1 = master
AT+ADDR?              -> +ADDR   the module's own address

Two gotchas: AT mode is always 38400 regardless of the data-mode baud you set, and the LED blink rate is the only reliable indication you are in it. Fast blink means data mode and your AT commands will simply be transmitted over the air to whatever is paired.

HC-05 or HC-06?

They look identical and are sold interchangeably, and there is one real difference.

HC-05 HC-06
Role Master or slave Slave only
Can initiate a connection Yes No
AT mode Via EN pin, 38400 Any time while unpaired, at the data baud
Price Slightly more Slightly less

If the module only ever needs to accept a connection from a phone, an HC-06 is fine. If you ever want two robots to talk to each other, or a robot to connect to a module rather than wait to be connected to, you need the HC-05’s master role.

Troubleshooting

Symptom Likely cause Fix
Pairs, but no data moves TX/RX not crossed Module TX → board RX, module RX → board TX
Garbage characters Baud mismatch Both ends at 9600, or set both to the same value
Uploads fail while connected Module on pins 0/1 Move to SoftwareSerial pins
AT commands do nothing Not actually in AT mode Hold EN during power-on; check for the slow blink
AT mode gives no response Using the data baud AT mode is 38400, always
Will not pair Wrong PIN Try 1234 then 0000
Drops out a few metres away Class 2 range plus walls Expected; use the STATE pin to fail safe
Robot keeps driving after disconnect No link check Read STATE and stop on LOW
Works on USB power, not on battery Supply sag The radio’s transmit bursts need a stiff 5 V

HC-05 or an ESP32?

If you are choosing components rather than using what you have, this is the real decision.

HC-05 + Arduino ESP32
Wireless Bluetooth Classic SPP Wi-Fi and Bluetooth, built in
Extra hardware A module, a divider, two pins None
Control interface A serial byte stream A web page the robot serves itself
Range ~10 m ~50 m on Wi-Fi, or anywhere with a network
Phone app needed Yes — a generic Bluetooth terminal No — any browser
Learning value Serial protocols, the plainest possible link Networking, which is a bigger subject

The HC-05 is the right answer when you already have an Arduino and want the shortest path to a wireless robot. It is genuinely simple: a byte in, a byte out, no networking concepts at all. For a new build where wireless is a requirement, an ESP32 does more for less and needs no extra parts — and a robot that serves its own control page needs no app installed on anyone’s phone.

Explore the graph

Used in these builds

Projects, learning paths, and simulators that include the HC-05 Bluetooth Module.

Compare

Alternatives

Questions

HC-05 Bluetooth Module FAQ

What is an HC-05?

The HC-05 is a Bluetooth module that turns a wireless connection into a plain serial (UART) link. To your microcontroller it looks exactly like a wired serial cable—you read and write bytes on TX/RX—except the other end is your phone or PC over Bluetooth. It's the easiest way to control a robot wirelessly.

How do you connect an HC-05 to an Arduino?

Power VCC and GND, then cross the serial lines—module TX to Arduino RX, module RX to Arduino TX. Because the HC-05's RX pin is 3.3 V, drop the Arduino's 5 V TX with a voltage divider. Then anything you print over serial goes wirelessly to the paired phone, and vice versa.

What is the range of the HC-05?

About 10 metres line of sight—it's a Class 2 Bluetooth device. Walls and interference cut that down. That's plenty for driving a robot around a room from your phone, but for long-range control you'd move to Wi-Fi or a dedicated radio.

How do you pair HC-05 modules?

To pair with a phone, power the module, open your phone's Bluetooth settings, select the HC-05, and enter the PIN (usually 1234 or 0000). To pair two HC-05s to each other, set one as master and one as slave with AT commands and bind them by address.

How do you program the HC-05?

The HC-05 has two modes. In data mode it simply passes serial bytes through. To change its name, baud rate, or master/slave role, put it in AT command mode—hold the EN/KEY pin high at power-up—and send AT commands over serial.

Further reading

References