In this exercise, we will modify the blinky example so that LED1 is turned on only when button 1 is being pressed, as shown in the illustration below.
On the nRF54L15 DK, the board’s LEDs and Buttons are labeled with PCB labels (PCB silkscreen) that start with 0 (LED0-LED3) and (BUTTON0-BUTTON3). In previous-generation development kits, the indexing starts with 1 (LED1-LED4). So, on the nRF54L14 DK, we will be working with LED0 and BUTTON0.
To do this, we will use the polling method, as discussed in GPIO Generic API. This is done by continuously polling the CPU to check if the button was pressed and then update the LED accordingly. In Exercise 2 that follows, we will learn how to use GPIO interrupts, which is more power-efficient than polling.
If we recall the schematic of the nRF52833 DK, there are four push-buttons connected to the same GPIO peripheral as the LEDs, GPIO0
(node label: gpio0
). This can be seen in the GPIO pin mapping, for instance, notice that button 1 is connected to P0.11
. The 0 in P0
symbolizes it is &gpio0
.
This is why the same driver is needed for both the LEDs and buttons. This is also evident from the DK’s devicetree file nrf52833dk_nrf52833.dts
.
buttons {
compatible = "gpio-keys";
button0: button_0 {
gpios = <&gpio0 11 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
label = "Push button switch 0";
};
button1: button_1 {
gpios = <&gpio0 12 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
label = "Push button switch 1";
};
/* ... */
};
};
/* ... */
/* These aliases are provided for compatibility with samples */
aliases {
/* ... */
sw0 = &button0;
sw1 = &button1;
sw2 = &button2;
sw3 = &button3;
bootloader-led0 = &led0;
};
};
DevicetreeButton 1 on the nRF52833 DK is given the node name button_0
, which has the alias (sw0
) and node label (button0
) and is connected to &gpio0
, pin 11
. Remember, indexing in the devicetree files always starts from 0, which is why button 1 on the board is called button0
.
gpios = <&gpio0 11 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
DevicetreeIf the buttons are connected to a different GPIO port (e.g. GPIO_1
) than the LEDs, a new device pointer is required. Luckily, this is not the case for any official Nordic Semiconductor development kits.
1. Clone the nRF Connect SDK Fundamentals GitHub repository. We have two options here. We can clone the GitHub repository using the graphical user interface in VS Code (described in step 1.1) or the command line (described in step 1.2). Pick either 1.1 or 1.2.
1.1 Copy the link to the repository and use VS Code’s Command Palette to clone the repository.
Go to View -> Command Palette -> type Git Clone and paste in the repository link. Save the repo somewhere close to the root directory.
1.2 Or, create a folder close to your root directory and clone the repository by running the following command in nRF Connect Terminal.
git clone https://github.com/NordicDeveloperAcademy/ncs-fund.git
BashOnce you issue the command, the course code base will be cloned in the current working directory.
Ensure there are no spaces or other special characters in the path to the repository.
2. Open the exercise code base for this exercise in VS Code.
2.1 From the Welcome View in the nRF Connect extension, click on Open an existing application.
Select the base code for this exercise, found in ncs-fund/v2.8.x-v2.7.0/l2/l2_e1
, and click on Select Folder.
2.2 Open main.c
from the Explorer in VS Code as shown in the screenshot below:
3. Initialize the button on the hardware.
3.1 Get the node identifier for button 1 through its alias sw0
.
Recall from the Devicetree section, that the /aliases
node in the DK devicetree defined the alias sw0
for node &button0
. The line below uses the macro call DT_ALIAS()
to access the node identifier for the node through its alias.
In main.c
, search for STEP 3
.1
and add (copy and paste) the following lines:
#define SW0_NODE DT_ALIAS(sw0)
CThis is done to ensure compatibility across different hardware.
3.2 Get the device pointer, pin number and pin’s configuration flags through gpio_dt_spec
.
The GPIO API has the struct called gpio_dt_spec that encapsulates all this information, and can be retrieved using GPIO_DT_SPEC_GET()
.
In main.c
, search for STEP 3.2
and add (copy and paste) the following lines:
static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(SW0_NODE, gpios);
CThis line uses the macro GPIO_DT_SPEC_GET(
) to populate the members of the gpio_dt_spec
variable with:
4. It is important to verify that the device is ready to use by calling device_is_ready()
before using it.
In main.c
, search for STEP 4
and add (copy and paste) the following lines:
if (!device_is_ready(button.port)) {
return -1;
}
C5. Configure the pin connected to the button to be an input pin and set its hardware specifications.
Inside main()
, search for STEP 5
and add the following lines:
ret = gpio_pin_configure_dt(&button, GPIO_INPUT);
if (ret < 0) {
return -1;
}
C6. In the main loop of our exercise, we will indefinitely poll the CPU to read the status of the button (pressed = 1, unpressed = 0) and update the LED to the status of the button.
6.1 Read the status of the button and store it.
Using gpio_pin_get_dt()
, read the current status of button.pin
and save it in the variable val
.
Search for STEP 6.1
and add the following code inside the infinite loop:
bool val = gpio_pin_get_dt(&button);
C6.2 Update the LED to the status of the button
Update the LED to reflect the current status of the button that was saved in the variable val
in the previous step, using gpio_pin_set_dt()
.
Search for STEP 6.2
and add the following code inside the infinite loop:
gpio_pin_set_dt(&led,val);
C7. Change the sleep time from 1000
ms to 100
ms. 100
ms is about the right time to put the main thread to sleep and still be able to respond in time when the button is pressed.
8. Add a build configuration, like we did in Lesson 1 Exercise 2.
9. Build the exercise and flash it to the board as we have done in the previous lesson. Observe that when button 1 is pressed, LED1 is turned ON. (Remember on the nRF54L15 DK that would be button0 and LED0)
The solution for this exercise can be found in the GitHub repository, in l2/l2_e1_sol
of the directory v2.8.x-v2.7.0
In this exercise, we will modify the blinky example so that LED1 is turned on only when button 1 is being pressed, as shown in the illustration below.
To do this, we will use the polling method, as discussed in GPIO Generic API. This is done by continuously polling the CPU to check if the button was pressed and then update the LED accordingly. In Exercise 2 that follows, we will learn how to use GPIO interrupts, which is more power-efficient than polling.
If we recall the schematic of the nRF52833 DK, there are four push-buttons connected to the same GPIO peripheral as the LEDs, GPIO0
(node label: gpio0
). This can be seen in the GPIO pin mapping, for instance, notice that button 1 is connected to P0.11
. The 0 in P0
symbolizes it is &gpio0
.
This is why the same driver is needed for both the LEDs and buttons. This is also evident from the DK’s devicetree file nrf52833dk_nrf52833.dts
.
buttons {
compatible = "gpio-keys";
button0: button_0 {
gpios = <&gpio0 11 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
label = "Push button switch 0";
};
button1: button_1 {
gpios = <&gpio0 12 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
label = "Push button switch 1";
};
/* ... */
};
};
/* ... */
/* These aliases are provided for compatibility with samples */
aliases {
/* ... */
sw0 = &button0;
sw1 = &button1;
sw2 = &button2;
sw3 = &button3;
bootloader-led0 = &led0;
};
};
DevicetreeButton 1 on the nRF52833 DK is given the node name button_0
, which has the alias (sw0
) and node label (button0
) and is connected to &gpio0
, pin 11
. Remember, indexing in the devicetree files always starts from 0, which is why button 1 on the board is called button0
.
gpios = <&gpio0 11 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
DevicetreeIf the buttons are connected to a different GPIO port (e.g. GPIO_1
) than the LEDs, a new device pointer is required. Luckily, this is not the case for any official Nordic Semiconductor development kits.
1. Clone the nRF Connect SDK Fundamentals GitHub repository. We have two options here. We can clone the GitHub repository using the graphical user interface in VS Code (described in step 1.1) or the command line (described in step 1.2). Pick either 1.1 or 1.2.
1.1 Copy the link to the repository and use VS Code’s Command Palette to clone the repository.
Go to View -> Command Palette -> type Git Clone and paste in the repository link.
1.2 Or, create a folder close to your root directory and clone the repository by running the following command in nRF Connect Terminal.
git clone https://github.com/NordicDeveloperAcademy/ncs-fund.git
BashOnce you issue the command, the course code base will be cloned in the current working directory.
Ensure there are no spaces or other special characters in the path to the repository.
2. Open the exercise code base for this exercise in VS Code.
2.1 From the Welcome View in the nRF Connect extension, click on Open an existing application.
Select the base code for this exercise, found in ncs-fund/v2.6.2-v2.0.0/l2/l2_e1
, and click on Select Folder.
2.2 Open main.c
from the Explorer in VS Code as shown in the screenshot below:
3. Initialize the button on the hardware.
3.1 Get the node identifier for button 1 through its alias sw0
.
Recall from the Devicetree section, that the /aliases
node in the DK devicetree defined the alias sw0
for node &button0
. The line below uses the macro call DT_ALIAS()
to access the node identifier for the node through its alias.
In main.c
, search for STEP 3
.1
and add (copy and paste) the following lines:
#define SW0_NODE DT_ALIAS(sw0)
CThis is done to ensure compatibility across different hardware.
3.2 Get the device pointer, pin number and pin’s configuration flags through gpio_dt_spec
.
The GPIO API has the struct called gpio_dt_spec that encapsulates all this information, and can be retrieved using GPIO_DT_SPEC_GET()
.
In main.c
, search for STEP 3.2
and add (copy and paste) the following lines:
static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(SW0_NODE, gpios);
CThis line uses the macro GPIO_DT_SPEC_GET(
) to populate the members of the gpio_dt_spec
variable with:
4. It is important to verify that the device is ready to use by calling device_is_ready()
before using it.
In main.c
, search for STEP 4
and add (copy and paste) the following lines:
if (!device_is_ready(button.port)) {
return -1;
}
C5. Configure the pin connected to the button to be an input pin and set its hardware specifications.
Inside main()
, search for STEP 5
and add the following lines:
ret = gpio_pin_configure_dt(&button, GPIO_INPUT);
if (ret < 0) {
return -1;
}
C6. In the main loop of our exercise, we will indefinitely poll the CPU to read the status of the button (pressed = 1, unpressed = 0) and update the LED to the status of the button.
6.1 Read the status of the button and store it.
Using gpio_pin_get_dt()
, read the current status of button.pin
and save it in the variable val
.
Search for STEP 6.1
and add the following code inside the infinite loop:
bool val = gpio_pin_get_dt(&button);
C6.2 Update the LED to the status of the button
Update the LED to reflect the current status of the button that was saved in the variable val
in the previous step, using gpio_pin_set_dt()
.
Search for STEP 6.2
and add the following code inside the infinite loop:
gpio_pin_set_dt(&led,val);
C7. Change the sleep time from 1000
ms to 100
ms. 100
ms is about the right time to put the main thread to sleep and still be able to respond in time when the button is pressed.
8. Add a build configuration, like we did in Lesson 1 Exercise 2.
9. Build the exercise and flash it to the board as we have done in the previous lesson. Observe that when button 1 is pressed, LED1 is turned ON.
The solution for this exercise can be found in the GitHub repository, in l2/l2_1_sol
of the directory v2.6.2-v2.0.0
In this exercise, we will modify the blinky example so that LED1 is turned on only when button 1 is being pressed, as shown in the illustration below.
To do this, we will use the polling method, as discussed in GPIO Generic API. This is done by continuously polling the CPU to check if the button was pressed and then update the LED accordingly. In Exercise 2 that follows, we will learn how to use GPIO interrupts, which is more power-efficient than polling.
If we recall the schematic of the nRF52833 DK, there are four push-buttons connected to the same GPIO peripheral (GPIO_0
, aka: gpio0
) as the LEDs. This can be seen in the GPIO pin mapping. For example, notice that button 1 is connected to P0.11
. The 0 in P0
symbolizes it is GPIO_0
.
This is why the same driver, the GPIO_0
driver, is needed for both the LEDs and buttons. This is also evident from the DK’s devicetree file nrf52833dk_nrf52833.dts
.
buttons {
compatible = "gpio-keys";
<strong>button0: button_0 { </strong>
gpios = <&gpio0 11 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
label = "Push button switch 0";
};
button1: button_1 {
gpios = <&gpio0 12 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
label = "Push button switch 1";
};
/* ... */
};
};
/* ... */
/* These aliases are provided for compatibility with samples */
aliases {
/* ... */
sw0 = &button0;
sw1 = &button1;
sw2 = &button2;
sw3 = &button3;
bootloader-led0 = &led0;
};
};
Button 1 on the nRF52833 DK is given the node name button_0
, which has two aliases (sw0
and button0
) and is connected to GPIO_0
, pin 11
. Remember, indexing in the devicetree files always starts from 0, which is why button 1 on the board is called button0
.
gpios = <&gpio0 11 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Euismod in pellentesque massa placerat duis. Consectetur purus ut faucibus pulvinar elementum integer. Tempor nec feugiat nisl pretium fusce id velit. Sed sed risus pretium quam vulputate. Ultrices vitae auctor eu augue ut lectus arcu bibendum.
1. Clone the nRF Connect SDK Fundamentals GitHub repository.
1.1 Copy the link to the repository and use Vs Code’s Command Palette to clone the repository.
1.2 Or, create a folder close to your root directory and clone the repository by running
git clone https://github.com/NordicDeveloperAcademy/nRF-Connect-SDK-Fundamentals
2. Open the exercise code base for this exercise in VS Code.
2.1 From the Welcome View in the nRF Connect extension, click on Add an existing application.
Select the base code for this exercise, found in ncs-fund/v1.6.0-v1.9.1/l2/l2_e1
, and click on Select Folder.
Open main.c
from the Explorer in VS Code as shown in the screenshot below:
3. Define the symbol that will represent the button on the board. This is done by calling the appropriate devicetree APIs, same way as was done in the blinky
example.
In main.c
, search for STEP 3
and add (copy and paste) the following lines:
#define SW0_NODE DT_ALIAS(sw0)
#if DT_NODE_HAS_STATUS(SW0_NODE, okay)
#define SW0_GPIO_LABEL DT_GPIO_LABEL(SW0_NODE, gpios)
#define SW0_GPIO_PIN DT_GPIO_PIN(SW0_NODE, gpios)
#define SW0_GPIO_FLAGS DT_GPIO_FLAGS(SW0_NODE, gpios)
#else
#error "Unsupported board: sw0 devicetree alias is not defined"
#define SW0_GPIO_LABEL ""
#define SW0_GPIO_PIN 0
#define SW0_GPIO_FLAGS 0
#endif
4. Configure the pin connected to the button to be an input pin and set its hardware specifications.
Inside main()
, search for STEP 4
and add the following lines:
ret = gpio_pin_configure(dev, SW0_GPIO_PIN, GPIO_INPUT | SW0_GPIO_FLAGS);
if (ret < 0) {
return;
}
5. In the main loop of our exercise, we will indefinitely poll the CPU to read the status (pressed = 1 , unpressed = 0) of the button and update the LED to the status of the button.
Search for STEP 5
, add the following code inside the infinite loop:
bool val; //A variable that stores the status of the button (pressed = 1 , unpressed = 0)
val = gpio_pin_get(dev, SW0_GPIO_PIN); //Read the status of the button
gpio_pin_set(dev, PIN, val); //Update the LED to the status of the button
k_msleep(SLEEP_TIME_MS); // Put the CPU to sleep for 100ms so it does not consume power
6. Change the sleep time from 1000
ms to 100
ms. 100
ms is about the right time to put the main thread to sleep and still be able to respond in time when the button is pressed.
7. Add a build configuration, like we did in Lesson 1 Exercise 2.
8. Build the exercise and flash it to the board as we have done in the previous lesson. Observe that when button 1 is pressed, LED1 is turned ON.
The solution for this exercise can be found in the GitHub repository, in l2/l2_1_sol
of the directory v1.6.0-v1.9.1
.