Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Frequency not read for nrfx PWM peripheral in WaveForm mode

Dear Sirs,

SDK: NCS version 1.6.0

Board: nrf5340 DK

IDE: SES Nordic Edition V5.50c

Compiled in application core cpuappns

I am a beginner with nrf programming trying to learn how to use the PWM peripheral through the nrfx drivers.

Normal PWM modes seems to work but I have not been able to make the PWM WaveForm mode work.

For some reason, the counter_top value seems to be ignored and thereby I cannot define the frequency.

In the attached example (which is condesed but should compile), the frequency is set at approx 1kHz (a counter_top value of 1000) despite trying to define it to 10kHz and I am unable to define it otherwise.

The duty cycle is read as expected though. Also the .top_value in config0 is ignored in this mode as expected.

Any idea what could be the reason?

/**
 * Simple program to drive LED0 on the nrf5340 evaluation board using the nrfx driver for lower level access
 * Jonas Forssell
 */

#include <stdio.h>
#include <string.h>
#include <nrfx_pwm.h>
#include <zephyr.h>

// Use Zephyr macro to get access to the LED0 on the board
#define OUTPUT_PIN DT_GPIO_PIN(DT_ALIAS(led0), gpios)

// Use nrfx to create a PWM instance which we will connect to the LED0 later
static nrfx_pwm_t m_pwm0 = NRFX_PWM_INSTANCE(0);

// Declare variables holding PWM sequence values. In this example only one channel is used 
// We start off with a counter to 50 and a top value of 100 giving a 50% duty cyle.
nrf_pwm_values_wave_form_t seq_values[] = {50, 0, 0, 100};

nrf_pwm_sequence_t const seq =
{
    .values.p_wave_form = seq_values,
    .length          = NRF_PWM_VALUES_LENGTH(seq_values),
    .repeats         = 0,
    .end_delay       = 0
};


nrfx_pwm_config_t const config0 =
    {
        .output_pins =
        {
            OUTPUT_PIN,                        // channel 0 now connected to LED0
            NRFX_PWM_PIN_NOT_USED,             // channel 1
            NRFX_PWM_PIN_NOT_USED,             // channel 2
            NRFX_PWM_PIN_NOT_USED,             // channel 3
        },
        .irq_priority = NRFX_PWM_DEFAULT_CONFIG_IRQ_PRIORITY,
        .base_clock   = NRF_PWM_CLK_1MHz,       // Here we select which prescaler to use
        .count_mode   = NRF_PWM_MODE_UP,
        .top_value    = 100,                    // This is ignored when in wave form mode
        .load_mode    = NRF_PWM_LOAD_WAVE_FORM,
        .step_mode    = NRF_PWM_STEP_AUTO
    };

int main(void) {

// Init PWM without error handler
nrfx_pwm_init(&m_pwm0, &config0, NULL, NULL);

// Set and start
nrfx_pwm_simple_playback(&m_pwm0, &seq, 1, NRFX_PWM_FLAG_LOOP);

while(1) 
    k_msleep(3000);

}

I am also a bit puzzled by the naming of the library defaults.

Some of them starts with nrfx as expected which many of the values and types maintain the old nrf definitions. Perhaps the porting of the SKD from nrf to nrfx is still in progress?

Most grateful for any assistance.

