In this exercise, we will use a generated PWM signal to control an LED on the DK.
You will practice using the PWM API in nRF Connect SDK to initialize a PWM device and learn how changing the PWM period and pulse affects the behavior of the LED.
This exercise will show you how to use Zephyrs API to get and use a predefined pwm compatible node.
Open the code base of the exercise by navigating to Create a new application in the nRF Connect for VS Code extension, select Copy a sample, and search for Lesson 4 – Exercise 1.
Alternatively, in the GitHub repository for this course, go to the base code for this exercise, found in lesson4/inter_less4_exer1.
1. Enable the PWM module in your application.
1.1 Enable the PWM module and set the logging level.
Add the following lines to the prj.conf
file
CONFIG_PWM=y
CONFIG_PWM_LOG_LEVEL_DBG=y
KconfigCONFIG_PWM
– Enables config options for PWM driversCONFIG_PWM_LOG_LEVEL_DBG
– Sets log level for the PWM log module1.2 Enable LED and LED PWM.
Add the following lines to the prj.conf
file
CONFIG_LED=y
CONFIG_LED_PWM=y
KconfigCONFIG_LED
– Includes the LED driversCONFIG_LED_PWM
– Enables driver for PWM LEDs1.3 Include the relevant PWM header files
Add the following lines in main.c
#include <zephyr/device.h>
#include <zephyr/drivers/pwm.h>
C2. Define the desired PWM period and pulse
Define the PWM period and pulse, as the macros PWM_PERIOD_NS
and PWM_PULSE_NS
Add the following lines to main.c
#define PWM_PERIOD_NS 20000000
#define PWM_DUTY_CYCLE 1400000
C3. Initialize the PWM LED device on the hardware.
3.1 Get the node identifier through its alias pwm_led0
.
Using DT_ALIAS()
, which takes an alias and returns the device’s node identifier.
#define PWM_LED0 DT_ALIAS(pwm_led0)
C3.2 Initialize and populate the struct pwm_dt_spec
using PWM_DT_SPEC_GET()
.
We want to get the device pointer, pin number, and pin configuration flags through pwm_dt_spec
. This can be done using the API-specific PWM_DT_SPEC_GET()
, which takes the node identifier, and populates the struct pwm_dt_spec
with the information from that device.
static const struct pwm_dt_spec pwm_led0 = PWM_DT_SPEC_GET(PWM_LED0);
C3.3 Check if the device is busy.
Now we need to verify if the device is ready to use, using pwm_is_ready_dt()
, which has the following signature
Add the following code snippet in main.c
if (!pwm_is_ready_dt(&pwm_led0)) {
LOG_ERR("Error: PWM device %s is not ready\n", pwm_led0.dev->name);
return 0;
}
C4. Control the LED with the control signal generated from the PWM.
We will use pwm_set_dt()
to set the period and pulse width of the device after initializing it.
Add the following code snippet in main.c
err = pwm_set_dt(&pwm_led0, PWM_PERIOD_NS, PWM_DUTY_CYCLE);
if (err) {
LOG_ERR("Error in pwm_set_dt(), err: %d", err);
return 0;
}
C5. Build and flash the application to your device.
LED1 on your device should glow slightly.
Try changing the pulse and/or period and observe the changes. If the value is set too high or too low, it may be out of range of what your hardware can reach.
For instance, let’s set the parameters to
#define PWM_PERIOD_NS 100000000
#define PWM_DUTY_CYCLE 14000000
CNotice that the LED is now blinking very quickly.
The solution for this exercise can be found in the GitHub repository, lesson4/ncs-inter_less4_exer1_solution
.