Bluetooth low energy is becoming one of the most popular radio protocols for low power devices. Several sensors can all communicate to a central tablet/pc/smartphone very efficiently using BLE. This makes BLE very useful for creating a controlled environment full of embedded devices: every engineer's dream. The first of such radio devices implemented in our click boards was the BLE P click, carrying Nordic's nRF8001, it had to have the whole protocol stack implemented on the MCU. The second one was BLE 2 click, with Microchip's RN4020. BLE 2 had the whole protocol stack written on the chip itself and could act both as a central and peripheral device. Couple UART string commands were all it took to set it up.
Now we have reached to the third installment to our BLE category: meet the BLE 3 click!
BLE 3 click board
Basic overview
BLE 3 click carries the NINA-B1 module made by u-blox. The module is very flexible, as it is able to communicate with a host MCU by either UART, SPI or I2C. The protocol stack is also implemented in the chip itself, so you don't need to worry about writing one yourself. A big thank you goes to the firmware developers at u-blox who made this happen. Along with the protocol stack, the chip has a built-in default profile, as well as a couple different operating modes.
Before we get down to code and examples, let's refresh our memory about BLE for a minute.
BLE Basics: The GATT
In the first part of our BLE tutorials, I have covered how the BLE protocol works. We have gone through all the layers which form this communication, and how they are implemented. If you want to refresh your memory, feel free to take another look at our introduction to BLE.
For the sake of implementing an example with BLE 3 click, we will talk here only about the GATT layer of BLE.
As you recall, the Generic Attribute layer consists of services and characteristics. Each service consists of several characteristics, each characteristic contains user data and descriptive data (metadata). Several services, with their characteristics, make up a GATT profile. The profile, as is, does not really exist, it's just a predefined number of services with their characteristics. Services and characteristics can be distinguished by their unique UUIDs. This is very important for when our tablet/pc/smartphone will search for a specific characteristic of our BLE 3 click.
The Serial Port Service
The firmware inside the BLE 3 click board has a default GATT profile, which contains a default service named "Serial Port Service". This service is used to emulate an asynchronous communication between the click and another BLE devices. So how does it work?
The service contains a FIFO characteristic. Data between the two BLE devices is being transmitted using this characteristic. When BLE 3 click writes data to this characteristic, our smartphone will be notified with the new value of the characteristic. But, the smartphone can also write to the same FIFO characteristic, therefore, once the smartphone writes a new value to the characteristic, BLE 3 click will be notified about the change. As simple as that.
More about the Serial Port Service can be found here.
Implementing the communication
Now that we have all the basics covered, we can make a simple example: an MCU and a smartphone will establish a connection, the MCU will constantly send data about the status of a couple of pins from one of its ports. The smartphone can read this data, and can write a new value. Once the BLE 3 click receives this value, it will set the port to that exact value, which can be monitored with a couple of LED's.
The MCU side
First we will set up the BLE 3 click to advertise our data. The click uses hardware flow control, so we have to be wary about RTS and CTS pins, as well as one reset (RST) pin.
When our little example program starts, we will pull the RST pin high, which will reset our click board. After that, we will send the appropriate string commands over UART. We will set up the BLE 3 to work in data mode. What this means is that, once in data mode, every byte received from UART, the BLE 3 will send it over the air. Similar thing with receiving data, once BLE 3 click receives a new byte of data from the smartphone, everything will be sent over UART to our MCU. The MCU will constantly read the value of a port, increment it, and send the value through UART to BLE 3. The BLE 3 will set this value to the FIFO characteristic of the Serial Port Service. If a smartphone changes this value, BLE 3 will send the new value over UART to the MCU, we will catch this value in an UART interrupt and set it as the value of our port.
#include#include sbit BLE3_RTS_MCU at GPIOD_IDR.B13; sbit BLE3_CTS_MCU at GPIOD_ODR.B10; sbit BLE3_RST at GPIOC_ODR.B2; uint16_t porte_read = 0; void main() { GPIO_Digital_Input( &GPIOD_BASE, _GPIO_PINMASK_10 ); GPIO_Digital_Output( &GPIOD_BASE, _GPIO_PINMASK_13 ); GPIO_Digital_Output ( &GPIOC_BASE, _GPIO_PINMASK_2 ); GPIO_Digital_Output(&GPIOE_BASE, _GPIO_PINMASK_ALL); // Set PORTE as digital output UART3_Init_Advanced( 115200, _UART_8_BIT_DATA, // Initialize UART _UART_NOPARITY, _UART_ONE_STOPBIT, &_GPIO_MODULE_USART3_PD89); delay_ms(500); BLE3_RTS_MCU = 0; // set RTS to 0 BLE3_RST = 1; // pull reset pin high delay_ms(2000); Uart3_Write_Text("AT+UBTLN="); // set the device name to "mikroE" Uart3_Write_Text(""mikroE""); Uart3_Write_Text("r"); delay_ms(2000); Uart3_Write_Text("ATO1r"); // set BLE 3 into data mode, all bytes sent from UART will be sent over BLE delay_ms(1000); // all bytes received from BLE will be sent to UART RXNEIE_USART3_CR1_bit = 1; // setup UART interrupt NVIC_IntEnable( IVT_INT_USART3 ); EnableInterrupts(); while(1) { GPIOE_ODR = porte_read << 8; Uart3_Write(porte_read); // send the updated value of the PORT over BLE delay_ms(1000); porte_read++; } } // if smartphone/tablet writes to BLE 3, update the port with the value sent from the smartphone/tablet void LO_RX_ISR() iv IVT_INT_USART3 ics ICS_AUTO { if( RXNE_USART3_SR_bit ) { porte_read = USART3_DR; } }
The smartphone/tablet/pc side
Once our MCU side is configured, we can jump to our smartphone side. If you don't have the BLE Scanner application downloaded, you can find it here.
Once you start the application, it will scan for all nearby available BLE devices. Our device will be named "mikroE". If you have found it, feel free to press "connect"
Scanned devices in BLE Scanner app
Once connected, the application will list you all available services and characteristics. The Serial Port Service will be shown as a custom service. Once you press on it, you will see two custom characteristics, the FIFO characteristic is the first one listed, with the following UUID: 0x2456e1b926e28f83e744f34f01e9d703
Now that you have found the FIFO characteristic, if you press the button "N", you will enable notifications for this characteristic. Which means that the value of this characteristic will update as soon as it is changed, you don't have to read it manually. Once notifications are enabled, you can also write to this characteristic by pressing "W" and entering a byte array. This byte array will then be forwarded from BLE 3 to our MCU through UART, and set as the value of our port.
Discovering the services and characteristics
And that's it, your smartphone and the BLE 3 click are communicating! This is a small example which can take you a long way. The FIFO characteristic can be used for all sorts of data, from heart rate to environmental temperature, notify your smartphone from a MCU in no time with the our newest Bluetooth Low Energy module!
The code for BLE 3 example can be found here.
References
wikipedia.org "Bluetooth Low Energy" wikipedia 2016
wikipedia.org "Flow control (data) " wikipedia 2016