Bluetooth Smart, or Bluetooth Low Energy (BLE), is a new type of technology mainly characterized by its low power consumption. This feature is highly convenient for devices that require constant data acquisition. Another benefit of this technology is that mobile operating systems such as Android and Apple, among others, support it. 

In this tutorial, we are going to demonstrate how to use Bluetooth Smart to display text on an OLED that was sent from a smartphone.  Below is a list of everything we need:

Hardware

Software

Android Apps

Libraries

Wiring

The picture below shows the wiring setup for both the OLED screen and the nRF8001 Development Board:

OLED

Arduino Uno

GND

GND

Vin

3.3V

Rst

Pin 5

Clk

Pin A5

Data

Pin A4

 

nRF8001 Development Board

Arduino Uno

GND

GND

VCC

5V

RST

Pin 4

RDY

Pin 3

REQ

Pin 10

MISO

Pin 12

MOSI

Pin 11

SCK

Pin 13

 

Configure nRF8001
Depending on the profile that we want the nRF8001 to have, we can create its Services and Characteristics using nRFgo Studio. When we open nRFgo Studio we get the following window:

We click on File – New – nRF8001 to create a new profile:

In this window, we are going to set the Services and Characteristics that we want the nRF8001 to have. On the right side of the window we can see a list of Services that are available. In order to add Service to our chip, we simply select and drag the Services that we want and drop them under Local (GATT Server). Usually GATT server is the slave while GATT client is the master. We can also create our own Services if we want.

For this tutorial we are going to use two Services: Device Information and Nordic UART over BTLE. For the first one, we are only going to include the characteristic Hardware Revision String with the following setup:

 

 

For the second Service, we are going to include the characteristics UART RX with the following setup:

 

 

Each Characteristic can have several modes:

   - Notify
   - Indicate
   - Write without Response
   - Write

In Notify mode, the server is updated and the client is notified. In other words, the slave (nRF8001) informs the client (smartphone) when data has changed. When the sender (in this case the nRF8001) writes, the value is automatically sent to the receiver (smartphone) without the receiver executing a “read” command. This is convenient because we get an immediate update every time something changes. Indicate mode works similar, but the receiver sends an acknowledgment to the sender. In other words, it informs the sender that transfers were successful and data was correctly received. This acknowledgement doesn’t take place in notification mode.

In Write without response mode, data is transmitted to server, but data reception is not acknowledged. In other words, the client (smartphone) sends data to the nRF8001, but the nRF8001 doesn’t let the sender know if the transfer was successful and/or if data was correctly received. Write works similar, but data reception is acknowledged.  

In nRF8001, the concept of Service Pipe is used to simplify access to Service Characteristics in a client and/or server. Pipes point to a specific Characteristic in a Service and the value is transmitted or received through that pipe.

The UUID is a Universally Unique Identifier that distinguishes Services and Characteristics. This way the pipe will know what Characteristic or Service it should point to. In this tutorial, we leave the UUIDs unchanged.

Now our GATT Services window looks like this:

While we use GATT Services to create a profile for our device with the Characteristics that we want it to have, GAP Settings is used for advertising. This lets other devices know that our nRF8001 exists and they can connect with it. We set up the GAP Settings as follows: 

In the General tab we can choose the name of our device, what is the maximum number of characters it can have, if we can modify it, and more. We can use the default settings or customize it with our own if we want. In this tutorial we simply changed the Bluetooth Device Name to URT.  

In the Service Solicitation and Local Services tab, we select the local Services we want to advertise. In this case, we want UART over BTLE to be advertised. 

In the Advanced GATT Settings, we select the Add Service Changed Characteristic to allow the server (nRF8001) to alert the client (smartphone) of any structural changes. 

In this window, we select the fields that we want to advertise. We check the box “Local Services (GATT Server)” to broadcast the Characteristic data. This way we can advertise the Services that our device has. These are the Services we defined in the GATT Services window.

The next step is to generate the source files. This is done by clicking on nRF8001 – Generate Source Files – Generate services.h. This will create three files:

  • services.h
  • services_lock.h
  • ublue_setup.gen.out

The last step is to create a setup file to run the .xml file (nRFgo Studio file) and setup the nRF8001 with the Services and Characteristics selected. In a text editor such as Notepad, type the following lines:

del services.h

del services_lock.h

del ublue_setup.gen.out.txt

"%NRFGOSTUDIOPATH%\nrfgostudio.exe" -nrf8001 -g BLE.xml -codeGenVersion 1 -o .

Finally we save the file as a .bat file. When you double click on this file, it will set the nRF8001 chip with the profile created in nRFgo Studio.

All these files are already included in the JS_nRF8001 library.

Arduino Code

Now that our chip is ready to be used, we have to write some code to make it interact with our smartphone. There is an Arduino SDK by Nordic (BLE library) that contains the source code for developing applications on Arduino. This will help us include the Services and work with them using the Arduino environment.

The Arduino SDK relies on a concept called ACI (Application Controller Interface). The ACI can be thought of as a communication channel that alerts the Arduino every time there is an event such as change in status, receipt of data, error, etc. Every cycle there is polling for updates over the ACI communication channel to check whether an event has occurred or not. The event of interest in this case is when data has been received. When text is sent over Bluetooth to the development board, the Arduino will be notified so that it can act accordingly to display the text on the OLED.

There is a template in BLE library (ble_my_project_template) that shows how the ACI is implemented in Arduino IDE.  In order to keep our code clean, we created the library JS_nRF8001 to deal with the required ACI setup and events. Below is the code used to display text sent from a smartphone on an OLED.

#include <SPI.h>
#include <EEPROM.h>
#include <boards.h>
#include <JS_nRF8001.h>
#include <services.h>
 
#include <SSD1306_text.h>
#include <Wire.h>
#define OLED_RESET 5
SSD1306_text display(OLED_RESET);
 
void setup(){ 
  display.init();
  display.clear();
  BLE_initialize();
  Serial.begin(57600);
}
 
void loop(){
  BLE_process();
  if ( BLE_free() ){
    display.clear();
    while ( BLE_free() ){
      char r = BLE_get();
      Serial.write(r);
      display.print(r);
    }
  }
}

The first section of the code includes the libraries required for the nRF8001 Development Board. The second section includes the libraries required for the OLED and defines what pin we want to use to reset the screen. Furthermore, it makes reference to the driver that we will be using (SSD1306). In the setup part, we initialize the screen and the nRF8001, and set the baud for serial data transmission. In the loop, the function “BLE_process” runs through the ACI events to process them. Then we check if there are any bytes that need to be read. If the case is true, we clear the screen and while there are bytes that need to be read, we store each one of them at a time in variable “r.” Each byte is then displayed on the serial monitor and on the screen.

When we upload the code and open the serial monitor, we get the following window:  

This lets us know that the device is ready and can be viewed (discovery mode). From our smartphone, we open the nRF UART v2.0 and click on “Connect.” We are now able to see our device called, “URT.” When we connect with the device, we get the following message:

This tells us that connection has been established with the device. When we send a text from our phone, we can see what pipe was used to transmit/receive the data and what information was sent:

The same message will be displayed on the OLED:

 

In this tutorial we demonstrate how to use Bluetooth Low Energy to send and receive text. However, there are many other applications for Bluetooth 4.0 than just sending and/or receiving messages. With Bluetooth Smart we can use our phones to receive data from sensors, turn lights on/off, control motors, control a robot, and much more.

If you have any questions about this tutorial, don't hesitate to post a comment, shoot us an email, or post it in our forum!