Connect Pi devices and a smartphone with Bluetooth

Small Talk

© Lead Image © Andrey Kiselev,

© Lead Image © Andrey Kiselev,

Article from Issue 264/2022

We use a Raspberry Pi, a Pi Pico, and a smartphone to communicate over Bluetooth.

Because the Raspberry Pi comes with both WiFi and Bluetooth, most programs choose to rely on WiFi, with Bluetooth being more of a wallflower. However, the Pi Pico mixes things up and makes Bluetooth a desirable option.

Bluetooth should be a familiar technology by way of your smartphone, and this topic has been investigated for the Raspberry Pi in a previous article [1], so I will be sticking to the bare minimum in terms of the basic technology in this article. The focus here is on various scenarios in which the Raspberry Pi, Pi Pico, and smartphones use Bluetooth to communicate. The Pico stands in for almost any microcontroller, as long as it supports serial communication.

Basic Technology

The two basic prerequisites for Bluetooth communication between partners is pairing and trust between the parties. After you establish both once, the devices usually remember the trust relationship. After pairing, each of the two partners can establish a connection. The initiator is referred to as the host and the other partner as the device. However, each component can assume either role.

The default user pi on the Raspberry Pi should be a member of the bluetooth and dialout groups; you can check their status with the id command. If you are missing membership in one or both groups, make the change with the command

$ sudo usermod -a -G bluetooth,dialout pi

and then log off and log on again.

The counterpart must be visible for pairing to succeed. On smartphones, the required settings are in the Bluetooth section of the preferences. On the Raspberry Pi, use the bluetoothctl command (Figure 1), which starts its own small shell with a limited command set. The help command calls up an overview. Pressing Tab completes commands and Bluetooth MAC addresses, which saves a great deal of typing.

Figure 1: Pairing and trust with bluetoothctl. After power on and scanning, you will see many different devices and their MAC addresses depending on the environment.

System Requirements

In addition to individual pairing, the Raspberry Pi must meet a few system requirements. Communication between the smartphone, Pi Pico, and Raspberry Pi relies on the serial port protocol (SPP), which is based on Radio frequency communication (RFCOMM) over the Logical Link Control and Adaptation Protocol (L2CAP). This protocol stack is part of legacy Bluetooth. Other profiles such as the File Transfer Protocol (FTP) or Object Exchange (OBEX) push protocol also rely on RFCOMM. OBEX is used by smartphones for direct file exchange.

For RFCOMM to be available on the Raspberry Pi, you need to start the Bluetooth daemon with the -C compatibility option. To do this, copy the service definition from /lib/systemd/system/bluetooth.service to /etc/systemd/system. There, you replace the ExecStart statement with:

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

The second line adds SPP to the service catalog of available protocols. Now, enter

$ sudo systemctl daemon-reload
$ sudo systemctl restart bluetooth.service

to restart the daemon.

Blue Keyboard

The first sample application is a media player on a TV located in the living room. If it fails to work correctly, just restart the server process. Independently, you might also need to check a couple of important parameters. Instead of using an editor and SSH, you can use a smartphone or tablet. Android devices run the Serial Bluetooth Terminal [2] app for this purpose; a similar app is available for iOS, as well.

You can access the paired devices from the app's menu; clicking on a device starts the connection setup. For this to work, however, the Raspberry Pi must wait for a connection. You can initiate this with the command:

sudo rfcomm listen hci0 &

The ampersand (&) at the end bundles the command off into the background and frees up the console for input again.

Figure 2 shows the principle of communication after the connection is established. The tablet (right) sends commands (in blue), and the Raspberry Pi uses cat to read them from /dev/rfcomm0 (left). This also works the other way around: The Rasp Pi uses echo to write to /dev/rfcomm0, and the output appears on the tablet (green). Once the connection is established, it doesn't matter who set it up: The data flow is always bidirectional. Because of an error in the app, the commands from the tablet are echoed in the response from the Raspberry Pi.

Figure 2: Communication flow between the Raspberry Pi and an Android tablet over Bluetooth.

To make the steps you performed manually on the Raspberry Pi shown in Figure 2 automatic, set up a systemd service with the definition from Listing 1. The watch argument in line 7 works like listen. After establishing the connection, RFCOMM starts the /usr/local/sbin/ script. With a connection failure, watch ensures that RFCOMM returns to listen mode.

Listing 1

Service Definition

01 [Unit]
02 Description=BT-Control service
03 After=bluetooth.service
04 Requires=bluetooth.service
06 [Service]
07 ExecStart=/usr/bin/rfcomm watch rfcomm0 1 /usr/local/sbin/
09 [Install] 10:

You can see the corresponding control program in Listing 2. The example is a simple shell script, but any other programming language would be just as good. The script reads continuously from the RFCOMM interface (line 18) and processes the predefined commands in the process_request() function starting in line 3.

Listing 2

Control Program

01 #!/bin/bash
03 process_request() {
04   case "$1" in
05     "hostname") hostname -f >&3 ;;
06     "mem")      free -h >&3 ;;
07     "disk")     df -h   >&3 ;;
08     *)          echo "Unknown command" >&3 ;;
09     esac
10 }
12 # --- Main program -----------------------------
14 # Open device for reading and writing
15 exec 3<>/dev/rfcomm0
17 while true; do
18   if read -u 3 request; then
19     process_request "$request"
20   else
21     break
22   fi
23 done;
25 # Close file descriptor
26 exec 3>&-

The Android app makes the control task very simple by letting you assign commands directly to buttons (Figure 3). The number of lines is defined in the settings. A long press on a button lets you enter edit mode, and you can change the title, command, and format. However, individual buttons cannot be hidden, nor can the font size be changed.

Figure 3: The Android app supports quick entry of commands with predefined buttons.

Quite a few apps in the Google Play store are based on the same RFCOMM technology. For example, of special interest is the Bluetooth Control Panel [3], which dynamically creates an interface on the basis of data sent to it by the Raspberry Pi or a microcontroller.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Web Serial API

    Upgrade your computer with LEDs, buttons, or sensors to control a microcontroller board over USB from your web browser.

  • Bluetooth LE

    Bluetooth Low Energy is ideal for networking battery-powered sensors. We show you how to use it on the Raspberry Pi.

  • GPRS in Linux

    Permanent mobile Internet access might sound like a nightmare for some, but for others it is a dream come true. All you need is Linux and a fairly recent mobile phone.

  • Bluetooth Mobile Phones

    It is becoming increasingly common for new generation mobile phones to have an integrated Bluetooth interface. This article explores how to access your Bluetooth phone using Linux.

  • Bluetooth Security

    Is your address book open to the world? Is your mobile phone calling Russia? Many users don’t know how easy it is for an attacker to target Bluetooth.

comments powered by Disqus
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters

Support Our Work

Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.

Learn More