Feedback
Feedback

If you are having issues with the exercises, please create a ticket on DevZone: devzone.nordicsemi.com
Click or drag files to this area to upload. You can upload up to 2 files.

Exercise 1

Setting the advertising data

In this exercise, we will cover core Bluetooth LE APIs in nRF Connect SDK. We will first learn how to enable the Bluetooth LE stack and the default configurations associated with it.

Then we will dive into how to configure our hardware to broadcast non-connectable advertising, making the device act as a beacon so that neighboring scanning devices can see the data.

Exercise steps

0. Prepare the project and build and flash it to your board

0.1 Clone the GitHub repository for this course.

Copy the link to the repository and use VS Code’s Command Palette (Go to View -> Command Palette -> type Git Clone and paste in the repository link) to clone the https://github.com/NordicDeveloperAcademy/bt-fund repository somewhere close to your root directory (Ex: C:\myfw\btfund).

Avoid storing the repo in locations with long paths, as the build system might fail on some operating systems (Windows) if the application path is too long.

0.2 In the nRF Connect extension in VS Code, select Open an existing application, and open the base code for this exercise, found in bt-fund/<version>/l2/l2_e1, <version> is whichever version directory you are using.

Navigation

The course repository contains two version directories depending on which nRF Connect SDK version you are using: v2.8.x-v2.7.0 and v2.3.0-v2.6.2. Select the directory that matches the nRF Connect SDK version you are using. Some of the exercises will also have varying exercise texts depending on which version you are using, this will be reflected by tabs at the beginning of the exercise text.

1. Include the Bluetooth LE stack in your project.

In order to include the Bluetooth LE stack in your nRF Connect SDK project, you need to enable CONFIG_BT in prj.conf . This option will already be enabled in all upcoming exercises.

CONFIG_BT=y
Kconfig

Enabling this symbol will apply a set of default configurations for the stack.

The highlights of the default configuration are listed below:

  • Broadcast support (BT_BROADCASTER) is enabled.
  • The SoftDevice Controller is used (BT_LL_CHOICE = BT_LL_SOFTDEVICE).
  • The TX Power is set to 0 dBm (BT_CTLR_TX_PWR = BT_CTLR_TX_PWR_0)

2. Set the Bluetooth LE device name.

The name is a C string that can theoretically be up to 248 bytes long (excluding NULL termination). In practice, it is highly recommended to keep it as short as possible, as when we include it in the advertising data, we have only 31 bytes, and these 31 bytes are shared by all advertising data. It can also be an empty string. In this exercise, we will call our device Nordic_Beacon.

Add the following line in prj.conf:

 CONFIG_BT_DEVICE_NAME="Nordic_Beacon"
Kconfig

We will include the device name in the advertising data in a later step.

3. Include the header files of the Bluetooth LE stack needed

Include the following header files needed for enabling the stack, populating the advertising data, and starting advertising.

Add the following lines in main.c

#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/gap.h>
C

4. Prepare the advertising data.

For the advertising data, we will use both the advertising packet and the scan response packet.

4.1 Prepare the advertising packet.

4.1.1 Declare an array ad[] of type struct bt_data, which will be the advertising packet to send out.

Add the following lines in main.c

static const struct bt_data ad[] = {
	/* STEP 4.1.2 - Set the advertising flags */

	/* STEP 4.1.3 - Set the advertising packet data  */

};
C

4.1.2 Populate the flags using the helper macro BT_DATA_BYTES().

The first thing we need to prepare in the advertising packet is the advertising flags, BT_DATA_FLAGS.

To help us populate these flags, we will use the helper macro BT_DATA_BYTES(), which has the following signature

In this exercise, we are creating a broadcaster with non-connectable advertising. Therefore, we will only set the advertising flag BT_LE_AD_NO_BREDR, to indicate that classic Bluetooth (BR/EDR) is not supported.

Note

Since Nordic’s products only support Bluetooth LE, this flag should always be set to this value.

Add the following line in main.c

BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR),
C

4.1.3 Set the advertising packet data using the helper macro BT_DATA().

There are numerous standard data types that can be included in the advertising data (either in the advertising packet or the scan response). These data types are defined in the Bluetooth Supplement to the Core Specification.

