Exercise 1

Using AT commands to control the modem

In this exercise, we will use the AT Client sample to send AT commands from an external computer to the modem. This way we can send commands and read the response on a terminal emulator, instead of through an application running on the device.

This sample enables the AT Host Library through the config CONFIG_AT_HOST_LIBRARY. This will automatically spawn a thread to handle the AT commands, meaning to utilize this library the only thing needed in your application is enabling it through the Kconfig.


Some of terminal output logs displayed below and throughout other exercises will vary depending on your available network provider and network configurations.

Exercise Steps

1. Open the AT Client sample in VS Code, by selecting “Add an existing application” and navigating to <install_path>\nrf\samples\nrf9160\at_client.

2. Add a build configuration and select whichever board you are using:

  • nRF9160 DK: nrf9160dk_nrf9160_ns
  • Thingy:91: thingy91_nrf9160_ns

3. Build and flash the AT client sample to your device.

4. Open nRF Connect for Desktop and launch LTE Link Monitor. This is the program we will use to send AT commands to the modem.

LTE Link Monitor

4.1 In the upper left-hand corner select your device, in this case, the nRF9160 DK
4.2 This panel is used to write AT commands
4.3 Send the AT commands in the write panel to the modem


Make sure to scroll down in the left-hand panel and deselect “Automatic requests” under Settings.

This functionality issues a list of automatic commands to the modem.

Subscribe to notifications

5. Subscribe to network status notifications using +CEREG.

We would like to receive unsolicited network status notifications. The command also lets you set how much information you would like in each notification, determined by setting between level 1 and 5.

Let’s subscribe to a level-5 notification, through +CEREG, by sending

When we turn on the modem, you should observe the following regular output printed intermittently.

6. Subscribe to result code notifications using +CSCON.

This command subscribes to unsolicited result code notifications and the value you set determines how much information the notification contains, between level 1 and 3.

Let’s subscribe to level-1-related unsolicited notifications, through +CSCON, by sending

When we turn on the modem, you should observe the following regular output printed intermittently.

7. Set the system mode, using %XSYSTEMMODE

Using LTE-M:

Using NB-IoT:

This command sets the system modes as LTE-M and GNSS (left) or NB-IoT and GNSS (right). No preferred LTE mode is set.

This command must be set before the modem is turned on. If you try to use this command when the modem is operating, it will return ERROR.

8. Turn on the modem using +CFUN.

Set the modem to full functionality, which according to the documentation is the value 1.

9. Wait until the log output indicates we have a cellular connection.

Observe the unsolicited notifications from +CEREG, and specifically stat parameter indicating either

1 - Registered, home network
5 - Registered, roaming

Here we can see that the unsolicited notifications (+CEREG: 2) indicate the UE is not registered but either searching for an operator or trying to attach and the modem is in RRC Connected mode (+CSCON: 1). Then the UE attaches and is registered with a network (+CEREG: 5), and the modem goes to RRC Idle mode (+CSON: 0).

10. Store the current configurations to flash using +CFUN.

Now that we’ve connected to a network, store all configurations to flash. This will store certain AT command configurations and the network information so that in the event of a reset, the device does not have to go through the same procedure again thus speeding up the connection process.

Send the following commands, one after another.

This will save the current configurations, and turn the modem on again.


The state of +CEREG and +CSCON are not stored when running AT+CFUN=0. These commands must be run again if you want these unsolicited notifications.

Error handling

For error handling, let’s enable some error reporting functions through available AT commands

11. Let’s enable the use of the +CME error codes in responses, through +CMEE, by sending

12. Confirm this by sending an invalid command that we know returns a +CME error.

Let’s try to set the system mode while the modem is on by sending the following

You should observe the following output

According to the %XSYSTEMMODE documentation, this means Not allowed in active state.

13. Let’s also activate unsolicited reporting of error codes sent by the network, via +CNEC

The above command enables both result code +CNEC_EMM and +CNEC_ESM.

Recall that the error codes that result from these notifications are documented in

  • +CNEC_EMM: 3GPP TS 24.301 Table for EPS mobility management errors codes
  • +CNEC_ESM: 3GPP TS 24.301 Table for EPS session management errors codes

