In this exercise, let’s use the LTE Link Controller library in nRF Connect SDK to establish the LTE connection. One advantage of using a high-level library instead of direct serial communication commands is that the library lets you asynchronously set up the LTE connection, which is what we will do in this exercise.
This course builds on the nRF Connect SDK Fundamentals course and focuses on Cellular IoT. You need to read Lesson 1 in the nRF Connect SDK Fundamentals to learn how to install nRF Connect SDK on your machine and build applications. Furthermore, completing the nRF Connect SDK Fundamentals course is strongly advised as it provides a comprehensive understanding of the nRF Connect SDK. The exercises in this course assume you have a basic understanding of the nRF Connect SDK.
1. Open the base exercise code for this exercise in VS Code.
1.1 Clone the GitHub repository for this course.
For Windows: Make sure to have place the repository as close to the root / C: drive as possible, to shorten the path lengths, for example C:\ncs\cell-fund
.
The maximum full path to an object file is 250 characters, and the build can fail if this limit is exceeded.
Copy the link to the repository and use VS Code’s Command Palette to clone the repository.
1.2 In the nRF Connect for VS Code extension, select Open an existing application, and open the base code for this exercise, found in cell-fund/<version>/l2/l2_e2
, of whichever version directory (<version>
) you are using.
Due to changes in the nRF Connect SDK, make sure to use the version folder of the base code and exercise tabs that matches the SDK version you are running.
2. Enable the nRF Modem library.
Search for STEP 2
in prj.conf
and add the following line:
CONFIG_NRF_MODEM_LIB=y
KconfigThe nRF Modem Library is the library that interfaces with the nRF91 Series modem and is necessary for the LTE link controller library to run. We will talk more about the nRF Modem Library in lesson 3, but for now we will just enable it in our application.
3. Enable and configure the LTE link controller library.
Search for STEP 3
in prj.conf
and add the following lines
CONFIG_LTE_LINK_CONTROL=y
Kconfig4. Include the relevant header files.
Include the header file for the nRF Modem library and the LTE link controller library.
In the main.c
file, search for STEP 4
and add the following line
#include <modem/nrf_modem_lib.h>
#include <modem/lte_lc.h>
C5. Define the semaphore lte_connected
.
Define a semaphore using K_SEM_DEFINE
, with initial count 0 and max count 1, to be used when connecting.
Search for STEP 5
and add the following line
static K_SEM_DEFINE(lte_connected, 0, 1);
C6. Define the function modem_configure()
.
Define the function modem_configure()
to initialize the modem library and the LTE connection.
Search for STEP 6
and add the following lines
static int modem_configure(void)
{
int err;
LOG_INF("Initializing modem library");
err = nrf_modem_lib_init();
if (err) {
LOG_ERR("Failed to initialize the modem library, error: %d", err);
return err;
}
LOG_INF("Connecting to LTE network");
err = lte_lc_connect_async(lte_handler);
if (err) {
LOG_ERR("Error in lte_lc_connect_async, error: %d", err);
return err;
}
return 0;
}
C7. In the event handler for the link controller lte_handler()
.
In lte_handler()
, in the event of changed registration status (LTE_LC_EVT_NEW_REG_STATUS
), check if the modems registration status is connected (LTE_LC_NW_REG_REGISTERED_HOME
or LTE_LC_NW_REG_REGISTERED_ROAMING
), and if so, give the semaphore lte_connected
.
Search for STEP 7.1
and add the following lines
case LTE_LC_EVT_NW_REG_STATUS:
if ((evt->nw_reg_status != LTE_LC_NW_REG_REGISTERED_HOME) &&
(evt->nw_reg_status != LTE_LC_NW_REG_REGISTERED_ROAMING)) {
break;
}
LOG_INF("Network registration status: %s",
evt->nw_reg_status == LTE_LC_NW_REG_REGISTERED_HOME ?
"Connected - home network" : "Connected - roaming");
k_sem_give(<e_connected);
break;
C7.2 Upon the event of changed RRC mode (LTE_LC_EVT_RRC_UPDATE
), print the RRC mode.
Search for STEP 7.2
and add the following lines
case LTE_LC_EVT_RRC_UPDATE:
LOG_INF("RRC mode: %s", evt->rrc_mode == LTE_LC_RRC_MODE_CONNECTED ?
"Connected" : "Idle");
break;
C8. In main()
, call modem_configure()
to initiate the LTE connection.
Search for STEP 8
and add the following lines
err = modem_configure();
if (err) {
LOG_ERR("Failed to configure the modem");
return 0;
}
C9. Take the semaphore lte_connected
.
Take the semaphore using k_sem_take()
with no timeout, which will only be given in the callback function once the modem’s registration status is connected.
Search for STEP 9
and add the following lines
k_sem_take(<e_connected, K_FOREVER);
CAfter taking the semaphore, the two next lines will only be run when the device is connected to the network at which point the semaphore is given.
10. Turn on the LED status LED
Upon successfully connecting to the network, turn on the status LED.
Search for STEP 10
and add the following line
dk_set_led_on(DK_LED2);
C11. Build and flash the application.
11.1 Add a build configuration and select whichever board you are using:
nrf9161dk/nrf9161/ns
or nrf9151dk/nrf9151/ns
nrf9160dk/nrf9160/ns
thingy91x/nrf9151/ns
thingy91/nrf9160/ns
Make sure the Build after generating configuration option is enabled to trigger the build process after clicking on the Build Configuration button.
For the nRF91x1 DK, you need to have nrfjprog v10.22.1 or higher. You can check this by running nrfjprog -v
in a terminal window.
11.2 Flash the application to your device.
If you are using the Thingy:91 X or Thingy:91 without an external debugger, make sure to follow the Thingy:91 flash procedure.
You should see the following log output on your console.
*** Booting nRF Connect SDK ***
<inf> Lesson2_Exercise2: Initializing modem library
<inf> Lesson2_Exercise2: Connecting to LTE network
<inf> Lesson2_Exercise2: RRC mode: Connected
<inf> Lesson2_Exercise2: Network registration status: Connected - roaming
<inf> Lesson2_Exercise2: Connected to LTE network
<inf> Lesson2_Exercise2: RRC mode: Idle
TerminalIn addition, the connection LED which is the LED that will indicate a connection (LED2 on the nRF91 DK or green LED on the Thingy:91) should be lit.
Your device can show up as multiple consecutive COM ports. If this is the case, you need to test which COM port is the correct one.
12. For further debugging purposes, let’s enable the AT Host library.
In the prj.conf
file, search for STEP 12
and add the following lines to the prj.conf
file
CONFIG_AT_HOST_LIBRARY=y
CONFIG_UART_INTERRUPT_DRIVEN=y
KconfigCONFIG_AT_HOST_LIBRARY
is to enable the AT Host library and CONFIG_UART_INTERRUPT_DRIVEN
enables interrupt support for UART so that the AT Host library can print asynchronously to the console.
The AT Host library automatically spawns a thread to print status AT commands.
13. Build and flash the application again.
You should notice intermittent unsolicited AT command notifications +CEREG
and +CSCON
being printed on the console among the log messages from the application.
*** Booting nRF Connect SDK 2.8.0-3758bcbfa5cd ***
<inf> Lesson2_Exercise2: Initializing modem library
<inf> Lesson2_Exercise2: Connecting to LTE network
+CEREG: 2,"76C1","030EB103",7
+CSCON: 1
<inf> Lesson2_Exercise2: RRC mode: Connected
+CEREG: 5,"76C1","030EB103",7,,,"11100000","11100000"
<inf> Lesson2_Exercise2: Network registration status: Connected - roaming
<inf> Lesson2_Exercise2: Connected to LTE network
+CSCON: 0
<inf> Lesson2_Exercise2: RRC mode: Idle
Terminal14. Enabling the AT Host library also allows us to send AT commands while the application is running.
Let’s read out the IMEI of our device by sending:
AT+CGSN=1
Observe the AT command response containing the 15-digit IMEI (censored here).
+CGSN: "3515161726xxxxx"
OK
TerminalThe solution for this exercise can be found in l2/l2_e2_sol
of whichever version directory you are using.
In this exercise, let’s use the LTE Link Controller library in nRF Connect SDK to establish the LTE connection. One advantage of using a high-level library instead of direct serial communication commands is that the library lets you asynchronously set up the LTE connection, which is what we will do in this exercise.
This course builds on the nRF Connect SDK Fundamentals course and focuses on Cellular IoT. You need to read Lesson 1 in the nRF Connect SDK Fundamentals to learn how to install nRF Connect SDK on your machine and build applications. Furthermore, completing the nRF Connect SDK Fundamentals course is strongly advised as it provides a comprehensive understanding of the nRF Connect SDK. The exercises in this course assume you have a basic understanding of the nRF Connect SDK.
1. Open the base exercise code for this exercise in VS Code.
1.1 Clone the GitHub repository for this course.
Copy the link to the repository and use VS Code’s Command Palette to clone the repository.
1.2 In the nRF Connect for VS Code extension, select Open an existing application, and open the base code for this exercise, found in cell-fund/<version>/l2/l2_e2
, of whichever version directory (<version>
) you are using.
Due to changes in the nRF Connect SDK, make sure to use the version folder of the base code and exercise tabs that matches the SDK version you are running.
2. Enable the nRF Modem library.
Search for STEP 2
in prj.conf
and add the following line:
CONFIG_NRF_MODEM_LIB=y
KconfigThe nRF Modem Library is the library that interfaces with the nRF91 Series modem and is necessary for the LTE link controller library to run. We will talk more about the nRF Modem Library in lesson 3, but for now we will just enable it in our application.
3. Enable and configure the LTE link controller library.
Search for STEP 3
in prj.conf
and add the following lines
CONFIG_LTE_LINK_CONTROL=y
Kconfig4. Include the relevant header files.
Include the header file for the nRF Modem library and the LTE link controller library.
In the main.c
file, search for STEP 4
and add the following line
#include <modem/nrf_modem_lib.h>
#include <modem/lte_lc.h>
C5. Define the semaphore lte_connected
.
Define a semaphore using K_SEM_DEFINE
, with initial count 0 and max count 1, to be used when connecting.
Search for STEP 5
and add the following line
static K_SEM_DEFINE(lte_connected, 0, 1);
C6. Define the function modem_configure()
.
Define the function modem_configure()
to initialize the modem library and the LTE connection.
Search for STEP 6
and add the following lines
static int modem_configure(void)
{
int err;
LOG_INF("Initializing modem library");
err = nrf_modem_lib_init();
if (err) {
LOG_ERR("Failed to initialize the modem library, error: %d", err);
return err;
}
/* lte_lc_init deprecated in >= v2.6.0 */
#if NCS_VERSION_NUMBER < 0x20600
err = lte_lc_init();
if (err) {
LOG_ERR("Failed to initialize LTE link control library, error: %d", err);
return err;
}
#endif
LOG_INF("Connecting to LTE network");
err = lte_lc_connect_async(lte_handler);
if (err) {
LOG_ERR("Error in lte_lc_connect_async, error: %d", err);
return err;
}
return 0;
}
CIn nRF Connect SDK v2.6.0 and up, lte_lc_init()
is deprecated as the LTE link control library is initialized automatically when included in the application.
7. In the event handler for the link controller lte_handler()
.
In lte_handler()
, in the event of changed registration status (LTE_LC_EVT_NEW_REG_STATUS
), check if the modems registration status is connected (LTE_LC_NW_REG_REGISTERED_HOME
or LTE_LC_NW_REG_REGISTERED_ROAMING
), and if so, give the semaphore lte_connected
.
Search for STEP 7.1
and add the following lines
case LTE_LC_EVT_NW_REG_STATUS:
if ((evt->nw_reg_status != LTE_LC_NW_REG_REGISTERED_HOME) &&
(evt->nw_reg_status != LTE_LC_NW_REG_REGISTERED_ROAMING)) {
break;
}
LOG_INF("Network registration status: %s",
evt->nw_reg_status == LTE_LC_NW_REG_REGISTERED_HOME ?
"Connected - home network" : "Connected - roaming");
k_sem_give(<e_connected);
break;
C7.2 Upon the event of changed RRC mode (LTE_LC_EVT_RRC_UPDATE
), print the RRC mode.
Search for STEP 7.2
and add the following lines
case LTE_LC_EVT_RRC_UPDATE:
LOG_INF("RRC mode: %s", evt->rrc_mode == LTE_LC_RRC_MODE_CONNECTED ?
"Connected" : "Idle");
break;
C8. In main()
, call modem_configure()
to initiate the LTE connection.
Search for STEP 8
and add the following lines
err = modem_configure();
if (err) {
LOG_ERR("Failed to configure the modem");
return 0;
}
C9. Take the semaphore lte_connected
.
Take the semaphore using k_sem_take()
with no timeout, which will only be given in the callback function once the modem’s registration status is connected.
Search for STEP 9
and add the following lines
k_sem_take(<e_connected, K_FOREVER);
CAfter taking the semaphore, the two next lines will only be run when the device is connected to the network at which point the semaphore is given.
10. Turn on the LED status LED
Upon successfully connecting to the network, turn on the status LED.
Search for STEP 10
and add the following line
dk_set_led_on(DK_LED2);
C11. Build and flash the application.
11.1 Add a build configuration and select whichever board you are using:
nrf9161dk_nrf9161_ns
or nrf9151dk_nrf9151_ns
nrf9160dk_nrf9160_ns
thingy91_nrf9160_ns
Make sure the Build after generating configuration option is enabled to trigger the build process after clicking on the Build Configuration button.
For the nRF91x1 DK, you need to have nrfjprog v10.22.1 or higher. You can check this by running nrfjprog -v
in a terminal window.
11.2 Flash the application to your device.
If you are using the Thingy:91 without an external debugger, make sure to follow the Thingy:91 flash procedure.
You should see the following log output on your console.
*** Booting nRF Connect SDK 2.6.1-3758bcbfa5cd ***
<inf> Lesson2_Exercise2: Initializing modem library
<inf> Lesson2_Exercise2: Connecting to LTE network
<inf> Lesson2_Exercise2: RRC mode: Connected
<inf> Lesson2_Exercise2: Network registration status: Connected - roaming
<inf> Lesson2_Exercise2: Connected to LTE network
<inf> Lesson2_Exercise2: RRC mode: Idle
TerminalIn addition, the connection LED which is the LED that will indicate a connection (LED2 on the nRF91 DK or green LED on the Thingy:91) should be lit.
Your device can show up as multiple consecutive COM ports. If this is the case, you need to test which COM port is the correct one.
12. For further debugging purposes, let’s enable the AT Host library.
In the prj.conf
file, search for STEP 12
and add the following lines to the prj.conf
file
CONFIG_AT_HOST_LIBRARY=y
CONFIG_UART_INTERRUPT_DRIVEN=y
KconfigCONFIG_AT_HOST_LIBRARY
is to enable the AT Host library and CONFIG_UART_INTERRUPT_DRIVEN
enables interrupt support for UART so that the AT Host library can print asynchronously to the console.
The AT Host library automatically spawns a thread to print status AT commands.
13. Build and flash the application again.
You should notice intermittent unsolicited AT command notifications +CEREG
and +CSCON
being printed on the console among the log messages from the application.
*** Booting nRF Connect SDK 2.6.1-3758bcbfa5cd ***
<inf> Lesson2_Exercise2: Initializing modem library
<inf> Lesson2_Exercise2: Connecting to LTE network
+CEREG: 2,"76C1","030EB103",7
+CSCON: 1
<inf> Lesson2_Exercise2: RRC mode: Connected
+CEREG: 5,"76C1","030EB103",7,,,"11100000","11100000"
<inf> Lesson2_Exercise2: Network registration status: Connected - roaming
<inf> Lesson2_Exercise2: Connected to LTE network
+CSCON: 0
<inf> Lesson2_Exercise2: RRC mode: Idle
Terminal14. Enabling the AT Host library also allows us to send AT commands while the application is running.
Let’s read out the IMEI of our device by sending:
AT+CGSN=1
Observe the AT command response containing the 15-digit IMEI (censored here).
+CGSN: "3515161726xxxxx"
OK
TerminalThe solution for this exercise can be found in l2/l2_e2_sol
of whichever version directory you are using.
In this exercise, let’s use the LTE Link Controller library in nRF Connect SDK to establish the LTE connection. One advantage of using a high-level library instead of direct serial communication commands is that the library lets you asynchronously set up the LTE connection, which is what we will do in this exercise.
This course builds on the nRF Connect SDK Fundamentals course and focuses on Cellular IoT. You need to read Lesson 1 in the nRF Connect SDK Fundamentals to learn how to install nRF Connect SDK on your machine and build applications. Furthermore, completing the nRF Connect SDK Fundamentals course is strongly advised as it provides a comprehensive understanding of the nRF Connect SDK. The exercises in this course assume you have a basic understanding of the nRF Connect SDK.
1. Open the base exercise code for this exercise in VS Code.
1.1 Clone the GitHub repository for this course.
Copy the link to the repository and use VS Code’s Command Palette to clone the repository.
1.2 In the nRF Connect for VS Code extension, select Open an existing application, and open the base code for this exercise, found in cell-fund/<version>/l2/l2_e2
, of whichever version directory (<version>
) you are using.
Due to changes in the nRF Connect SDK, make sure to use the version folder of the base code and exercise tabs that matches the SDK version you are running.
2. Enable the nRF Modem library.
Search for STEP 2
in prj.conf
and add the following line:
CONFIG_NRF_MODEM_LIB=y
KconfigThe nRF Modem Library is the library that interfaces with the nRF91 Series modem and is necessary for the LTE link controller library to run. We will talk more about the nRF Modem Library in lesson 3, but for now we will just enable it in our application.
3. Enable and configure the LTE link controller library.
Search for STEP 3
in prj.conf
and add the following lines
CONFIG_LTE_LINK_CONTROL
enables the library and CONFIG_LTE_AUTO_INIT_AND_CONNECT
disables the auto initialize and connect functionality.
CONFIG_LTE_LINK_CONTROL=y
CONFIG_LTE_AUTO_INIT_AND_CONNECT=n
Kconfig4. Include the relevant header files.
Include the header file for the LTE link controller library.
In the main.c
file, search for STEP 4
and add the following line
#include <modem/lte_lc.h>
C5. Define the semaphore lte_connected
.
Define a semaphore using K_SEM_DEFINE
, with initial count 0 and max count 1, to be used when connecting.
Search for STEP 5
and add the following line
static K_SEM_DEFINE(lte_connected, 0, 1);
C6. Define the function modem_configure()
.
Define the function modem_configure()
to initialize the LTE connection.
Search for STEP 6
and add the following lines
int err = lte_lc_init_and_connect_async(lte_handler);
if (err) {
LOG_ERR("Modem could not be configured, error: %d", err);
return;
}
C7. In the event handler for the link controller lte_handler()
.
In lte_handler()
, in the event of changed registration status (LTE_LC_EVT_NEW_REG_STATUS
), check if the modems registration status is connected (LTE_LC_NW_REG_REGISTERED_HOME
or LTE_LC_NW_REG_REGISTERED_ROAMING
), and if so, give the semaphore lte_connected
.
Search for STEP 7.1
and add the following lines
case LTE_LC_EVT_NW_REG_STATUS:
if ((evt->nw_reg_status != LTE_LC_NW_REG_REGISTERED_HOME) &&
(evt->nw_reg_status != LTE_LC_NW_REG_REGISTERED_ROAMING)) {
break;
}
LOG_INF("Network registration status: %s",
evt->nw_reg_status == LTE_LC_NW_REG_REGISTERED_HOME ?
"Connected - home network" : "Connected - roaming");
k_sem_give(<e_connected);
break;
C7.2 Upon the event of changed RRC mode (LTE_LC_EVT_RRC_UPDATE
), print the RRC mode.
Search for STEP 7.2
and add the following lines
case LTE_LC_EVT_RRC_UPDATE:
LOG_INF("RRC mode: %s", evt->rrc_mode == LTE_LC_RRC_MODE_CONNECTED ?
"Connected" : "Idle");
break;
C8. In main()
, call modem_configure()
to initiate the LTE connection.
Search for STEP 8
and add the following lines
err = modem_configure();
if (err) {
LOG_ERR("Failed to configure the modem");
return 0;
}
C9. Take the semaphore lte_connected
.
Take the semaphore using k_sem_take()
with no timeout, which will only be given in the callback function once the modem’s registration status is connected.
Search for STEP 9
and add the following lines
k_sem_take(<e_connected, K_FOREVER);
CAfter taking the semaphore, the two next lines will only be run when the device is connected to the network at which point the semaphore is given.
10. Turn on the LED status LED
Upon successfully connecting to the network, turn on the status LED.
Search for STEP 10
and add the following line
dk_set_led_on(DK_LED2);
C11. Build and flash the application.
11.1 Add a build configuration and select whichever board you are using:
nrf9160dk_nrf9160_ns
thingy91_nrf9160_ns
Make sure the Build after generating configuration option is enabled to trigger the build process after clicking on the Build Configuration button.
11.2 Flash the application to your device.
If you are using the Thingy:91 without an external debugger, make sure to follow the Thingy:91 flash procedure.
You should see the following log output on your console.
*** Booting nRF Connect SDK 2.3.0-3758bcbfa5cd ***
<inf> Lesson2_Exercise2: Initializing modem library
<inf> Lesson2_Exercise2: Connecting to LTE network
<inf> Lesson2_Exercise2: RRC mode: Connected
<inf> Lesson2_Exercise2: Network registration status: Connected - roaming
<inf> Lesson2_Exercise2: Connected to LTE network
<inf> Lesson2_Exercise2: RRC mode: Idle
TerminalIn addition, the connection LED which is the LED that will indicate a connection (LED2 on the nRF91 DK or green LED on the Thingy:91) should be lit.
Your device can show up as multiple consecutive COM ports. If this is the case, you need to test which COM port is the correct one.
12. For further debugging purposes, let’s enable the AT Host library.
In the prj.conf
file, search for STEP 12
and add the following lines to the prj.conf
file
CONFIG_AT_HOST_LIBRARY=y
CONFIG_UART_INTERRUPT_DRIVEN=y
KconfigCONFIG_AT_HOST_LIBRARY
is to enable the AT Host library and CONFIG_UART_INTERRUPT_DRIVEN
enables interrupt support for UART so that the AT Host library can print asynchronously to the console.
The AT Host library automatically spawns a thread to print status AT commands.
13. Build and flash the application again.
You should notice intermittent unsolicited AT command notifications +CEREG
and +CSCON
being printed on the console among the log messages from the application.
*** Booting nRF Connect SDK 2.3.0-3758bcbfa5cd ***
<inf> Lesson2_Exercise2: Initializing modem library
<inf> Lesson2_Exercise2: Connecting to LTE network
+CEREG: 2,"76C1","030EB103",7
+CSCON: 1
<inf> Lesson2_Exercise2: RRC mode: Connected
+CEREG: 5,"76C1","030EB103",7,,,"11100000","11100000"
<inf> Lesson2_Exercise2: Network registration status: Connected - roaming
<inf> Lesson2_Exercise2: Connected to LTE network
+CSCON: 0
<inf> Lesson2_Exercise2: RRC mode: Idle
Terminal14. Enabling the AT Host library also allows us to send AT commands while the application is running.
Let’s read out the IMEI of our device by sending:
AT+CGSN=1
Observe the AT command response containing the 15-digit IMEI (censored here).
+CGSN: "3515161726xxxxx"
OK
TerminalThe solution for this exercise can be found in l2/l2_e2_sol
of whichever version directory you are using.