Difficulty: Intermediate | Time: 45 Minutes | Target Board: Arduino Uno R3 / Nano v3 (ATmega328P)

If you are searching for an "Arduino BT" solution to add wireless serial communication to a standard 5V microcontroller, the HC-05 Bluetooth Classic (SPP) module remains the most reliable and cost-effective choice in 2026. While the original, officially branded "Arduino BT" board (which used the Bluegiga WT11 module) was discontinued years ago, the maker community has standardized on the HC-05 for Classic Bluetooth and the HM-10 or Nano 33 BLE for Bluetooth Low Energy (BLE).

This guide provides the exact wiring, voltage divider math, and compilable code to bridge your Arduino Uno or Nano to an HC-05 module without frying its 3.3V RX pin. We will also debug the most common AT command failures and serial timeout errors that stall 90% of first-time Bluetooth builds.

Parts List & Module Variants for Arduino BT

Before wiring, confirm you have the correct module for your target mobile OS. Bluetooth Classic (SPP) works natively with Android and Windows, but Apple iOS restricts SPP, requiring BLE (HM-10 or native Nano 33 BLE) for custom apps.

Module / Board Protocol Role iOS Support Approx. Cost (2026)
HC-05 (ZS-040) BT Classic (SPP) Master / Slave No (Requires MFi) $6.00 - $8.50
HC-06 BT Classic (SPP) Slave Only No $4.50 - $6.00
HM-10 BLE 4.0 Master / Slave Yes $7.00 - $9.00
Arduino Nano 33 BLE BLE 5.0 (Native) Native Peripheral Yes $22.00 - $26.00

Required Support Components for HC-05:

  • Resistors: One 10kΩ and one 20kΩ (for the TX-to-RX voltage divider).
  • Alternative: A bi-directional logic level converter (BSS138-based, e.g., SparkFun BOB-12009) if you prefer not to build a resistor divider.
  • Wiring: 22 AWG solid core jumper wires.

Pin Mapping & Wiring the HC-05

The most common mistake in Arduino BT projects is connecting the 5V Arduino TX pin directly to the 3.3V HC-05 RX pin. While the HC-05's VCC pin accepts 3.6V to 6V (thanks to an onboard 3.3V regulator), its logic pins are strictly 3.3V tolerant. Feeding 5V into the RX pin will eventually degrade the silicon, leading to intermittent pairing failures.

Pin Mapping Table

Arduino Uno R3 / Nano v3 HC-05 ZS-040 Breakout Notes & Constraints
5V VCC Do not exceed 6V.
GND GND Common ground is mandatory.
Pin 10 (Software RX) TXD Direct connection (3.3V to 5V is read as HIGH safely).
Pin 11 (Software TX) RXD MUST go through a voltage divider.
Pin 9 (Digital Input) EN (or KEY) Pull HIGH (3.3V) before power-up to enter AT mode.

Wiring Steps

  1. Build the Voltage Divider: Connect the 10kΩ resistor to Arduino Pin 11. Connect the other end of the 10kΩ to one leg of the 20kΩ resistor. Connect the other leg of the 20kΩ to GND. The junction between the two resistors connects to the HC-05 RXD pin. This drops the 5V logic down to exactly 3.33V ($5V \times \frac{20k}{10k+20k}$), which is perfectly safe for the HC-05. For deeper theory on logic thresholds, refer to SparkFun's guide on logic levels.
  2. Wire the State Pin: Connect the HC-05 STATE pin to Arduino Pin 9. This tells your code if the module is actively paired (HIGH) or searching (LOW).
  3. Power Cycle for AT Mode: If you need to change the baud rate or device name, wire the EN/KEY pin to 3.3V before applying power to the VCC pin. The LED should blink slowly (once every 2 seconds) to indicate AT command mode.

Compilable Code: Two-Way Bluetooth Serial Bridge

