Arduino and HC-05/HC-06 Bluetooth Module Complete Tutorial

This post contains affiliate links, marked with *. As an Amazon Associate I earn from qualifying purchases, at no extra cost to you. It helps keep the tutorials free.

The video loads from YouTube (Google), which may set cookies. Privacy policy

Quick summary

You connect an HC-05 or HC-06 Bluetooth module to an Arduino. An Android app built in MIT App Inventor switches the Arduino’s outputs. Project 1 switches an LED. Project 2 uses the same module and app and switches a 230 V lamp through a relay. If you are new to Arduino, start with the Arduino programming basics guide.

HC-05 vs. HC-06: which module to choose

The HC-05 and HC-06 are two of the most common Bluetooth modules in Arduino projects. Both are Bluetooth Classic modules (version 2.0). Bluetooth Classic is the original Bluetooth standard; Bluetooth Low Energy (BLE) is a newer, separate standard. The modules connect to the Arduino through its serial port, the TX (transmit) and RX (receive) pins. The main difference: the HC-05 can work as master or slave, the HC-06 only as slave. A master starts a connection; a slave waits for one.

  • HC-06: enough when a phone or PC sends commands to the Arduino, as in both projects here. Your smartphone is the master, the module is the slave. It is slightly cheaper.
  • HC-05: needed for master mode, for example when two Arduinos talk to each other; at least one side must be an HC-05 set as master.

I used an HC-05 in my Bluetooth robot car, my 6-DOF robotic arm with Bluetooth control and the OmObiArm mobile robot. In all three, the phone is the master, so an HC-06 would work as well.

Technical comparison table

FeatureHC-05HC-06
RoleMaster and slaveSlave only
Bluetooth version2.0 (Bluetooth Classic)2.0 (Bluetooth Classic)
RangeClass 2, about 10 mClass 2, about 10 m
VCC (breakout board)3.6 to 6 V, powered from the Arduino’s 5 V pin3.6 to 6 V, powered from the Arduino’s 5 V pin
Default baud rate9600 on most modules (AT command mode: 38400)9600
Baud rate configurableYes, 2400 to 1382400 with AT commandsYes, with AT+BAUD commands on most firmware versions
Default PIN12341234 (some modules: 0000)

Class 2 is a Bluetooth power class; Class 2 devices reach about 10 m. VCC is the supply pin of the breakout board, the small carrier board with pins that holds the module. AT commands are short text commands that read or change module settings such as name, PIN and baud rate. The HC-05 accepts them in its AT command mode, which runs at 38400 baud.

How the Bluetooth link works

  1. Arduino serial port: the Arduino sends data on its TX pin (pin 1) and receives data on its RX pin (pin 0). Serial.begin() sets the speed in bits per second (baud rate); Serial.read() reads one received byte.
  2. Bluetooth module: a wireless serial bridge. Every byte the phone sends arrives at the Arduino’s RX pin unchanged, as if it came through the USB cable.
  3. Phone app: sends one character per command, ‘1’ for ON and ‘0’ for OFF.
  4. Arduino sketch (the program on the board): reads the character and sets pin 7 HIGH (5 V) or LOW (0 V), which switches the LED or the relay.
Signal flow of Project 2: Turn ON in the app sends 1 and the Arduino Uno puts 5 V on the relay, so the lamp lights; Turn OFF sends 0, the Arduino outputs 0 V and the lamp goes off

The same one-character pattern works for motors, servos or displays. For the board itself, see what Arduino is and how it works.

Components

Core components (both projects)

ComponentQuantityNotes
HC-05 or HC-06 Bluetooth module1Either module works for both projects
Arduino Uno, Nano or Mega1For other boards, see the FAQ
1 kΩ resistor1Voltage divider
2 kΩ resistor1Voltage divider (or two 1 kΩ in series)
Breadboard1For prototyping connections
Jumper wires (male-to-male)SeveralConnections between board, breadboard and module
USB cable for your board1USB-B for Uno/Mega; Mini-USB, Micro-USB or USB-C for Nano, depending on the version
Android smartphone or tablet1Runs the control app

Additional components for Project 1: LED control