Below are a few commonly used ones, that we will be using in following exercises. The complete list of advertising data types can be found here.

  • Complete local name (BT_DATA_NAME_COMPLETE): This is simply the device name. We will include the Complete Local Name in the advertising packet of this exercise.
  • Shortened local name (BT_DATA_NAME_SHORTENED): A shorter version of the Complete Local name.
  • Uniform Resource Identifier (BT_DATA_URI): You can use this type for advertising URI like website addresses (URLs). We will include the URL of Nordic Developer Academy (https://academy.nordicsemi.com/) in the scan response packet of this exercise.
  • Service UUID: Different options are available here. This is useful if you want a central to filter advertising devices based on services. We will include the UUID for the LBS and NUS services in upcoming exercises.
  • Manufacturer Specific Data (BT_DATA_MANUFACTURER_DATA). This is a popular type that enables companies to define their own custom advertising data, as in the case of iBeacon. We will cover using this data type in the exercise of the next lesson.

For now, we want to include the complete local name, BT_DATA_NAME_COMPLETE, in the advertising packet.

We will use the macro BT_DATA() to populate data into the advertising packet. The macro expects three parameters as shown in the signature below

Add the following line in main.c

BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
C

Note in legacy advertising we have only 31 octets available. To send more than 31 octets in advertisements, we will need to use the scan response, as we will see next.

4.2. Prepare the scan response.

In the scan response, we will include the URL for Nordic Developer Academy, for the sake of demonstration.

4.2.1 Declare the scan response packet.

Same as we did for the advertising packet, we will declare it as an array sd[] of type struct bt_data.

Add the following code in main.c

static const struct bt_data sd[] = {
        /* 4.2.3 Include the URL data in the scan response packet*/

};
C

4.2.2 Declare the URL data to include in the scan response packet.

We will declare the URL as an array of static unsigned char. In the first byte, we need to specify the URI Scheme Name String Mapping as specified in the Assigned Numbers Document from the Bluetooth SIG. The scheme is used to save data transmitted over the air. So for example, instead of transmitting advertising of 6 bytes for the “https:”, we only need to send one byte (0x17).

URI Scheme Name String Mapping defined by the Bluetooth SIG in Assigned Numbers Document

Add the following lines in main.c

static unsigned char url_data[] ={0x17,'/','/','a','c','a','d','e','m','y','.',
                                 'n','o','r','d','i','c','s','e','m','i','.',
                                 'c','o','m'};
C

4.2.3 Include the URL data in the scan response packet. Add the following line inside the sd packet.

BT_DATA(BT_DATA_URI, url_data,sizeof(url_data)),
C

5. Enable the Bluetooth LE stack.

The function bt_enable() is used to enable the Bluetooth LE stack in the application. This function must be called before any other calls that require communication with the Bluetooth LE hardware (for example, start advertising).

bt_enable() is blocking when passing NULL to it, and non-blocking if you pass a bt_ready_cb_t callback.

Add the following lines in main()

err = bt_enable(NULL);
if (err) {
	LOG_ERR("Bluetooth init failed (err %d)\n", err);
	return -1;
}
LOG_INF("Bluetooth initialized\n");
C

6. Start advertising.

Now that we have prepared the advertising data (both the advertising packet and the scan response packet), we are ready to start advertising.

Do this by calling the function, bt_le_adv_start(), which has the following signature

bt_le_adv_start() function

The first parameter this function expects is the advertising parameters. Here, we can either use predefined macros that cover the most common cases. Or we can declare a variable of type bt_le_adv_param and set the parameters manually.

For now, we will use one of the predefined macros. In exercise 2, we will set this parameter manually. Available macros are documented here. In our case, we will be using BT_LE_ADV_NCONN – non-connectable advertising with a minimum advertising interval of 100 ms and a maximum advertising interval of 150 ms.

The second and third parameters are the advertising packet (created in step 4.1) and its size, while the fourth and fifth parameters are the scan response (created in step 4.2) and its size.

Add the following lines inside main()

err = bt_le_adv_start(BT_LE_ADV_NCONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
if (err) {
	LOG_ERR("Advertising failed to start (err %d)\n", err);
	return -1;
}
C

7. Build and flash the application on your board.

You should notice that LED1 (LED0 on nRF54 Series devices) on your board is blinking, indicating that your board is advertising.

8. Open nRF Connect for Mobile on your smartphone.

Android

In the SCANNER tab press on the SCAN button to begin scanning

Android

9. Tap on Nordic_Beacon to view the advertising data.

Android

The first thing to notice is that there is no CONNECT button displayed. This is because we are advertising non-connectable packets (BT_LE_ADV_NCONN). Let’s now spend some time interpreting the data.

  1. RSSI level is the received signal strength indicator on the receiver side
  2. Advertising interval. Since we chose BT_LE_ADV_NCONN, the advertising interval is between 100-150 ms
  3. Advertising flags that we set in step 4.1.2 (Bluetooth Classic BR/EDR not supported)
  4. The complete local name, that we set in step 2
  5. The URI data that we included in the scan response packet. Note that you can tap on the OPEN button to open the link directly in a browser.

We encourage you to try and change these parameters in the code, build and flash your board to see how easy it is to control the advertising data.

iOS

In the Scanner tab, select the play icon to begin scanning

iOS

9. Tap on Nordic_Beacon to view the advertising data.

iOS

The first thing to notice is that there is no Connect button displayed. This is because we are advertising non-connectable packets (BT_LE_ADV_NCONN). Let’s now spend some time interpreting the data.

  1. RSSI level is the received signal strength indicator on the receiver side
  2. Advertising interval. Since we chose BT_LE_ADV_NCONN, the advertising interval is between 100-150 ms

Since the iOS Bluetooth stack filters out a lot of the advertising data, this is all the information we can see.

We encourage you to try and change these parameters in the code, build and flash your board to see how easy it is to control the advertising data.

Register an account
Already have an account? Log in
(All fields are required unless specified optional)

  • 8 or more characters
  • Upper and lower case letters
  • At least one number or special character

Forgot your password?
Enter the email associated with your account, and we will send you a link to reset your password.