This code targets the Arduino Uno R3 and Nano v3 (ATmega328P). It uses the SoftwareSerial library to create a secondary serial port on pins 10 and 11, leaving the hardware UART (pins 0 and 1) free for USB debugging via the Serial Monitor. It includes non-blocking reads and overflow error handling, which are critical for preventing dropped bytes in high-throughput sensor logging.

#include <SoftwareSerial.h>

// --- PIN DEFINITIONS ---
#define BT_RX_PIN 10      // Arduino RX -> HC-05 TX (Direct)
#define BT_TX_PIN 11      // Arduino TX -> HC-05 RX (Via Voltage Divider)
#define BT_STATE_PIN 9    // Arduino Input <- HC-05 STATE

// Initialize SoftwareSerial
SoftwareSerial btSerial(BT_RX_PIN, BT_TX_PIN);

unsigned long lastStatusPrint = 0;
bool isConnected = false;

void setup() {
  // Hardware serial for USB debugging
  Serial.begin(9600);
  while (!Serial) { ; } // Wait for serial port (Leonardo/Micro only, safe for Uno)
  
  // Bluetooth serial (Default HC-05 normal mode baud is 9600)
  btSerial.begin(9600);
  
  pinMode(BT_STATE_PIN, INPUT);
  
  Serial.println(F("Arduino BT Bridge Initialized."));
  Serial.println(F("Waiting for HC-05 connection..."));
}

void loop() {
  // 1. Check connection state non-blockingly
  bool currentState = digitalRead(BT_STATE_PIN);
  if (currentState != isConnected) {
    isConnected = currentState;
    if (isConnected) {
      Serial.println(F("[STATUS] Bluetooth Device Paired!"));
      btSerial.println(F("Hello from Arduino!"));
    } else {
      Serial.println(F("[STATUS] Bluetooth Disconnected."));
    }
  }

  // 2. Forward Hardware Serial (USB) to Bluetooth
  if (Serial.available()) {
    btSerial.write(Serial.read());
  }

  // 3. Forward Bluetooth to Hardware Serial (USB) with Error Handling
  if (btSerial.available()) {
    // Check for buffer overflow (happens if loop() is blocked by delays)
    if (btSerial.overflow()) {
      Serial.println(F("[ERROR] SoftwareSerial buffer overflow! Bytes dropped."));
    }
    Serial.write(btSerial.read());
  }

  // 4. Periodic heartbeat to verify loop timing
  if (millis() - lastStatusPrint > 5000) {
    lastStatusPrint = millis();
    if (isConnected) {
      btSerial.println(F("Heartbeat: System OK"));
    }
  }
}

Note: For official documentation on SoftwareSerial limitations, such as the inability to transmit and receive simultaneously on certain pins, consult the Arduino SoftwareSerial reference.

Debugging: Fixing "ERROR: (17)" and Serial Timeouts

When configuring the HC-05 via AT commands, or when reading sensor data in normal mode, you will inevitably hit serial communication errors. Here is the decision path for the most common failure modes.

Exact Error String: ERROR: (17) or ERROR: (0) when sending AT commands.
Exact Error String: ⸮⸮⸮⸮⸮ (Garbage characters) in the Serial Monitor during normal operation.

The First Three Things to Check When It Fails

  1. Baud Rate Mismatch: The HC-05 defaults to 9600 baud in normal data mode, but switches to 38400 baud when entering AT command mode. If your btSerial.begin() does not match the module's current state, you will receive garbage characters (⸮⸮⸮). Fix: Set Serial Monitor to 38400 for AT commands, and 9600 for normal data.
  2. AT Command Syntax (The \r\n Trap): The HC-05 firmware requires a Carriage Return and Line Feed (\r\n) at the end of every AT command. If you type AT+NAME=MyBT in the Serial Monitor and get ERROR: (0) (Invalid Command) or ERROR: (17) (Invalid Parameter), change your Serial Monitor dropdown from "No line ending" to "Both NL & CR".
  3. EN Pin Timing: If the HC-05 LED is blinking rapidly (2 times per second), it is in normal pairing mode, not AT mode. The EN/KEY pin must be pulled HIGH before the module receives power. If you wire it after power-up, it will ignore the AT mode request until the next power cycle.

