Introduction: BLE Controlled OLED Display

About: We bring hardware products to life, specializing in engineering, prototyping, and mass manufacturing. We've worked with over 20 Kickstarter projects.

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.

Step 1: Materials

Below is a list of everything we need:



Android Apps


Step 2: Wiring

The pictures above show the wiring setup for both the OLED screen and the nRF8001 Development Board.

Step 3: 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 as seen above.

Step 4: Configure NRF8001 - Continued

We click on File – New – nRF8001 to create a new profile, as seen above.

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.

Step 5: Configure NRF8001 - Continued

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 as seen in the images above.

Step 6: Configure NRF8001 - Continued

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

Step 7: Configure NRF8001 - Continued - Some Explanation

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.

Step 8: Configure NRF8001 - Continued

Now our GATT Services window looks like the image above.

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.

Step 9: Configure NRF8001 - Continued

We set up the GAP Settings as shown above.

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.

Step 10: Configure NRF8001 - Continued

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.

Step 11: Configure NRF8001 - Continued

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

Step 12: Configure NRF8001 - Continued

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.

Step 13: Configure NRF8001 - Continued

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.

Step 14: 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 <SSS1306_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); } } }

Step 15: Arduino Code Explanation

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.

Step 16: Arduino Code Results

When we upload the code and open the serial monitor, we get the following window as shown above.

This lets us know that the device is ready and can be viewed (discovery mode).

Step 17: Arduino Code Results - Continued

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 message as shown in the image above.

This tells us that connection has been established with the device.

Step 18: Arduino Code Results - Continued

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 as shown in the image above.

Step 19: Arduino Code Results - Continued

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.

Ready to start creating? Check out Jaycon Systems online store to get the materials you need!

Want to learn more? Jaycon Systems has a bunch of tutorials and Instructables to help you create more things.

Let us know what you think and what you make! 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!

Thank you for reading!