Power saving techniques

14. Now we will test the available power-saving technique PSM

14.1 Calculate the timer value for 6 minutes <Active-Time> and 8 hours <Periodic-TAU>.

Recall the table for interpreting the different timers.

Timer value unit
Timer value unit

<Active-Time>: Let’s choose the timer value unit corresponding to 6 minutes: 010. Then the timer value should be 1 in binary: 00001. This gives us 01000001.

<Periodic-Tau>: The largest time value unit applicable is 1 hour: 001. To get 8 hours, the timer value should be 8, which in binary is 01000. This gives us 00101000.

14.2 Enable power saving mode and request <Periodic-TAU> be 8 hours and <Active-Time> be 6 minutes, through +CPSMS, by sending

In the above command, we are setting a requested value for the periodic TAU timer and the Active-Time timer. Note that these can be ignored by the network.


AT+CPSMS? will just read the values you are requesting, not the actual values set by the network.

14.3 Now that we’ve requested PSM, let’s read out the values to confirm that it was actually enabled by the network. This is done by reading the value of <Active-Time>, either using +CEREG or %XMONITOR. If it is deactivated, you do not have PSM.

Send the following command

Below are two examples of response messages, one where PSM was enabled and the requested values granted and the other where PSM was not enabled.

PSM enabled:

Observe the PSM values

  • <Active-Time>: "00100110" (6 minutes)
  • <Periodic-TAU-ext>: "00101001" (9 hours)

PSM has been granted by the network, with a slightly larger Periodic TAU than requested.

PSM not enabled:

Observe that the PSM values requested in the previous step have not granted by the network and the field <Active-Time> is indicating the timer is deactivated (11100000).

PSM has not been enabled by the network and is most likely not supported by the network provider.

15. Now we will test the available power-saving technique eDRX with PSM.

15.1 Disable PSM by sending the following command

15.2 Enable eDRX by setting the applicable eDRX parameters, through +CEDRXS, by sending

Requesting for LTE-M:

Requesting for NB-IoT:

The above command sets <mode> to 2 which enables the use of eDRX and enables the unsolicited result code +CEDRXP. <AcT-type> sets for which AcT-type the value configured should apply (either 4 or 5, for LTE-M or NB-IoT respectively), and requests the eDRX interval of 20,48 seconds (<Requested_eDRX_value> to "0101").

15.3 Now that we’ve requested eDRX, let’s read out the values to confirm that it was actually enabled by the network. Similar to +CPSMS, the read command of +CEDRXS will only return the requested values. To read the values from the network, we can either wait for the unsolicited notification (if <mode> is 2) or use +CEDRXRDP.

Send the following command

Below are two examples of response messages, one where eDRX was enabled and the requested values granted and the other where eDRX was not enabled.

eDRX enabled:

Observe the eDRX values

  • <NW-Provided_eDRX_value>: "0010" (20.48 s)
  • <Paging_time_window>: "0111" (20.48 s)

eDRX has been granted by the network, with the requested eDRX Cycle.

eDRX not enabled:

Observe that the eDRX Cycle requested has not been granted, since the response does not contain there parameters.

eDRX has not been enabled by the network, and is most likely not supported by the network provider.

If steps 14 and 15 were successful and you were granted both PSM and eDRX, proceed to the next step.

16 (Optional). Let’s enable PSM and check if eDRX and PSM are supported simultaneously by the network provider.

In our case, we observe the following output

This log output shows the following granted values

<NW-Provided_eDRX_value>: "0010" (20.48 seconds)
<Active-Time>: "00100110" (6 minutes)
<Periodic-TAU-ext>: "00101001" (9 hours)

We have been granted both eDRX and PSM from the network.

Now you have practiced using AT commands to establish an LTE connection, read and understand notifications from the network and configure power saving techniques.

More on this

The Serial LTE modem application in nRF Connect SDK supports both these AT commands, as well as proprietary AT commands specific to the application. This is the application recommended when using the nRF9160 SiP as a stand-alone LTE modem.

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

Forgot your password?
Enter your email address, and we will send a link to reset your password.