Bluetooth Low Energy on Adafruit Arduino

Lately as I develop and realize few IOT use-cases , I have concluded that BLE ( Bluetooth Low Energy) , also known as Bluetooth smart , is a very good choice as it runs for longer periods of time with smaller power sources.

What is BLE ?

This is the version 4.0+ of Bluetooth which is aimed as building the communication network for IOT ( Internet of things ) . Like classic Bluetooth it utilizes the 2.4 Ghz band and performs in dual-mode. Also both the models use Gaussian frequency shift modulation for data transmission.

How is BLE different from classic Bluetooth ?

Power and Life : BLE provided better bit rate with lesser power consumption( 0.01W to 0.1W) than classic bluetooth technology ( 1 W). Channel : While Classic Bluetooth uses 79 1-MHz channels , BLE has 40 2-MHz channels

How can one make use of BLE in IOT ?

If you have a usecase that needs implementation than high changes are it needs 3 basic components: 1. End devices such as machines , automated doors , surveillance systems , metering systems etc This is where BLE can be used to transmit realtime data quickly to central controller

  1. Central control hub to control the end points and communicate to server This has to be a bridge between BLE devices and internet to put all the gathered information on the cloud for analysis and logic processing.
  2. User provisioning system or Graphical interface to who stats , status , control options etc . This is also a critical component as the user needs to have a way of controlling the operation without physically going to the machines . Although the system can very much work without given a pre-programmed operation .

*References *

you can learn more about bluetooth form these links


Simple Adafruit Bluefruit Bluetooth LE UART android app

This is the first and the most basic example of using BLE.

Code

Key concepts for BLE programming

GATT ( Generic Attribute Profile) : The bluetooth Special Interest Group ( SIG ) defines many profile for low energy devices.  GATT is also an profile for sending and receiving short data in low energy devices .

ATT (Attribute Protocol ) : Each attribute is uniquely identified by a Universally Unique Identifier (UUID), which is a standardized 128-bit format for a string ID. The attributes transported by ATT are formatted as characteristics and services

BLE activity class

While defining the Bluetooth LE UART acttivity class we must extend the BluetoothGattCallback parent class and implement the BluetoothAdapter.LeScanCallback interface .

Then define the public data values for the device such as UUID of the UART , TX and RX. Also the UUID for the UART BTLE client characteristic which is necessary for notifications .UUIDs for the Device Information service and associated characeristics such as Manufacture , Model , hardware , software .

set the adapter to BluetoothAdapter.getDefaultAdapter()

we can define some callbacks in an interface , This enables BLE UART client to be notified of UART actions .

 public interface Callback {
 public void onConnected(BluetoothLeUart uart);
 public void onConnectFailed(BluetoothLeUart uart);
 public void onDisconnected(BluetoothLeUart uart);
 public void onReceive(BluetoothLeUart uart, BluetoothGattCharacteristic rx);
 public void onDeviceFound(BluetoothDevice device);
 public void onDeviceInfoAvailable();
 }

For scanning the available devices , call adapter.startLeScan(this) . This will Start scanning for BLE UART devices. Registered callback’s onDeviceFound method will be called when devices are found during scanning. Similarly call adapter.stopLeScan(this) to stop the device scan .

we may also define Handlers for BluetoothGatt and LeScan events such as ,

1. onLeScan

Stop if the device doesn’t have the UART service

        if (!parseUUIDs(scanRecord).contains(UART_UUID)) {
            return;
        }

Notify registered callbacks of found device.

        notifyOnDeviceFound(device);

connect to device

	gatt = device.connectGatt(context, true, this);

2. onConnectionStateChange

super.onConnectionStateChange(gatt, status, newState);

we can check the state through BluetoothGatt.STATE_CONNECTED and status of connection through BluetoothGatt.GATT_SUCCESS.
Further more we can check if the service was found on the device through gatt.discoverServices()
If any of the above conndition were not checked we can call connectFailure() which signifies that connection was a failure and reset cinnection state through

        rx = null;
        tx = null;
        notifyOnConnectFailed(this);

