Connect an Arduino to a Rasberry Pi via an HC-05 Bluetooth Module
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/system/<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
.
Start your service:
sudo systemctl daemon-reload
sudo systemctl start <connectbt>.service
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:
- Getting the Pi to connect to the module: https://forums.raspberrypi.com/viewtopic.php?p=947185#p947185
- rfcomm: https://www.tutorialspoint.com/unix_commands/rfcomm.htm
- Managing Bluetooth Devices on Linux Using bluetoothctl: https://www.makeuseof.com/manage-bluetooth-linux-with-bluetoothctl/
- Serial Bluetooth Communication: https://pirobotblog.wordpress.com/2016/12/22/serial-bluetooth-communication/
- How to Use journalctl to read Linux System Logs: https://www.howtogeek.com/499623/how-to-use-journalctl-to-read-linux-system-logs/
- Systemd Service Options: https://www.freedesktop.org/software/systemd/man/systemd.service.html#Options
- Systemd Unit Options: https://www.freedesktop.org/software/systemd/man/systemd.unit.html#[Unit] Section Options