Connect an Arduino to a Rasberry Pi via an HC-05 Bluetooth Module

Walk through of how to connect an HC-05 bluetooth module to a Raspbery Pi and setting up a service to automatically connect the device on startup and disconnect.

The £5 HC-05 Bluetooth Transcever Module is a popular choice for Arduino and Raspberry Pi projects however, it can be a touch fickle when it comes to connecting especially in the more recent iterations of Rasbperry Pi OS.

Add the serial port profile to the pi

To do this you need to edit the dbus-org.bluez.service file. (Use nano instead of vim if you haven't used vim before.)

sudo vim /etc/systemd/system/dbus-org.bluez.service

In the [service] section you need to add the compatability flag (-C)at the end of the ExecStart line and then add ExecStartPost=/usr/bin/sdptool add SP below it:

ExecStart=/usr/libexec/bluetooth/bluetoothd -C
ExecStartPost=/usr/bin/sdptool add SP

Restart the services:

sudo systemctl daemon-reload
sudo systemctl restart dbus-org.bluez.service

Pair and trust your device

The simplest way to do this is to run bluetoothctl in interactive mode.

bluetoothctl

Assuming you didn't have any syntax errors in your file, this will change the prompt to [bluetooth]#. Run:

scan on

You'll be presented with a list of available bluetooth devices one of which should be: 00:00:00:00:00:00 HC-05 make a note of the address. If you can't see your device you might need to put it into pairing mode. Now run:

pair <00:00:00:00:00:00>

If your device has a PIN set you will be prompted to enter it. Once you've paired you need to run

trust <00:00:00:00:00:00>

to get out of bluetoothctl type exit

Test your connection

Run

sudo rfcomm connect hci0 <00:00:00:00:00:00> <channel>

This is telling the internal bluetooth module (hci0) to connect to your HC-05 module.  If you don't specify a channel it will use 1. This should give you something like

connected /dev/rfcomm0 to 00:00:00:00:00:00 on channel 1
Press CTRL-C for hangup

If your bluetooth device is sending data you can trivially check this by running cat /dev/rfcomm0 in a different terminal window.

NOTE: if you try to connect using bluetoothctl you will get Failed to connect: org.bluez.Error.NotAvailable.

Connect on boot

The neatest way to do this is to create a service.

sudo vim /etc/systemd/<connectbt>.service

Add the following:

[Unit]
Description=Automatic connection to a bluetooth device
After=bluetooth.target
Requires=bluetooth.target

[Service]
User=root
ExecStart=rfcomm connect hci0 <00:00:00:00:00:00>
Restart=always
RestartSec=20

[Install]
WantedBy=multi-user.target

Reducing the restart interval from the default 100ms gives time for the user to turn the bluetooth device on in case they forget. If you don't do this you will hit the default StartLimitBurst (5) and the service will terminate.

If you want to check for the device more frequently it would be prudent to set StartLimitIntervalSec and StartLimitBurst in the [Unit] section. Be careful to ensure that StartLimitBurst * RestartSec < StartLimitIntervalSec.

Troubleshooting your script

If your service fails you can find the error message by running

journalctl -e -u <connectbt>
  • -e drops you in at the end of the pager output
  • -u limits the logs to those from the specified unit
  • if you don't want the whole output you can also add -n <lines> to limit it to the last n lines
  • If you want to check whether the service is connecting properly on failure you can add -f to tail the log. CTRL-C to exit.

Resources:

Comments powered by Talkyard.