ComponentQuantityNotes
LED (any color)1Standard 5 mm through-hole LED
220 Ω resistor1Current-limiting resistor: limits the current through the LED

Additional components for Project 2: relay and lamp

ComponentQuantityNotes
Relay module (5 V, single channel)1Opto-isolated module recommended (an optocoupler separates the Arduino input from the relay coil circuit)
Lamp (230 V or 110 V)1A small mains lamp within the relay’s contact rating (printed on the relay, often 10 A at 250 V AC; AC means alternating current)
Lamp holder and power cable1For safe mains wiring

Project 1: Bluetooth LED control

The phone switches an LED on pin 7.

Circuit wiring for LED control

Connect the module and the LED as in the two tables below. The module’s TXD pin (transmit) goes to the Arduino’s RX (pin 0), and the module’s RXD pin (receive) goes to the Arduino’s TX (pin 1). They cross over.

The module’s RXD input works at 3.3 V, but the Arduino’s TX pin outputs 5 V, so this line needs a voltage divider: two resistors in series that reduce the voltage. Wire Arduino TX (pin 1) → 1 kΩ → module RXD, and module RXD → 2 kΩ → GND (ground, 0 V). The module then sees 5 V × 2 kΩ / (1 kΩ + 2 kΩ) ≈ 3.3 V.

Module pinArduino pinNotes
VCC5 VPower supply for the module
GNDGNDCommon ground
TXDRX (pin 0)Module transmit → Arduino receive
RXDTX (pin 1)Through the voltage divider (1 kΩ + 2 kΩ)
LED pinArduino pinNotes
Anode (long leg)Pin 7, through the 220 Ω resistorDigital output pin
Cathode (short leg)GNDCommon ground
Wiring diagram for Project 1: HC-05 Bluetooth module and an LED wired directly to an Arduino Uno, LED on pin 7 and GND

The diagram shows the direct connections only. Add the voltage divider and the 220 Ω resistor from the tables above.

Arduino code for Bluetooth LED control

The sketch listens for incoming characters on the serial port and switches the LED on pin 7.

Before uploading: disconnect the Bluetooth module from pins 0 and 1. The Arduino uses the same two pins for USB programming. If the module stays connected, the upload usually fails with an error such as “avrdude: stk500_getsync(): not in sync”. This caused me problems on my Bluetooth robot car. Reconnect the module after the upload.

/**
 * Author: Omar Draidrya
 * Date: 2024/06/26
 * Bluetooth LED Control -- HC-05 / HC-06 Arduino Tutorial
 * Receives '1' or '0' from a smartphone via Bluetooth
 * and turns an LED on or off.
 */

#define ledPin 7 // Pin for the LED

char state = 0; // Variable to store incoming data

void setup() {
  pinMode(ledPin, OUTPUT);      // Set the LED pin as output
  digitalWrite(ledPin, LOW);    // Initialize the LED state to OFF
  Serial.begin(9600);           // Start serial at 9600 baud
}

void loop() {
  if (Serial.available() > 0) {       // Check if data is available
    state = Serial.read();             // Read the incoming byte

    if (state == '0') {                // If '0' is received
      digitalWrite(ledPin, LOW);       // Turn LED OFF
      Serial.println("LED: OFF");      // Send confirmation back
    } else if (state == '1') {         // If '1' is received
      digitalWrite(ledPin, HIGH);      // Turn LED ON
      Serial.println("LED: ON");       // Send confirmation back
    }
  }
}

Code explanation: LED sketch

  • #define ledPin 7: before compiling, every ledPin in the sketch is replaced by 7. It is a fixed value, not a variable. Change the number to use another digital pin.
  • Serial.begin(9600): starts serial communication at 9600 baud. The value must match the baud rate of your module. The HC-06 and most HC-05 modules use 9600, and so does the HC-05 in my video. If yours ships at 38400, change this line to Serial.begin(38400) or set the module to 9600 with AT commands.
  • Serial.available(): returns the number of received bytes waiting in the serial buffer, a small memory area where incoming bytes wait until the sketch reads them. When the phone sends a character, this becomes greater than 0.
  • Serial.read(): reads one byte from the serial buffer and stores it in the state variable.
  • if (state == ‘1’): compares the received character to ‘1’. If it matches, digitalWrite(ledPin, HIGH) turns the LED on. If ‘0’ arrives, the LED turns off. ‘1’ in quotes is the character; 1 without quotes would be the number, and the comparison would fail.
  • Serial.println(): sends a confirmation text back over Bluetooth. The app built here does not display it; a Bluetooth serial terminal app on the phone does.

