In this article, we'll show you how to get a quick start on implementing basic BLE communications using Nordic Semiconductor's nRF5340 processor on the nRF5340-DK development board.
Project preparation
We start our adventure by setting up the environment with nRF Connect SDK and Visual Studio Code, using an extension from Nordic. Getting started instructions are available in the official Getting Started guide (Get Started). We will start the project with the classic "blinky diode" using the Blinky example. We can download it directly from the site or create it by clicking Create a new application in the start menu of the nRF Connect extension and selecting Blinky Sample from the list.
The Blinky project is ideal for the beginning of our adventure, not only because it contains the key elements we need to get started, but also allows us to check that our development environment is properly configured and that our hardware works flawlessly.
To move forward with building our application, we still need to set up the configuration, specifying for which board we are developing the code. We do this by selecting Create new build configuration from the Applications menu and selecting nrf5340dk_nrf5340_cpuapp in the list of available boards in the Board section. We leave the rest of the settings unchanged and finalize the process by clicking Build Configuration.
From this point, the way is opened for us to freely edit the code, compile the application and upload it directly to the microcontroller. This is all thanks to the debugger on the board, which connects to our environment via a USB interface.
By selecting the option Flash from the menu Actions upload the application to the board, and then open the terminal VCOM1, which will display all the logs sent by the function printk
. If everything went as we expected, one of the four LEDs available on the nRF5340-DK board will blink, switching between states every second.
Starting basic communication
Now we'll make a few changes to the code that will allow us to start broadcasting the default BLE "broadcast" packets. We start by adding the following lines to the prj.conf file:
These options will become part of the Kconfig configuration on which the Zephyr system build is based.
- CONFIG_BT unlocks support for Bluetooth communication,
- CONFIG_BT_PERIPHERAL configures the hardware to operate in Peripheral Device mode,
- CONFIG_BT_DEVICE_NAME allows you to set the name that will be visible during the scanning performed by the Central Device.
We now move to main.c, where we first add the following header files:
Then, over the function int main(void)
, we add two new structures:
The first of these, the board adv_data
, contains the configuration of broadcast (advertising) packets. In turn conn_callbacks
stores pointers to the functions called when the connection was established and just after it was broken.
Finally, inside the function int main(void)
, above the loop while
add:
Function bt_enable
initializes the settings and starts Bluetooth communication, a bt_le_adv_start
starts sending out broadcast packets, according to the indicated parameters.
Mobile app connection test
After uploading the app, our processor should broadcast its presence to other devices in the vicinity. The easiest way to verify this is by using a BLE-equipped phone and the nRF Connect app.
The iOS app looks quite different from that for Android, but the functionality is quite similar. Under the tab Scanner we run a scan and after a while we should see our device in the list, with a predefined name. After clicking on the button Connect the connection will be established and we should see in the application the attributes of the Generic.
We add our own characteristics
In this section, we will add a custom characteristic that will allow us to control the second diode available on our board.
Again, we start with the prj.conf file, where we add an option that allows us to configure the device as a GATT (Generic Attribute Profile) client:
Returning to main.c, we first add additional header files:
We then duplicate the code responsible for configuring LED0 and use it to configure led1:
The diode control will require two functions with distinctive headers, led_read
and led_write
:
At this point we should define a universal unique identification number (UUID) for our characteristic and for the service to which it will be assigned. For the purpose of the test, we can enter any string of numbers, but for future reference we recommend using a special generator. We enter the UUID into our code using coding macros:
It's time for the most important part of the presented code, namely the definition of our own characteristics. Here, too, special macros come to our aid, thanks to which we can easily define all the necessary parameters in one place:
The last step is to add to the previously defined array adv_data
additional element that will guarantee the visibility of our own service (with characteristics) for other devices:
Characteristics performance test
As in the earlier test, we connect through the application on the phone, but this time we should in the view of the Client to see additional service and our characteristics:
We have no choice but to check the diode control. By clicking the down arrow on the right side of the characteristic we should get in the field Value status of the diode. On the other hand, by clicking on the up arrow, we can send the value of the unsigned int, where a value of 1 should immediately turn on the diode.
Summary
In the article, we showed how quickly you can get started with BLE communications if you choose to use a platform based on the nRF5340 processor and the tools included in the nRF Connect SDK.
References
#YourOwnCharacteristicInBLE #GoodByte