Bluetooth Low Energy for the Raspberry Pi
Wireless Saver
Bluetooth Low Energy is ideal for networking battery-powered sensors. We show you how to use it on the Raspberry Pi.
Bluetooth LE, or BLE for short, comes with a whole new world of terms on top of the new technology. Before getting started with some practical examples, I first need to discuss the theoretical background. Without all of this BLE speak, you can't evaluate the many application examples available on the web and adapt them to your needs.
Bluetooth is a short-range technology for use between two devices [1]. Before a connection is established, a system can be either a peripheral device or a central device. Powerful devices such as PCs, tablets, and laptops can assume both roles, while less powerful devices are limited to the peripheral role.
Each peripheral sends advertisements at regular intervals, such as "I am sensor ABC and provide heart rate data." Alternatively, the message could be: "I am sensor XYZ and would like to know the current time." Heart rate and current time are services. Both of them are standardized, but manufacturers are free to use their own proprietary services. More about that later.
Figure 1 from the Bluetooth Special Interest Group (SIG) [2] BLE Primer shows that devices use multiple predefined channels of the spectrum for advertisements. (Bluetooth SIG is a special interest group of more than 30,000 companies for the development and distribution of Bluetooth technology.) If you are interested in the technical details of BLE, you will definitely want to read this document.
Opening a Connection
Central devices scan their environments for advertisements. If a central device finds something interesting, it opens a connection to the peripheral device. As soon as the connection is established, the peripheral stops sending advertising messages. The whole process is known as the Generic Access Profile (GAP), which I'll cover here briefly.
Once connected, it is all about data exchange between the two devices. The standard for this is the Generic Attribute Profile (GATT), which regulates which bytes one device sends to the other device via the wireless link. Even though the connection is always established from the central device to the peripheral, this does not mean that data only flows in one direction. A bidirectional data flow is also possible, for example, using the universal asynchronous receiver/transmitter (UART) service. BLE defines the terms server and client for this purpose. The client has read or write access to the server, which in turn can send data (with or without a response) to the client. In this case, the server has the definition of the resources.
The heart rate sensor from the previous example would be an example of a server. The peripheral device that asks for the current time, on the other hand, would have a client role after opening the connection. For its part, the client can only hope that a central unit will adopt the server role.
Profiles and More
The service, a central concept in the BLE world, defines the data and behavior. Each service has a universally unique ID (UUID). The services standardized by the Bluetooth SIG have 16-bit UUIDs, while private services use 128-bit UUIDs. An official document [3] defines all standardized UUIDs. For example, the Heart Rate Service has the UUID 0x180D.
Using these UUIDs, a central instance can filter for just the sensors it is interested in when scanning for advertisements. An app that wants to visualize a heartbeat can specifically connect to the appropriate sensors. If everyone adheres to the standard, this even works across manufacturers.
A logical grouping of several services is known as a profile. The Heart Rate Profile, for example, also contains the Device Information Service (Figure 2). The corresponding standard also defines two roles: Collector (client) and Sensor (server). In addition, it specifies other more or less important details (e.g., that the sensor's device name can optionally be overwritten).
Within a service, there are several logical attributes or functions known as characteristics in BLE speak. The Heart Rate Service contains the mandatory Heart Rate Measurement characteristic and, optionally, the Body Sensor Location characteristic, among others. Each characteristic in turn includes named fields with the actual data.
Scan Me!
After all of this theory, it's time for some simple examples. On the Raspberry Pi, you only need Python for this. The Bleak library provides an abstraction layer that greatly simplifies the application. Bleak stands for BLE Platform Agnostic Klient (ouch), a nod to the fact that the package runs on Linux, macOS, and Windows. So for program development, you don't necessarily need a Rasp Pi, but you definitely need Python v3.7 or later.
Simply install Bleak using:
pip3 install bleak
You will also want to download the source code (including examples) from Bleak's GitHub repo [4]. You'll find the examples very useful as templates for your applications.
CircuitPython via Blinka is an alternative to Bleak. Installed on the Rasp Pi along with the appropriate BLE libraries (Listing 1), this combination facilitates communication with custom microcontrollers that also run CircuitPython. While it will probably not cause you problems in many scenarios, Blinka does pose some limitations: The Raspberry Pi can only adopt the central role with Blinka. The source code for the BLE libraries for CircuitPython can also be found on GitHub, below the Adafruit account. Again, there are many useful examples.
Listing 1
Blinka with BLE
The program in Listing 2 implements a very simple BLE scanner. The infinite loop in lines 7 to 11 scans for advertisements every 10 seconds. For each match, the program outputs the Bluetooth MAC address and name. However, the Bluetooth name does not have to be available. If you are interested in the actual byte sequence of the message, then add repr(adv)
to the print
statement.
Listing 2
Simple BLE Scanner
The Bleak installer installs the bleak-lescan
program in /usr/local/bin/
; it has the same functionality as our simple BLE scanner. However, the logic is hidden in a module, so it is not as revealing as Listing 2.
Figure 3 shows the output from the simple BLE scanner. Besides my open source smartwatch (Bangle.js
) and smartphone (HV10BB
), several devices from the neighboring apartment are also advertising.
Speaking of smartphones, there are several apps in the Apple and Google stores to help you get started with BLE and testing. These include the nRF Connect for Mobile app by Nordic Semiconductor (Figure 4), which is the leading manufacturer in Bluetooth chips. Nordic Semiconductor offers many useful documents, tools, and software on the topic on its website [5].
Another useful app is Bluefruit LE Connect by Adafruit. In addition to hardware, Adafruit offers a very large collection of tutorials on all sorts of hardware-related IT topics. Bluefruit LE Connect and its practical application are very well documented.
Special Bluetooth microcontrollers by Adafruit, such as the Feather nRF52840 Express, are a great choice for interaction with the Bluefruit app. The app receives data and can also control the MCU, provided a suitable program is running there.
Buy this article as PDF
(incl. VAT)