To put the HC-05 into AT command mode, hold its KEY/EN pin HIGH while you power it up. In this mode, commands such as AT+UART? read or change the module settings.

Building the control app with MIT App Inventor

The Arduino needs an Android app that sends the characters. MIT App Inventor is a free visual programming platform: you program with blocks instead of typed code. The same app works for both projects. The Arduino code decides what happens when ‘1’ or ‘0’ arrives, not the app.

Step 1: Create a project

  1. Open MIT App Inventor and log in with your Google account.
  2. Click “Start New Project” and name it “BluetoothControl”.

Step 2: Design the user interface

Set the Title of Screen1 to “Bluetooth Control”. In the Designer view, add these components and keep their default names, because the blocks below use them:

  1. Label1: text “Not Connected”. It shows the connection status.
  2. ListPicker1: text “Select Bluetooth Device”. It lists the Bluetooth devices already paired with the phone.
  3. Button1: text “Turn ON”.
  4. Button2: text “Turn OFF”.
  5. BluetoothClient1 from the Connectivity palette. It is a non-visible component: it does not appear on the screen and handles the Bluetooth connection.

Step 3: Program the blocks

Switch to the Blocks editor and build this logic:

when ListPicker1.BeforePicking
  set ListPicker1.Elements to BluetoothClient1.AddressesAndNames

when ListPicker1.AfterPicking
  if call BluetoothClient1.Connect address ListPicker1.Selection
    then set Label1.Text to "Connected"
    else set Label1.Text to "Not Connected"

when Button1.Click
  if BluetoothClient1.IsConnected
    call BluetoothClient1.SendText text "1"

when Button2.Click
  if BluetoothClient1.IsConnected
    call BluetoothClient1.SendText text "0"
  1. ListPicker1.BeforePicking loads the names and addresses of all paired devices into the list before it opens.
  2. ListPicker1.AfterPicking connects to the selected device. On success, Label1 shows “Connected”; otherwise it stays at “Not Connected”.
  3. Button1.Click and Button2.Click send the text “1” or “0” while a connection is open. The Arduino reads these characters and acts on them.
MIT App Inventor blocks of the control app: ListPicker1 BeforePicking and AfterPicking, Button1 sends 1, Button2 sends 0

Step 4: Build and install the app

In MIT App Inventor, open Build → Android App (.apk) and scan the QR code with your phone to install the app. An .apk file is the installation file of an Android app. Allow installation from this source when Android asks. On Android 12 or newer, allow the Nearby devices permission; if the device list stays empty, enable it under Settings → Apps → BluetoothControl → Permissions.

I downloaded the .apk to my computer instead, copied it to my Android tablet and installed it with the file manager. On the tablet, the app’s device list stayed empty until I allowed Nearby devices and paired the module.

Connecting your smartphone to the module

You pair each module with your phone only once.

Step 1: Pair the Bluetooth module

  1. Power the Arduino via USB or an external supply. The module’s LED blinks fast: it is in pairing mode and waits for a connection.
  2. On your Android phone, open Settings → Bluetooth and switch Bluetooth on.
  3. Scan for devices. The module appears as “HC-05” or “HC-06”; some modules use another name, for example “linvor” on older HC-06 firmware.
  4. Tap it to pair and enter the PIN 1234 (on some HC-06 modules: 0000).
  5. The module now appears under “Paired devices”. Pairing alone does not change the LED. Once the app connects, the HC-05 LED blinks twice about every 2 s and the HC-06 LED stays on.

Step 2: Connect via the app

  1. Open the BluetoothControl app.
  2. Tap “Select Bluetooth Device”. The list shows the paired devices.
  3. Select the module. Label1 changes to “Connected”.
  4. Press “Turn ON” to send ‘1’ and “Turn OFF” to send ‘0’.