Parents
  • Thank you for your reply Jared.
    Would you mind posting your modified code that you tried so that I can replicate this on my board and oscilloscope?

    I have measured the PWM signal on pin 28 which also is connected to the LED.

  • #include <stdio.h>
    #include <string.h>
    #include <nrfx_pwm.h>
    #include <zephyr.h>
    
    // Use Zephyr macro to get access to the LED0 on the board
    //#define OUTPUT_PIN DT_GPIO_PIN(DT_ALIAS(led0), gpios)
    
    // Use nrfx to create a PWM instance which we will connect to the LED0 later
    static nrfx_pwm_t m_pwm0 = NRFX_PWM_INSTANCE(0);
    
    // Declare variables holding PWM sequence values. In this example only one channel is used 
    // We start off with a counter to 50 and a top value of 100 giving a 50% duty cyle.
    nrf_pwm_values_wave_form_t seq_values[] = {50, 0, 0, 100};
    
    nrf_pwm_sequence_t const seq =
    {
        .values.p_wave_form = seq_values,
        .length          = NRF_PWM_VALUES_LENGTH(seq_values),
        .repeats         = 0,
        .end_delay       = 0
    };
    
    
    nrfx_pwm_config_t const config0 =
        {
            .output_pins =
            {
                4,                        // channel 0 now connected to LED0
                NRFX_PWM_PIN_NOT_USED,             // channel 1
                NRFX_PWM_PIN_NOT_USED,             // channel 2
                NRFX_PWM_PIN_NOT_USED,             // channel 3
            },
            .irq_priority = NRFX_PWM_DEFAULT_CONFIG_IRQ_PRIORITY,
            .base_clock   = NRF_PWM_CLK_1MHz,       // Here we select which prescaler to use
            .count_mode   = NRF_PWM_MODE_UP,
            .top_value    = 100,                    // This is ignored when in wave form mode
            .load_mode    = NRF_PWM_LOAD_WAVE_FORM,
            .step_mode    = NRF_PWM_STEP_AUTO
        };
    
    int main(void) {
    
    // Init PWM without error handler
    nrfx_pwm_init(&m_pwm0, &config0, NULL, NULL);
    
    // Set and start
    nrfx_pwm_simple_playback(&m_pwm0, &seq, 1, NRFX_PWM_FLAG_LOOP);
    
    while(1) 
        k_msleep(3000);
    
    }

Reply
  • #include <stdio.h>
    #include <string.h>
    #include <nrfx_pwm.h>
    #include <zephyr.h>
    
    // Use Zephyr macro to get access to the LED0 on the board
    //#define OUTPUT_PIN DT_GPIO_PIN(DT_ALIAS(led0), gpios)
    
    // Use nrfx to create a PWM instance which we will connect to the LED0 later
    static nrfx_pwm_t m_pwm0 = NRFX_PWM_INSTANCE(0);
    
    // Declare variables holding PWM sequence values. In this example only one channel is used 
    // We start off with a counter to 50 and a top value of 100 giving a 50% duty cyle.
    nrf_pwm_values_wave_form_t seq_values[] = {50, 0, 0, 100};
    
    nrf_pwm_sequence_t const seq =
    {
        .values.p_wave_form = seq_values,
        .length          = NRF_PWM_VALUES_LENGTH(seq_values),
        .repeats         = 0,
        .end_delay       = 0
    };
    
    
    nrfx_pwm_config_t const config0 =
        {
            .output_pins =
            {
                4,                        // channel 0 now connected to LED0
                NRFX_PWM_PIN_NOT_USED,             // channel 1
                NRFX_PWM_PIN_NOT_USED,             // channel 2
                NRFX_PWM_PIN_NOT_USED,             // channel 3
            },
            .irq_priority = NRFX_PWM_DEFAULT_CONFIG_IRQ_PRIORITY,
            .base_clock   = NRF_PWM_CLK_1MHz,       // Here we select which prescaler to use
            .count_mode   = NRF_PWM_MODE_UP,
            .top_value    = 100,                    // This is ignored when in wave form mode
            .load_mode    = NRF_PWM_LOAD_WAVE_FORM,
            .step_mode    = NRF_PWM_STEP_AUTO
        };
    
    int main(void) {
    
    // Init PWM without error handler
    nrfx_pwm_init(&m_pwm0, &config0, NULL, NULL);
    
    // Set and start
    nrfx_pwm_simple_playback(&m_pwm0, &seq, 1, NRFX_PWM_FLAG_LOOP);
    
    while(1) 
        k_msleep(3000);
    
    }

Children
Related