Ranked Causes for Intermittent Disconnects

If your Arduino BT setup pairs successfully but drops connection after 10-30 minutes, check these in order:

  • Power Supply Sag (Most Likely): The HC-05 draws up to 45mA during transmission. If powered directly from the Arduino's onboard 5V regulator while running sensors and LEDs, the voltage sags below 3.6V, causing the module's internal watchdog to reset. Fix: Power the HC-05 VCC from an external 5V buck converter.
  • SoftwareSerial Blocking: If your loop() contains delay() calls longer than 64 bytes / 9600 baud (approx. 60ms), the SoftwareSerial buffer overflows, corrupting the UART stream and causing the receiving phone app to drop the socket. Fix: Use millis() for timing, as shown in the code above.
  • RF Interference: 2.4GHz Wi-Fi routers placed within 1 meter of the HC-05 can cause packet loss. Move the antenna away from the ESP8266/Wi-Fi antenna.

Extending and Simplifying the Build

How to Simplify: Ditch the Module, Use an ESP32

If you are starting a new project in 2026 and do not strictly require an ATmega328P, simplify your build by switching to an ESP32 DevKit V1. The ESP32 has native Bluetooth Classic and BLE built directly into the SoC. You eliminate the voltage divider, the SoftwareSerial overhead, and the wiring entirely. You can program it using the Arduino IDE with the BluetoothSerial.h library, reducing your BOM cost and physical footprint.

How to Extend: Mobile App Integration & Relay Control

To extend this bridge into a home automation controller:

  1. Mobile UI: Use MIT App Inventor to build a custom Android app. Use the "Bluetooth Client" block to send single-character commands (e.g., '1' for ON, '0' for OFF) to the Arduino.
  2. Hardware Control: Add an optocoupler (like the PC817) between the Arduino output pin and a 5V relay module. This provides galvanic isolation, ensuring that inductive kickback from a relay coil switching a mains-powered fan never travels back through the ground plane to reset your HC-05.

Arduino BT FAQ

Can I still buy and use the original Arduino BT board in 2026?

No. The original Arduino BT board, which featured the Bluegiga WT11 Bluetooth module and an ATmega168, was officially retired over a decade ago. Any boards sold under that exact name today are either counterfeits, used surplus, or mislabeled clones. For modern projects, pairing an Arduino Uno R3 with an HC-05 or using a Nano 33 BLE is the supported, documented path.

Why does my HC-05 module blink rapidly and refuse to pair?

A rapid blink (typically 2 to 5 times per second) indicates the module is in "Normal Data Mode" and is discoverable. If your phone sees the device (usually named "HC-05" or "BT05") but fails to pair or immediately disconnects, the issue is almost always power-related. The internal voltage regulator on the ZS-040 breakout board overheats if supplied with more than 5.5V, or the module browns out if the host Arduino's 5V rail is sagging under load. Ensure you are feeding it a clean, regulated 5V source.

How do I put the HC-05 into AT command mode reliably?

There are two methods depending on your breakout board. If your board has a small pushbutton labeled "EN" or "KEY", hold that button down while plugging in the USB cable to the Arduino, then release it. The LED should blink slowly (once every 2 seconds). If your board only has a pin header for EN/KEY, wire that pin to the Arduino's 3.3V output, then apply power to VCC. Once the slow blink is confirmed, open the Serial Monitor at 38400 baud with "Both NL & CR" selected to send commands like AT+UART=115200,0,0.

Is Bluetooth Classic (HC-05) or BLE (HM-10) better for iOS devices?

If your target device is an iPhone or iPad, you must use BLE (HM-10 or Nano 33 BLE). Apple's MFi (Made for iPod/iPhone) program restricts Bluetooth Classic SPP profiles to certified, expensive hardware. Standard HC-05 modules will not appear in the iOS Bluetooth settings menu for custom serial apps. BLE modules communicate via the CoreBluetooth framework, which is open to all iOS developers and works seamlessly with apps like LightBlue or custom Swift applications.