If the module is missing from the list, check that it has power and that you paired it in the phone’s Bluetooth settings. The ListPicker only shows paired devices.

Project 2: Relay and 230 V lamp control

Project 2 replaces the LED with a relay module. A relay is an electrically controlled switch: the Arduino drives its coil, and its contact opens or closes the 230 V (or 110 V) lamp circuit. The contact has two terminals you need here: COM (common) and NO (normally open). NO is connected to COM only while the relay is on.

⚠ Safety warning: Mains voltage (230 V or 110 V) can cause serious injury or death. If you have no experience with mains wiring, do not build Project 2; work with a qualified electrician. Test first with a low-voltage load on the relay’s COM and NO terminals, for example a 5 V buzzer or a 12 V LED strip with its own supply. Check that the relay clicks. Insulate every mains connection and put the relay module and all mains wiring in a closed, insulated enclosure with strain relief on the cable. Cheap relay modules leave little distance between the mains contacts and the low-voltage side, so never touch the circuit while it is plugged in. The low-voltage test needs no code change: the sketch and the wiring on the Arduino side stay the same.

Circuit wiring for relay lamp control

The Bluetooth wiring is the same as in Project 1. Only the output changes: pin 7 now drives the relay module’s IN pin.

Relay module pinArduino pinNotes
VCC5 VPower for the relay module
GNDGNDCommon ground
INPin 7Control signal from the Arduino
WireConnects toNotes
Mains live (L)Relay COMOnly the live wire is switched
Lamp live wireRelay NOConnected to COM while the relay is on
Mains neutral (N)Lamp neutral wire, directlyDoes not pass through the relay
Protective earth (PE, green-yellow)Lamp earth terminal, directlyRequired for lamps with a metal housing; never through the relay
Wiring diagram for Project 2: HC-05 Bluetooth module and relay module wired to an Arduino Uno, relay IN on pin 7, lamp switched through COM and NO

This diagram also shows the direct connections only. Keep the voltage divider from Project 1 on the module’s RXD line.

Arduino code for Bluetooth relay control

The relay sketch follows the LED sketch; pin 7 now drives the relay’s IN pin. Upload it with the module disconnected from pins 0 and 1, as in Project 1.

/**
 * Author: Omar Draidrya
 * Date: 2024/06/26
 * Bluetooth Relay/Lamp Control -- HC-05 / HC-06 Arduino Tutorial
 * Receives '1' or '0' from a smartphone via Bluetooth
 * and switches a relay (connected to a lamp) on or off.
 */

#define relayPin 7   // Pin connected to relay IN

int state = 0;       // Variable to store incoming data

void setup() {
  pinMode(relayPin, OUTPUT);       // Set relay pin as output
  digitalWrite(relayPin, LOW);     // Initialize relay to OFF
  Serial.begin(9600);              // same baud rate as Project 1
}

void loop() {
  if (Serial.available() > 0) {        // Check if data is available
    state = Serial.read();              // Read the incoming byte
  }

  if (state == '0') {
    digitalWrite(relayPin, LOW);        // Turn Relay OFF
    Serial.println("Lamp: OFF");        // Send confirmation back
    state = 0;                          // Reset state
  } else if (state == '1') {
    digitalWrite(relayPin, HIGH);       // Turn Relay ON
    Serial.println("Lamp: ON");         // Send confirmation back
    state = 0;                          // Reset state
  }
}

Code explanation: relay sketch

  • state = 0; after each action: the if/else check runs outside the Serial.available() block. Without the reset, the sketch would repeat the last command and send “Lamp: ON” in every pass of loop(). The reset makes each command run once.
  • Relay logic: relay modules differ. Some switch on when IN is HIGH (active-HIGH); many opto-isolated modules switch on when IN is LOW (active-LOW), and some have a jumper to choose. My module in the video is active-HIGH: 5 V on IN closes the relay contact and the lamp lights, 0 V opens it. If the lamp is on right after power-up or reacts inverted, swap HIGH and LOW in the sketch, including the line in setup().