Simillarlily if state was BluetoothGatt.STATE_DISCONNECTED then notify callbacks of disconnection.
3. onServicesDiscovered
super.onServicesDiscovered(gatt, status);

notify connection failure if service discivery failed

status == BluetoothGatt.GATT_FAILURE

Save reference to each UART characteristic.

        tx = gatt.getService(UART_UUID).getCharacteristic(TX_UUID);
        rx = gatt.getService(UART_UUID).getCharacteristic(RX_UUID);

Save reference to each DIS characteristic.

        disManuf = gatt.getService(DIS_UUID).getCharacteristic(DIS_MANUF_UUID);
        disModel = gatt.getService(DIS_UUID).getCharacteristic(DIS_MODEL_UUID);
        disHWRev = gatt.getService(DIS_UUID).getCharacteristic(DIS_HWREV_UUID);
        disSWRev = gatt.getService(DIS_UUID).getCharacteristic(DIS_SWREV_UUID);

Add device information characteristics to the read queue . These need to be queued because we have to wait for the response to the first read request before a second one can be processed

        readQueue.offer(disManuf);
        readQueue.offer(disModel);
        readQueue.offer(disHWRev);
        readQueue.offer(disSWRev);

Request a dummy read to get the device information queue going

        gatt.readCharacteristic(disManuf);

Setup notifications on RX characteristic changes (i.e. data received).

First call setCharacteristicNotification to enable notification

gatt.setCharacteristicNotification(rx, true)

Stop if the characteristic notification setup failed.

Next update the RX characteristic’s client descriptor to enable notifications

BluetoothGattDescriptor desc = rx.getDescriptor(CLIENT_UUID)
desc.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(desc)

Stop if the RX characteristic desc has no client descriptor ie null or if the client descriptor could not be written.

Notify of connection completion.

        notifyOnConnected(this);

3. onCharacteristicChanged

        super.onCharacteristicChanged(gatt, characteristic);
        notifyOnReceive(this, characteristic);

4. onCharacteristicRead

	super.onCharacteristicRead(gatt, characteristic, status);

Check if there is anything left in the queue

            BluetoothGattCharacteristic nextRequest = readQueue.poll();

if nextRequest is not null ie it has items more Send a read request for the next item in the queue

                gatt.readCharacteristic(nextRequest);

else We’ve reached the end of the queue so set the flags and make the callback

                disAvailable = true;
                notifyOnDeviceInfoAvailable();

5. onCharacteristicWrite

	super.onCharacteristicWrite(gatt, characteristic, status);

android manifest file

1. Declare the Bluetooth permission to perform connection and data transfer over bluetooth

<uses-permission android:name=”android.permission.BLUETOOTH”/>

2. To initiate device discovery or manipulate Bluetooth settings, you must also declare the BLUETOOTH_ADMIN permission.

<uses-permission android:name=”android.permission.BLUETOOTH_ADMIN”/>

3. To declare that your app is available to BLE-capable devices only.

<uses-feature android:name=”android.hardware.bluetooth_le” android:required=”true”/>

Layout

Android studio screenshots 

I have used Adafruit Bluefruit LE UART Friend – Bluetooth Low Energy (BLE) device . More details about this can be found here .

The circuit for a BLE Arduino is as follows :

This application has more modules than the previous simple read and write application . It can work in 4 modes namely

  1. Info
  2. UART
  3. Controller
  4. Beacon

The circuit arrangement is shown in following pictures :

The edited source code of the android application is on the github repo : https://github.com/DKAagri/BluefruitArduinoLE

screenshots of the Android application

The controller mode

ColorPickerActivity

We can connect a android phone in adb mode to android studio and monitor the realtime network , memory and other stats.

See the connection and communication entities form the android device monitor logcat

The code of this application is derived from

https://github.com/adafruit/Bluefruit_LE_Connect_Android

More information about Bluefruit LE the device can be obtained form

https://blog.adafruit.com/2014/11/19/new-products-bluefruit-le-friend-bluetooth-low-energy-ble-4-0-nrf51822-v1-0-bluefruit-le-sniffer-bluetooth-low-energy-ble-4-0-nrf51822-v1-0/