The Raspberry Pi is a popular platform because of its low cost and high integration. In addition to Wi-Fi and Ethernet, this board also has integrated Bluetooth which support BLE.
The Rapsberry Pi support for Bluetooth depends on specifically on which Raspberry Pi you have:
|Board||Bluetooth Chipset||Bluetooth Supported|
|Raspberry Pi 3 Model A+||Broadcom BCM43438||Bluetooth 4.1|
|Raspberry Pi 3 Model B||Broadcom BCM43438||Bluetooth 4.1|
|Raspberry Pi Model 3B+||Cypress CYW43455||Bluetooth 4.2|
|Raspberry Pi 4 Model B||Cypress CYW43455||Bluetooth 5.0|
Raspberry Pi supports Bluetooth Low Energy because they integrate a combo Wi-Fi + Bluetooth chipset. The exact chipset supported varies depending on the board being used. raspberry Pi 3A used BCM43438 chipset from Broadcom, while it moved to a CYW43455 chipset with support for 802.11ac and dual band (2.4GHz and 5GHz).
Each version of the Raspberry Pi uses Linux and so leverages the OpenSource BlueZ Bluetooth stack. This stack has been used for many years, and although it supports both Bluetooth Classic and BLE, its support for BLE is more recent and there are some limitations and sometimes bugs because it does not get as much testing. If you're thinking of deploying BlueZ, you should most definitively test it extensively in a real world application.
Bluetooth 5.0 support on the Raspberry Pi is limited to the mandatory features. The main one that is missing is the Long Range support, so if you were thinking of leveraging the Coded PHY for extra long range, you won't be able to. This feature is normally not found on combo Wi-Fi + Bluetooth chipsets.
Before we get into running the Raspberry Pi, we wanted to discuss a bit about performance. After all, no guide from us would be complete without it. Over the last few years, we've seen companies use the Raspberry Pi as a gateway system because of it's performance and cost. We've used it in a few projects as well.
The good news are that the Pi has pretty good chipsets from an RF performance and feature perspective, leveraging Broadcom and now Cypress. Some of devices have support for 5GHz Wi-Fi band reduces interference on the 2.4GHz band used by BLE. Given that the system is a single chip solution, there is also support for Coexistence to reduce interference The biggest issue the Raspberry Pi has a relatively small antenna. This antenna is surrounded somewhat by the GPIO connector pin connector. Both of these have some impact on performance, though the RPI foundation does not provide detailed antenna radiation information.
The antenna can't be changed on the raspberry Pi for a few reasons:
Ultimately, the Bluetooth LE range of the Raspberry Pi devices is decent but limited, and it won't approach what you can get with an external antenna and a more sophisticated system. If you're looking to control devices over any reasonable distances beyond a room or two, adding another radio or finding another solution would be best.
With all this said, it can make a good solution for indoor control of devices. Now let's start using the Raspberry Pi to control some devices.
We'll be using a Raspberry Pi 4 which was recently released, but the information will be useful for other Pi boards. To follow along you will need:
If you already have a RPi configured, you can skip to Installing BlueZ Bluetooth Stack on the Raspberry Pi
Raspberry Pi runs a custom distribution of Linux. We will be using Raspbian. Download the image file that will be programmed to the SD Card:
As of the writing of this guide, the latest release is Raspbian Buster which was released in July 2019.
We recommend using the Torrent approach to download as it is significantly faster. Once downloaded, extract the zip to a folder.
Creating the SD card with Raspbian depends on your platform. For Windows, the easiest approach is as follows:
After this, click on Write to begin. The write process will begin. How long this takes depends on the SD card and reader performance so we recommend to use good microSD cards with fast writes to avoid waiting too long.
For Linux, we recommend you follow the Installing operating system images on Linux instructions as they depend on a few factors.
Although there's a lot of ways to go about controlling the Raspberry Pi, including mouse and keyboard, we tend to use either Serial Port or SSH because the command line is fast.
To get a command prompt on a Raspberry Pi, a USB to UART converter cable needs to be connected to the board. You can readily buy any of these from Mouser, Digikey or many other sources. Here are a few recommendations
All these cables use 3.3V I/O which is the standard voltage of the Raspberry Pi. For these cables, you will need to cut off the ends and connect them properly. In this case, we use the FTDI TTL-232R-3V3-WE cable.
The diagram above shows the 3 pins of the TTL-232R-3V3-WE that must be connected. The colors Black, Yellow and Orange are the colors of the cable wires. You cannot use the 6 pin connector that's already soldered to some of the cables because the pinout is different. Instead, you will need to cut them and solder some female jumper wires as we show below:
The Raspberry Pi by default has the serial console output disabled. To enable it:
This will allow you to use serial immediately without having to deal with SSH, disconnections, etc. On the other hand, if you want to use SSH, follow the steps in the next section.
Create a file called SSH in the boot partition. This file should be called "SSH" without the quotes and no extension. On windows, simply Right Click inside the Boot drive folder, select New and then Text Document, renaming it to SSH. When Windows shows a warning for the extension, accept with Yes.
Now that the SD card is ready, make sure to eject it (Windows) or unmount it (Linux/Mac) properly, or else it may not sync.
Insert the SD card into the Raspberry Pi and insert the 5V power supply and an Ethernet cable. The board LEDs should light up.
If you're using Serial to connect, the Raspberry Pi interface will come up and you can login using the username and password above. If you don't see any prompt, make sure the pin connections are correct and if needed reverse TX and RX wires.
For SSH, you will need to know the IP address of the Raspberry Pi. Finding it can be a bit of a challenge. One method we use is to use NMAP and scan the network quickly for devices. The Raspberry Pi will show itself and its IP address. You can also login to your router interface and find the MAC address assignments (the RPI will be the last device added).
You will need to use a program such as PuTTY to connect over serial or SSH to the unit. Download PuTTY from the following link:
The link above takes you to the direct 64-bit download. There's no need to install PuTTY. Open PuTTY, and either
To login with the defaults, use the username "pi" and password "raspberry"
Before we start playing around with BLE on the Raspberry Pi, we need to take care of a few things. first, let's use the Raspbian configuration utility to expand the file system so we have enough space:
Go to the Advanced Options menu and select Expand Filesystem. Go back and select Finish to save. Afterwards, reboot the raspberry Pi to ensure the configuration is completed:
You will need to re-connect if you are using SSH. The quickest way to do this is right click on PuTTY interface and select "Restart Session".
Now that our Raspberry Pi is ready, it's time to get BlueZ on it. as we mentioned before, BlueZ is the Open Source Bluetooth stack. The Raspberry Pi Foundation has already taken care of doing the low level configuration for the Wi-Fi / Bluetooth chipset. If this were a custom hardware platform (as we've worked with in the past), you would need to properly configure everything.
Wi-Fi and Bluetooth Chipsets (along with the combo variants) have firmware in ROM. The ROM firmware needs to be patched with updates and fixes. These patches and updates get loaded when the Bluetooth/Wi-Fi drivers are loaded and the RPI foundation has already taken care of it. We mention it because in some cases it would be important to update it. We won't need to do anything in this case as the defaults are sufficient.
Raspbian already comes with Bluetooth packages that can be downloaded, but we will be installing BlueZ ourselves. it's important you can install and update to the latest version, and potentially customize the build if custom features are needed. To do this, we need to download the BlueZ distribution and install dependencies. Download BlueZ source code as shown below. note that we are using BlueZ 5.50 which is currently the latest version.
cd ~ wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.50.tar.xz tar xvf bluez-5.50.tar.xz
The commands above download the BlueZ source and extract it, and in this case we will use BlueZ 5.50. We will be compiling BlueZ on the Raspberry Pi itself, because it is powerful enough to do so and because setting up a cross-compile system is more work and unnecessary. To compile on the RPI we need to install dependencies as follows:
sudo apt-get update sudo apt-get install -y libusb-dev libreadline-dev libglib2.0-dev libudev-dev libdbus-1-dev libical-dev
With all the dependencies installed, we will configure, make and install BlueZ:
cd bluez-5.50 ./configure --enable-library
Configure is a utility that verifies all the build dependencies are present and creates anything that is needed for the build. If there are any specific errors, check the messages from configure to see if any dependency is missing. Since we already installed everything, there should not be an issue.
Now, compile Bluez by executing make:
This build will take some time, but using 4 cores it will speed it up (RPI may get hot during that time).
Finally, we need to install it in the system. the following command will make it so that calling BlueZ utilities will be the version we compiled, not any older version that was already present:
sudo make install
Now that BlueZ is installed, let's confirm the version is correct:
[email protected]:~/bluez-5.50 $ btmon -v 5.50
Which confirms the version installed is the one we compiled.
It will be useful for you to know about basic commands and how BlueZ works. First of all, BlueZ contains a collection of utilities which we will use to connect and control devices. Here's a list of the most common utilities:
|hciconfig||Configures the HCI interface to the radio|
|hcitool||HCI Swiss Knife|
|gatttool||Connect to devices and control GATT|
[email protected]:~/bluez-5.50/tools $ hciconfig hci0: Type: Primary Bus: UART BD Address: B8:27:EB:AF:2C:B0 ACL MTU: 1021:8 SCO MTU: 64:1 UP RUNNING RX bytes:766 acl:0 sco:0 events:49 errors:0 TX bytes:2504 acl:0 sco:0 commands:49 errors:0
The Bluetooth capability is provided by from the BT adapter by means of an interface, and the hciconfig utility is now telling us that our interface is hci0. We will be using that interface.
To cycle the interface, which may be sometimes needed, we can take the interface down, then up.
[email protected]:~/bluez-5.50/tools $ sudo hciconfig hci0 down
[email protected]:~/bluez-5.50/tools $ sudo hciconfig hci0 up
You may need to use the reset above if the interface isn't behaving properly
In order to connect to BLE devices, we need to scan for the, and one way to do so is using the hcitool utility:
[email protected]:~/bluez-5.50/tools $ sudo hcitool -i hci0 lescan LE Scan ... 4F:2A:A8:AD:7E:0B (unknown) 4F:2A:A8:AD:7E:0B (unknown) DB:F8:F9:65:59:15 SCLE-01 DB:F8:F9:65:59:15 (unknown) 78:5D:71:CE:AF:E0 (unknown) 7D:FC:BE:D1:39:F6 FitBit 7D:FC:BE:D1:39:F6 (unknown) F5:ED:4B:A5:08:72 (unknown) F5:ED:4B:A5:08:72 (unknown) DF:F7:7B:74:4D:76 (unknown) E8:3D:EF:7A:30:FD SCLE-01 E8:3D:EF:7A:30:FD (unknown)
Above we called the hcitool with hci0 as the scan, and requested an LE Scan. This looks for all nearby devices and provides the MAC address.
Now that we have addresses of BLE devices, let's connect to them. For this we will use the gatttool utility since we will manipulate the GATT of a BLE device too. hcitool is basically a swiss knife for all HCI commands, both Classic Bluetooth and BLE, but it will not by itself manipulate the GATT tool.
gatttool can operate in two modes: interactive and non interactive. In interactive mode, the console provides an interface that enables you to issue commands and interact with the device. You will need to quit to return to the terminal.
sudo gatttool -i hci0 -b DB:F8:F9:65:59:15 -I -t random
The code above is standard, but it's important to note the use of the -t parameter which specifies whether the address used by the device is random or public. Public addresses are those that use assigned IEEE MAC addresses. random are addresses where the MAC is assigned randomly, as is in most cases in BLE devices.
One of the most important tasks is to read and write to characteristics. Using the interactive gatttool
[DB:F8:F9:65:59:15][LE]> char-read-uuid f000aa11-0451-4000-b000-000000000000 handle: 0x0030 value: 00 00 00
[DB:F8:F9:65:59:15][LE]> char-write-cmd 34 07 [DB:F8:F9:65:59:15][LE]> char-read-hnd 30 handle: 0x0030 value: 00 f0 02
Getting notifications from BLE devices is another mechanism for getting data from BLE devices in a low power way. A device can send a notification when it has new information to send, such as new data or an alert.
To enable notifications, we need to write to the CCCD (Client Configuration characteristic descriptor) with the right flags
[DB:F8:F9:65:59:15][LE]> char-write-cmd 34 07
At the beginning of this article we mentioned some of the performance issues the Raspberry Pi has, and you may have seen that the range can be somewhat limited, depending on the device being used. That's not everything to consider. major limitations of the Raspberry Pi is its limited temperature range. The latest Raspberry Pi 4 has a temperature range of 0°C - 50°C, which limits the Raspberry Pi to indoor deployments only. We have seen some more success using custom heatsinks and even fans to improve this, but you would need to test it for any reasonable assurance of deployment.
If you are looking to use the Raspberry Pi in any kind of deployment, look to do the following to improve your results: