BLE communication between an Arduino Bluno and a Raspberry Pi - archetag/smart-water-quality-monitoring GitHub Wiki

Wiki: BLE communication between an Arduino Bluno and a Raspberry Pi

The measurements and date can be sent from the Arduino Bluno and be received by the Raspberry Pi 3 B+, through Bluetooth Low Energy. The first device plays the peripheral role, the second one plays the central role. This part indicates how to make these two devices communicate via BLE.

Table of contents

Material needed

  • 1 Computer with Linux OS
  • An Arduino IDE on your computer
  • 1 Arduino Bluno (DFRobot Bluno = Uno + BLE integrated module)
  • 1 USB-micro USB cable which ALLOWS data transmission
  • 1 Raspberry Pi 3B+ (or maybe another model with a BLE integrated/additional module), working on a Linux Kernel
  • 1 Micro-SD card for the Raspberry Pi
  • 1 Power supply for the Raspberry Pi (cable, battery, etc.)

This wiki assumes you have already read the Measurements with Arduino Bluno wiki section.

1. Configure the Arduino Bluno

Some settings need to be made on the Arduino Bluno, to make it act as a peripheral (equivalent to a server) during the BLE transmission.

  1. Open your Arduino IDE application.
  2. Open the WaterMonitor.ino file in WaterMonitor folder. Copy and paste into the main loop the bluetooth sending debugging code among those proposed at the end of the WaterMonitor.ino file. Be sure to paste it inside the if(millis()-updateTime > XXXX) condition.
  3. Connect the Arduino Bluno Board with the USB-micro USB cable to your computer. On the IDE, select Arduino Uno in Tools > Board. The IDE may set automatically the port in Tools > Port, otherwise select the correct port. When connected, the red LED of the Arduino Bluno should be on (PWR).
  4. Click on the Verify button, and if successful on the Upload button (icons just below File/Edit/Sketch in the upper left corner).
  5. Open the Serial Monitor (icon in the upper right corner), set the baud rate to 115200, select the "No line ending" option, enter "+++" in the command bar and click on send. A "You entered AT mode" message should appear.
  1. From now and for the next steps, select the "Both NL & CR" option. You are now able to change the main settings of the Arduino Bluno. All commands for AT mode are available at this link https://wiki.dfrobot.com/Bluno_SKU_DFR0267#Bluno_Basic_Demo. To know the MAC address of your device, since it is essential for BLE transmission, enter the command "AT+MAC=?" in the command bar to directly ask it to the Arduino. In my case, the MAC address is C8:DF:84:24:27:F6.
  1. Enter the following commands in the command bar to set up correctly the Arduino as a BLE peripheral:
  • AT+FSM=FSM_TRANS_USB_COM_BLE (to set a BLE transparent transmission)
  • AT+ROLE=ROLE_PERIPHERAL (to set the Arduino as a BLE peripheral device)
  • AT+MIN_INTERVAL=10 (to change the minimum connection interval, here adapted for PC and Android)
  • AT+MAX_INTERVAL=10 (to change the maximum connection interval, here adapted for PC and Android)
  • AT+UART=115200 (to set the baud rate of UART, 115200 is recommended for BLE transmissions)
  • AT+SETTING=DEFPERIPHERAL (to set the last settings)

It is preferable to check if each order has been correctly processed with the commands (to enter separately): AT+FSM=?, AT+ROLE=?, AT+MIN_INTERVAL=?, AT+MAX_INTERVAL=?, AT+UART=?, AT+SETTING=?.

  1. Exit AT mode with the "AT+EXIT" command.
  2. Check if your Arduino Bluno is recognized by other devices. By enabling the Bluetooth on a phone or a computer, the Arduino Bluno should be detected with its MAC address or its identifier Bluno. The Arduino is now ready to send data through BLE.

2. Configure the Raspberry Pi

The Raspberry Pi must be configurated to allow BLE connections. Normally, like computers, it automatically acts as a central device. All the following commands and steps are entered on the Raspberry terminal.

Basic installation checks

First, check if the Raspberry BLE module is enabled with:

$ sudo hciconfig

and identify if the UART Bus is in the UP RUNNING:

If for some reason it is DOWN, enable it with (with hci1 as UART bus) :

sudo hciconfig hci1 up

Install BlueZ library

The adafruit website already offers a very clear tutorial on how to install the Linux library BlueZ at this link: https://learn.adafruit.com/install-bluez-on-the-raspberry-pi/installation. To summarize it :

  1. Download source
  2. Install dependencies
$ sudo apt-get update
$ sudo apt-get install -y libusb-dev libdbus-1-dev libglib2.0-devlibudev-dev libical-dev libreadline-dev
  1. Compile and install BlueZ
  2. Set up BlueZ service
$ sudo systemctl start bluetooth
$ systemctl status bluetooth
$ sudo systemctl stop bluetooth
  1. Enable Bluetooth Low Energy features
  • Edit /lib/systemd/system/bluetooth.service to enable experimental features
  • Restart BlueZ service
  1. If the Raspberry is correctly configured, the command systemctl status bluetooth should give:

In addition, installing blueman application may help for quick checks in graphical mode.

Install bluepy library

To install and check the bluepy library on the Raspberry Pi:

  1. Install dependencies :
$ sudo apt-get install python-pip libglib2.0-dev        //python2.7
 or 
$ sudo apt-get install python-pip3 libglib2.0-dev       //python3.6
  1. Install bluepy from the package :
$ sudo pip install bluepy                               //python2.7
or 
$ sudo pip3 install bluepy                              //python3.6

MAC address and the first use of bluepy

Another way to detect the MAC address of the Arduino Bluno (powered up), from the Raspberry Pi this time, is to use hcitool command:

$ sudo hcitool lescan

Once the MAC address is known, switch to "/usr/local/lib/python2.7/dist-packages/bluepy" or "/usr/local/lib/python3.6/dist-packages/bluepy" (or at least the directory where your bluepy python library is stored), and enter :

$ python btle.py <MAC-address>                          //python2.7
or 
$ python3 btle.py <MAC-address>                         //python3.6

The output should be :

The above picture is the BLE architecture of the Arduino Bluno! The Raspberry Pi is now ready for the BLE transmission, and we have all the information to make the two devices communicate.

Note: If the BLE of the Raspberry Pi is not working, verify the Bluetooth service has correctly started (systemctl status bluetooth), or is not interrupted. Otherwise, restarting the service may help (sudo systemctl restart bluetooth / sudo systemctl stop bluetooth and sudo systemctl start bluetooth).

3. Transmit data through BLE

At this step, the Arduino Bluno and the Raspberry Pi should know which role to play during the BLE transmission.

Introduction of the devices

As a safety measure, the Raspberry Pi may need to be introduced to the Arduin Bluno with the following commands (it can also be done with graphic tools like blueman) :

$ bluetoothctl
$ power on
$ agent on
$ default-agent
$ scan on
$ trust <DEVICE-MAC-ADDRESS>
$ pair <DEVICE-MAC-ADDRESS>
$ connect <DEVICE-MAC-ADDRESS>
$ exit

Here, the Arduino Bluno can communicate with the Raspberry Pi without these steps. This is certainly due to one of the modes set to the Arduino during the AT MODE configuration (AT+FSM). In other modes, pairing to the Arduino Bluno requires the password: 000000.

How BLE communication works

The Arduino Bluno BLE architecture previously obtained in MAC address and the first use of bluepy section corresponds to its GATT profile (Generic Attribute Profile). For peripheral devices like Arduino Bluno, it establishes common operations and a framework for the data transported and stored by the Attribute Protocol (AT) (communication diagram from http://tvaira.free.fr/ website):

A peripheral can propose several services. Each service has a UUID (name identifier) and is composed of one or more characteristics. Each characteristic is defined with a UUID (name), a handle (channel of communication), permissions (WRITE, READ, NOTIFY, NO ANSWER, ...), and a value. Finally, to interact through BLE:

  • the central device (Raspberry Pi) can READ/WRITE a characteristic of the peripheral device,
  • the peripheral device (Arduino Buno) can NOTIFY/RESPOND through a characteristic to the central device.

An analysis of the Arduino Bluno GATT indicates 4 different services :

  • Generic Access (GAP protocol)
  • Generic Attributes (GATT profile)
  • Device Information
  • dfb0

The dfb0 service is dedicated to data transmission since it is only one who has characteristics with NOTIFY permission. More precisely, DF Robots website explains the dfb1 characteristic is used for serial communication between the devices, and that dfb2 characteristic serves for configuring the Bluno AT MODE.

Communication between the devices

  1. Connect your Arduino Bluno to a power supply. The red led (PWR) should be on, but not the green LINK or PAIR led (it means the device is already connected or is communicating through BLE). If it is the case, reconnect manually your Arduino.
  2. Copy-paste the following code in a file of your Raspberry Pi.
  3. In connectToBLE() method, indicate the correct MAC address of your Arduino in Peripheral("MAC-ADDRESS", "public"), the correct service in bluno.getServiceByUUID("service-name"), and the correct characteristic to use in svc.getCharacteristics("characteristic-name")[0].
  4. Run the code. The green "LINK" led should be on, and the console should print data sent by the Arduino Bluno.
import binascii
import signal
import sys
from bluepy.btle import Peripheral, UUID, DefaultDelegate
 

class SensorsDelegate(DefaultDelegate):
    """
    Deleguate object from bluepy library to manage notifications from the Arduino Bluno through BLE.
    """
    def __init__(self):
        DefaultDelegate.__init__(self)
        # ... initialise here

    def handleNotification(self, cHandle, data):
        """
        Sorts data transmitted by Arduino Bluno through BLE.
        """
        if (cHandle==37):
            print(data)
            
def signal_handler(sig, frame):
    print('  You pressed Ctrl+C! Bluno disconnected')
    bluno.disconnect()
    sys.exit(0)

def connectToBLE():
    # connection to the device
    bluno = Peripheral("C8:DF:84:24:27:F6", "public")
    bluno.setDelegate(SensorsDelegate())
    
    svc = bluno.getServiceByUUID("dfb0")
    ch = svc.getCharacteristics("dfb1")[0]
    return (bluno, ch)
    

if __name__=='__main__':
    
    signal.signal(signal.SIGINT, signal_handler)
    print("Connecting to device...")
    bluno, ch = connectToBLE()
    print("\n Device connected")
    try:
        while True:
            #ch.write(str.encode("ok"))
            if bluno.waitForNotifications(5.0): # calls handleNotification()
                 continue
            print("Waiting...")
    finally:
        bluno.disconnect()
  1. Use Ctrl+C to properly disconnect the Arduino when finished. The green "LINK" led should then be off. Otherwise, disconnect the Arduino from its power supply. It is not possible to connect again via BLE if the device is not disconnected.
  2. To directly get the data from the sensors, upload the WaterMonitor.ino file from the WaterMonitor folder with the bluetooth sending debugging part (among the codes proposed at the end of the script) to the Arduino Bluno. On the Raspberry, replace the previous python code with the ble_interface.py script from the RaspberryBleRos folder. Replace the data as explained above and run the code.

4. Precautions

  • If the BLE of the Raspberry Pi is not working, verify the Bluetooth service has correctly started (systemctl status bluetooth), or is not interrupted. Otherwise, restarting the service may help (sudo systemctl restart bluetooth / sudo systemctl stop bluetooth and sudo systemctl start bluetooth).
  • If your Arduino is not correctly detected during BLE communication, check if the green LINK or PAIR led is on (it means the device is already connected or is communicating through BLE). If it is the case, reconnect manually your Arduino. It may happen when the device has not been properly disconnected.