Reconnect the module and test with the same app. The relay clicks when you press “Turn ON” and releases when you press “Turn OFF”.

Troubleshooting

Wiring and hardware issues

ProblemLikely causeSolution
Phone cannot find the moduleModule not powered or not in pairing modeCheck that the module’s LED blinks fast. Verify VCC and GND. Check that Bluetooth is on in the phone.
Communication fails, or the TX/RX wiring looks wrongTX and RX swappedModule TXD goes to Arduino RX (pin 0), module RXD goes to Arduino TX (pin 1). They cross over.
LED does not switch on or offWrong pin or missing resistorLED anode to pin 7 through the 220 Ω resistor, cathode to GND. Verify pin 7 in the code.
Relay clicks but lamp stays offIncorrect mains wiring at the relayLive wire to COM, lamp live wire to NO, neutral directly to the lamp.
Lamp is on right after power-up, or reacts invertedActive-LOW relay moduleSwap HIGH and LOW in the sketch, including setup(). Check the module for an H/L jumper.

Serial communication and app issues

ProblemLikely causeSolution
No response from the Arduino after uploadingModule was connected during uploadDisconnect the module from pins 0 and 1 before uploading. USB and the module share these pins.
App connects, Arduino does not reactBaud rate in Serial.begin() does not match the module, or the buttons send the wrong charactersSet Serial.begin(9600) (or 38400). Check that Button1 sends the text “1” and Button2 the text “0”, not numbers; the sketch compares character literals.
HC-05 LED blinks slowly, one blink about every 2 s (not the double blink of a connection)Module is in AT command mode (KEY pin HIGH at power-up)Disconnect the KEY pin and switch the module’s power off and on.
HC-06 LED stays on, app cannot connectModule is already connected to another deviceDisconnect the other device.
App shows “Not Connected” after selecting the deviceModule connected to another device, or pairing expiredUnpair and re-pair the module in the phone’s Bluetooth settings. Make sure no other phone or app is connected to the module.
Device list in the app is empty (Android 12 or newer)Nearby devices permission missingSettings → Apps → BluetoothControl → Permissions, allow Nearby devices.

Frequently asked questions

Can I control more than one LED or relay with this setup? Yes. Extend the code with more characters (‘2’, ‘3’, ‘A’, ‘B’), each assigned to a different pin, and add one button per character in the app. The Bluetooth-controlled robot car uses this approach for its motor commands.

Does this work with an iPhone? No. The HC-05 and HC-06 use Bluetooth Classic with the Serial Port Profile (SPP), which iOS does not support for this kind of module. An iPhone needs a BLE module such as the HM-10, or the ESP32 with its built-in BLE.

How far does the Bluetooth connection reach? Both modules are Class 2 Bluetooth devices with a range of about 10 m (33 feet) in open air. Walls and furniture reduce it.

Can I use SoftwareSerial instead of pins 0 and 1? Yes. The SoftwareSerial library turns two other digital pins into a serial port. This avoids the upload conflict and keeps the Serial Monitor (the Arduino software’s window for serial text) free for finding errors. SoftwareSerial becomes unreliable at high baud rates, so keep it at 9600. Wire module TXD to pin 10 and module RXD to pin 11 through the same voltage divider. With the Adafruit Motor Shield V1 of my robot cars, pin 11 drives motor M1; use A0 and A1 there.

Can I use this with other Arduino boards? Yes. On the Uno and Nano, use the wiring and code as shown. On the Mega, Serial1 (pins 18/19), Serial2 (16/17) or Serial3 (14/15) are alternatives that avoid the upload conflict on pins 0 and 1. On the Leonardo and Micro, Serial is the USB port; a module on pins 0 and 1 is Serial1, so replace Serial with Serial1 in the sketch.

Resources and next projects

Beginner follow-up projects

Advanced Bluetooth projects

Next step: map more characters to more pins (see the FAQ), or build the Bluetooth-controlled robot car from the list above. If your module behaves differently, post its version and baud rate in the comments.

2 thoughts on “Arduino and HC-05/HC-06 Bluetooth Module Complete Tutorial”

Leave a Comment