In the previous exercise, we established a connection between the Nordic board, as a peripheral, and your smartphone, as a central. We were able to send some simple data using the pre-implemented LED Button Service. Although we didn’t see it, the central already selected some connection parameters when it connected to our peripheral. In this exercise, we will look into what those parameters were, and we will also look at what we can do to change our connection parameters.
We will cover Bluetooth LE services and sending data in more detail in lesson 4. For now, it is only relevant to know that we are sending some data to a connected device.
1. Get the connection parameters for the current connection.
1.1 Declare a structure to store the connection parameters.
In your on_connected() callback function, declare a structure info of type bt_conn_info to store the connection parameters. Then use the function bt_conn_get_info() to populate the info struct with the connection parameters used in the connection.
Let’s log the three main connection parameters that we talked about in Connection parameters. Note that the connection interval is represented by a unit of 1.25 ms, and the supervision timeout in units of 10 ms. So we will do some calculations to make it more readable.
Add the following lines to the end of your on_connected() callback in main.c
Note that in order for the log to be able to process float (double) numbers, we have added the config CONFIG_FPU=y to the prj.conf file. If you used the template from GitHub, this was already added.
Note that your connection parameters may differ from the ones shown here.
4. Modify the callbacks to be notified when the parameters for an LE connection have been updated.
You may have noticed that the bt_conn_cb structure we defined in the previous exercise, also has the member le_param_updated. This is used to tell our application that the connection parameters for an LE connection have been updated.
Note
There is also the event le_param_req callback member, which is called when the connected device requests an update to the connection parameters. You probably want to have this in your application, but we will not look into that event in this exercise.
4.1 Modify your connection_callbacks parameter, by adding the following line
Copy
.le_param_updated = on_le_param_updated,
C
4.2 Add the on_le_param_updated() event.
Define the callback function on_le_param_updated() to log the new connection parameters.
4.3 Already now, if we flash the application and connect to it, we may see that after some seconds, this callback will trigger, and you might see something like the log below. Note that this will vary depending on your smartphone.
So this entire time, connection parameters changes were in fact being requested by your device. This is because, even though we didn’t actively request the parameter updates when you enable the Bluetooth stack in nRF Connect SDK, default values for a lot of parameters are set, including the peripheral’s preferred connection parameters. And if these parameters don’t match the ones given by the central in the initial connection, the peripheral will automatically request changes to the connection parameters to try to get the preferred values.
Let’s take a look at what their default values are:
This is all found in Kconfig.gatt, in <install_path>\zephyr\subsys\bluetooth\host.
So we can see from the log output above that the initial connection had supervision timeout of 240 ms. Therefore, the peripheral requested a change in the parameters, and after this update, all the parameters turned out to satisfy our preferences.
5. Change the preferred connection parameters.
Let’s change our preferred connection parameters by adding the following lines to our prj.conf
The last config, CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS, responsible for automatically sending requests for connection parameters updates, is not really needed as it is set to y by default. This is why we saw the update take place even though we didn’t manually request it.
You can disable this Kconfig if you do not want your application to ask for updates automatically. In that case, you can request parameter changes manually in your application by using bt_conn_le_param_update().
The above parameters will set both the minimum and maximum preferred connection interval to 1 second. It will set the preferred peripheral latency to 0 connection intervals, and a preferred supervision timeout of 4 seconds.
6. Build and flash your application, and connect to it with your smartphone.
The log will output something like this. Note that it will take around 5 seconds after the connected event before the connection parameters are updated.
So we can see that the phone initially connected with a connection interval of 30ms and a supervision timeout of 240ms. After we requested some changes, the connection interval was changed to 1.005s and the supervision timeout to 4s. Although the 1005ms is outside of our minimum and maximum preferences, it is up to the central to decide how to reply to your request. These numbers will vary depending on the central (i.e your smartphone) in the connection, but you will most likey see 1000 ms. It is up to the phone, acting as the central, to set the connection parameters.
Note
To actually observe the connection interval, nRF Blinky is a mobile app that enables you to actually observe the changes in the connection interval when pressing the button on the device. Due to the graphical refresh rate of the nRF Connect for Mobile application, you won’t notice any difference in the connection interval when using this app.
We have now made the application less responsive. It may not make sense that an application that feels slower is better, and – in many cases – it isn’t. But remember that in order to decrease the latency, the devices need to communicate more often, thus using more power. This is something to consider when developing your own Bluetooth LE application, For instance, a temperature sensor does not need to update its value 10 times per second. Play around with these connection parameters to find something that suits your application.
7. Set our preferred PHY.
First, we need to set up a set of our preferred PHY, we will use 2M PHY.
7.1 Define the function update_phy() to update the connection’s PHY
What we are doing here is that we are triggering the PHY update directly from the connected callback event. We set our preferred PHY parameter saying that we prefer to use BT_GAP_LE_PHY_2M.
7.2 Call the function to update PHY during the connection.
Call the function update_phy()from the end of the on_connected() callback function, with the my_conn as the input parameter. Add the following line
Copy
update_phy(my_conn);
C
8. Modify the callbacks to be notified when the PHY of the connection has changed.
In theory, this should work, but we want some way to check whether the PHY actually changes. So, let’s add the le_phy_updated callback to the connection_callbacks, which will tell us if the PHY of the connection changes.
8.1 Implement the on_le_phy_updated() callback function. It can look something like this
Copy
voidon_le_phy_updated(struct bt_conn *conn, struct bt_conn_le_phy_info *param){// PHY Updatedif (param->tx_phy == BT_CONN_LE_TX_POWER_PHY_1M) {LOG_INF("PHY updated. New PHY: 1M"); }elseif (param->tx_phy == BT_CONN_LE_TX_POWER_PHY_2M) {LOG_INF("PHY updated. New PHY: 2M"); }elseif (param->tx_phy == BT_CONN_LE_TX_POWER_PHY_CODED_S8) {LOG_INF("PHY updated. New PHY: Long Range"); }}
C
8.2 Enable the ability to update the PHY
The callback is ready, but we are currently not able to add it to our connection_callbacks struct. If you look at the declaration of bt_conn_cb in conn.h, you will see that this callback is only defined if CONFIG_BT_USER_PHY_UPDATE is defined, and by default, it is not.
Add this line to your prj.conf:
Copy
CONFIG_BT_USER_PHY_UPDATE=y
Kconfig
8.3 Add the le_phy_updated event to the connection_callbacks parameter, by adding the following line to your connection_callbacks structure.
Copy
.le_phy_updated = on_le_phy_updated,
C
9. Build and flash the application.
Now try connecting to your device, and see whether the PHY is updated. What does the log say? It should look something like this:
It is not by chance that we chose 2M as the preferred PHY. Most new phones have support for 2M, while only some phones have support for Coded PHY. If you want to check whether your phone supports Coded PHY, you can replace the BT_GAP_LE_PHY_2M in your preferred_phy with BT_GAP_LE_PHY_CODED. In addition, you need to enable the Kconfig symbol CONFIG_BT_CTLR_PHY_CODED.
Lastly, we want to increase our Data Length and MTU size. Even though the LBS service which we are currently using only supports sending one byte of payload data, this is useful in many applications.
10. Define the function update_data_length() to update the data length
Here we are setting the number of bytes and the amount of time to the maximum. Here we are using the defined values BT_GAP_DATA_LEN_MAX and BT_GAP_DATA_TIME_MAX, which are set to 251 bytes and 17040µs, respectively. You can also set custom parameters if you like. Note that the negotiation that this triggers will result in the maximum parameter that both devices in the connection will support, so you may not get the full 251 bytes that you request. The peer that supports the shortest data length will have the final say.
11.1 Define the function update_data_mtu() to trigger the MTU negotiation
Similarly to how we requested the data length update, we tell our device to request an MTU update. During an MTU update negotiation, both devices will declare their supported MTU size, and the actual MTU will be set to the lower of the two, since that will be the limiting factor. You may note that this function doesn’t contain the actual MTU size. This is because this needs to be set in your prj.conf file, which we will set shortly.
11.2 We also need to declare the exchange_params parameter. This needs to be defined outside our update_mtu() function, so we will place it close to the top of our main.c
We are first enabling the data length extension by setting CONFIG_BT_USER_DATA_LEN_UPDATE=y. Then we set the actual data length by setting CONFIG_BT_CTLR_DATA_LENGTH_MAX=251. Then we set the size of the actual buffers that will be used, and lastly, we set the MTU size that we want to use in our application.
We are first enabling the data length extension by setting CONFIG_BT_USER_DATA_LEN_UPDATE=y. Then we set the size of the actual buffers that will be used, and lastly, we set the MTU size that we want to use in our application.
In addition to this, we also need to add some configurations to the network core, through the file found in child_image/hci_rpmsg.conf.
Important
Starting from nRF Connect SDK version 2.6.0, the configuration file for the network core on the nRF5340 DK is named hci_ipc.conf instead of hci_rpmsg.conf . If you are using nRF Connect SDK v2.6.0 or above, populate the hci_ipc.conf file , if you are using nRF Connect SDK <v2.6.0 , populate the hci_rpmsg.conf file .
Add the following configs to hci_rpmsg.conf or hci_ipc.conf depending on your nRF Connect SDK version
Here we set the data length we want to use in addition to setting the size of the buffers, since this is the core that actually holds the buffer. The network core will by default set the maximum number of connections to 16, which in addition to increasing the data length would cause our application to quickly run out of RAM. Therefore we need to set CONFIG_BT_MAX_CONN=2.
Note that in this exercise, that file was created for you, but if it is not present in your application, you can just create it, and it will automatically be included in the build for the network core.
13. Implement the two callback functions that will trigger when the data length is updated and when the MTU is updated.
13.1 Let us start by adding the data length update callback.
Since the MTU changed callback, exchange_func(), is placed after the implementation of update_mtu() in main.c, we need to add a declaration of it before the update_mtu() function’s implementation.
13.5 Call the functions to update the data length and MTU size in on_connected().
Make sure to call all of the parameter exchange functions that we just implemented from the on_connected() callback function
Copy
update_data_length(my_conn);update_mtu(my_conn);
C
14. Build and flash the application to your device, and connect to it using your smartphone.
Your log output should look something like this
[00:00:00.008,056] <inf> Lesson3_Exercise2: Bluetooth initialized[00:00:00.009,094] <inf> Lesson3_Exercise2: Advertising successfully started[00:00:22.159,820] <inf> Lesson3_Exercise2: Connected[00:00:22.159,820] <inf> Lesson3_Exercise2: Connection parameters: interval 30.00 ms, latency 0 intervals, timeout 240 ms[00:00:22.508,392] <inf> Lesson3_Exercise2: Data length updated. Time 251/251, length 2120/2120[00:00:22.627,807] <inf> Lesson3_Exercise2: PHY updated. New PHY: 2M[00:00:22.658,050] <inf> Lesson3_Exercise2: MTU exchange successful[00:00:22.658,050] <inf> Lesson3_Exercise2: New MTU: 244 bytes[00:00:27.428,161] <inf> Lesson3_Exercise2: Connection parameters updated: interval 1005.00 ms, latency 0 intervals, timeout 4000 ms
Terminal
You should see a lot of logs from the different callbacks, stating all the different connection parameters for your connection.
More on this
nRF5340 DK: Note that if you look at the solution for this exercise, you probably put all your configurations into your prj.conf. In the solution project, lesson3/blefund_less3_exer2/boards, you will see the files nrf5340dk_nrf5340_cpuapp.conf and nrf5340dk_nrf5340_cpuapp_ns.conf. Depending on which target you are building for, either of these files will be included as the the config file if you are using the nRF5340 DK. The prj.conf file will not be included in the build if a <BOARD_NAME>.conf is present in the boards folder.
Nordic Developer Academy Privacy Policy
1. Introduction
In this Privacy Policy you will find information on Nordic Semiconductor ASA (“Nordic Semiconductor”) processes your personal data when you use the Nordic Developer Academy.
References to “we” and “us” in this document refers to Nordic Semiconductor.
2. Our processing of personal data when you use the Nordic Developer Academy
2.1 Nordic Developer Academy
Nordic Semiconductor processes personal data in order to provide you with the features and functionality of the Nordic Developer Academy. Creating a user account is optional, but required if you want to track you progress and view your completed courses and obtained certificates. If you choose to create a user account, we will process the following categories of personal data:
Email
Name
Password (encrypted)
Course progression (e.g. which course you have completely or partly completed)
Certificate information, which consists of name of completed course and the validity of the certificate
Course results
During your use of the Nordic Developer Academy, you may also be asked if you want to provide feedback. If you choose to respond to any such surveys, we will also process the personal data in your responses in that survey.
The legal basis for this processing is GDPR article 6 (1) b. The processing is necessary for Nordic Semiconductor to provide the Nordic Developer Academy under the Terms of Service.
2.2 Analytics
If you consent to analytics, Nordic Semiconductor will use Google Analytics to obtain statistics about how the Nordic Developer Academy is used. This includes collecting information on for example what pages are viewed, the duration of the visit, the way in which the pages are maneuvered, what links are clicked, technical information about your equipment. The information is used to learn how Nordic Developer Academy is used and how the user experience can be further developed.
2.2 Newsletter
You can consent to receive newsletters from Nordic from within the Nordic Developer Academy. How your personal data is processed when you sign up for our newsletters is described in the Nordic Semiconductor Privacy Policy.
3. Retention period
We will store your personal data for as long you use the Nordic Developer Academy. If our systems register that you have not used your account for 36 months, your account will be deleted.
4. Additional information
Additional information on how we process personal data can be found in the Nordic Semiconductor Privacy Policy and Cookie Policy.
Nordic Developer Academy Terms of Service
1. Introduction
These terms and conditions (“Terms of Use”) apply to the use of the Nordic Developer Academy, provided by Nordic Semiconductor ASA, org. nr. 966 011 726, a public limited liability company registered in Norway (“Nordic Semiconductor”).
Nordic Developer Academy allows the user to take technical courses related to Nordic Semiconductor products, software and services, and obtain a certificate certifying completion of these courses. By completing the registration process for the Nordic Developer Academy, you are agreeing to be bound by these Terms of Use.
These Terms of Use are applicable as long as you have a user account giving you access to Nordic Developer Academy.
2. Access to and use of Nordic Developer Academy
Upon acceptance of these Terms of Use you are granted a non-exclusive right of access to, and use of Nordic Developer Academy, as it is provided to you at any time. Nordic Semiconductor provides Nordic Developer Academy to you free of charge, subject to the provisions of these Terms of Use and the Nordic Developer Academy Privacy Policy.
To access select features of Nordic Developer Academy, you need to create a user account. You are solely responsible for the security associated with your user account, including always keeping your login details safe.
You will able to receive an electronic certificate from Nordic Developer Academy upon completion of courses. By issuing you such a certificate, Nordic Semiconductor certifies that you have completed the applicable course, but does not provide any further warrants or endorsements for any particular skills or professional qualifications.
Nordic Semiconductor will continuously develop Nordic Developer Academy with new features and functionality, but reserves the right to remove or alter any existing functions without notice.
3. Acceptable use
You undertake that you will use Nordic Developer Academy in accordance with applicable law and regulations, and in accordance with these Terms of Use. You must not modify, adapt, or hack Nordic Developer Academy or modify another website so as to falsely imply that it is associated with Nordic Developer Academy, Nordic Semiconductor, or any other Nordic Semiconductor product, software or service.
You agree not to reproduce, duplicate, copy, sell, resell or in any other way exploit any portion of Nordic Developer Academy, use of Nordic Developer Academy, or access to Nordic Developer Academy without the express written permission by Nordic Semiconductor. You must not upload, post, host, or transmit unsolicited email, SMS, or \”spam\” messages.
You are responsible for ensuring that the information you post and the content you share does not;
contain false, misleading or otherwise erroneous information
infringe someone else’s copyrights or other intellectual property rights
contain sensitive personal data or
contain information that might be received as offensive or insulting.
Such information may be removed without prior notice.
Nordic Semiconductor reserves the right to at any time determine whether a use of Nordic Developer Academy is in violation of its requirements for acceptable use.
Violation of the at any time applicable requirements for acceptable use may result in termination of your account. We will take reasonable steps to notify you and state the reason for termination in such cases.
4. Routines for planned maintenance
Certain types of maintenance may imply a stop or reduction in availability of Nordic Developer Academy. Nordic Semiconductor does not warrant any level of service availability but will provide its best effort to limit the impact of any planned maintenance on the availability of Nordic Developer Academy.
5. Intellectual property rights
Nordic Semiconductor retains all rights to all elements of Nordic Developer Academy. This includes, but is not limited to, the concept, design, trademarks, know-how, trade secrets, copyrights and all other intellectual property rights.
Nordic Semiconductor receives all rights to all content uploaded or created in Nordic Developer Academy. You do not receive any license or usage rights to Nordic Developer Academy beyond what is explicitly stated in this Agreement.
6. Liability and damages
Nothing within these Terms of Use is intended to limit your statutory data privacy rights as a data subject, as described in the Nordic Developer Academy Privacy Policy. You acknowledge that errors might occur from time to time and waive any right to claim for compensation as a result of errors in Nordic Developer Academy. When an error occurs, you shall notify Nordic Semiconductor of the error and provide a description of the error situation.
You agree to indemnify Nordic Semiconductor for any loss, including indirect loss, arising out of or in connection with your use of Nordic Developer Academy or violations of these Terms of Use. Nordic Semiconductor shall not be held liable for, and does not warrant that (i) Nordic Developer Academy will meet your specific requirements, (ii) Nordic Developer Academy will be uninterrupted, timely, secure, or error-free, (iii) the results that may be obtained from the use of Nordic Developer Academy will be accurate or reliable, (iv) the quality of any products, services, information, or other material purchased or obtained by you through Nordic Developer Academy will meet your expectations, or that (v) any errors in Nordic Developer Academy will be corrected.
You accept that this is a service provided to you without any payment and hence you accept that Nordic Semiconductor will not be held responsible, or liable, for any breaches of these Terms of Use or any loss connected to your use of Nordic Developer Academy. Unless otherwise follows from mandatory law, Nordic Semiconductor will not accept any such responsibility or liability.
7. Change of terms
Nordic Semiconductor may update and change the Terms of Use from time to time. Nordic Semiconductor will seek to notify you about significant changes before such changes come into force and give you a possibility to evaluate the effects of proposed changes. Continued use of Nordic Developer Academy after any such changes shall constitute your acceptance of such changes. You can review the current version of the Terms of Use at any time at https://academy.nordicsemi.com/terms-of-service/
8. Transfer of rights
Nordic Semiconductor is entitled to transfer its rights and obligation pursuant to these Terms of Use to a third party as part of a merger or acquisition process, or as a result of other organizational changes.
9. Third Party Services
To the extent Nordic Developer Academy facilitates access to services provided by a third party, you agree to comply with the terms governing such third party services. Nordic Semiconductor shall not be held liable for any errors, omissions, inaccuracies, etc. related to such third party services.
10. Dispute resolution
The Terms of Use and any other legally binding agreement between yourself and Nordic Semiconductor shall be subject to Norwegian law and Norwegian courts’ exclusive jurisdiction.