Updating PWM sequence in NCS using nrfx driver

Hi,

I am working on nrf52840DK with NCS v2.7.0. I want to send the data to the addressable led strip using the pwm interface.

I am using the NRF PWM driver (nrfx_pwm) in my project, and I am encountering an issue with missing events when operating at high frequencies. I need to update the sequence values dynamically upon receiving interrupts for NRFX_PWM_EVT_END_SEQ0 and NRFX_PWM_EVT_END_SEQ1

If I try to update the sequence values when frequency is at 1KHz, everything works as expected.

What is the recommended way to update sequence values dynamically without risking missed events or glitches at such high frequencies?

Are there additional steps or configurations I should check to resolve this?

  • Hi,

    The dequence pointers are double buffered, so there should normally not be a problem with higher data rate either. That said, LED strip control is often doen usint the I2S peripheral which while not designed for it, is well suited.

  • I know it should work and same thing is working on nrf52832 with sdk13. So it should work with nrf52840 with NCS.

    But strange thing is I am not even getting the sequence completion interrupt when I increase the frequency.

    Sharing the example code I am using and the output I am getting

    #include <zephyr/kernel.h>
    #include <nrfx_pwm.h>
    #include <hal/nrf_gpio.h> // Required for NRF_GPIO_PIN_MAP
    
    #define PWM_OUTPUT_PIN  NRF_GPIO_PIN_MAP(1, 13) // Port 1, Pin 13
    #define LED0_PIN        NRF_GPIO_PIN_MAP(0, 13) // LED1 pin
    #define LED1_PIN        NRF_GPIO_PIN_MAP(0, 14) // LED1 pin
    #define LED2_PIN        NRF_GPIO_PIN_MAP(0, 15) // LED1 pin
    
    #define PWM_TOP_VALUE               1000
    #define PWM_INST_IDX                0
    #define DIGITAL_BYTES_PER_WRITE     24
    #define MULTIPLY_FACTOR             1
    
    static nrfx_pwm_t pwm_instance = NRFX_PWM_INSTANCE(0);
    static nrf_pwm_values_common_t pwm_values[DIGITAL_BYTES_PER_WRITE * MULTIPLY_FACTOR] = {
        [0 ... (DIGITAL_BYTES_PER_WRITE * MULTIPLY_FACTOR) - 1] = PWM_TOP_VALUE / 2
    };
    
    static nrf_pwm_sequence_t pwm_seq0 = {
        .values.p_common = pwm_values,
        .length = NRF_PWM_VALUES_LENGTH(pwm_values),
        .repeats = 0,
        .end_delay = 0,
    };
    
    static nrf_pwm_sequence_t pwm_seq1 = {
        .values.p_common = pwm_values,
        .length = NRF_PWM_VALUES_LENGTH(pwm_values),
        .repeats = 0,
        .end_delay = 0,
    };
    
    static void pwm_interrupt_callback(nrfx_pwm_evt_type_t event_type, void *context) {
        if (event_type == NRFX_PWM_EVT_END_SEQ0) {
            printf("NRFX_PWM_EVT_END_SEQ0 triggered\n");
        }
        if (event_type == NRFX_PWM_EVT_END_SEQ1) {
            printf("NRFX_PWM_EVT_END_SEQ1 triggered\n");
        }
    }
    
    void main(void)
    {
        nrfx_pwm_config_t pwm_config = NRFX_PWM_DEFAULT_CONFIG(PWM_OUTPUT_PIN, LED0_PIN, LED1_PIN,LED2_PIN);
        //pwm_config.base_clock = NRF_PWM_CLK_16MHz;
        pwm_config.output_pins[0] = PWM_OUTPUT_PIN;
        pwm_config.top_value = PWM_TOP_VALUE;
    
     #if defined(__ZEPHYR__)
        IRQ_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_PWM_INST_GET(PWM_INST_IDX)), IRQ_PRIO_LOWEST,
                    NRFX_PWM_INST_HANDLER_GET(PWM_INST_IDX), 0, 0);
    #endif
    
       if (nrfx_pwm_init(&pwm_instance, &pwm_config, pwm_interrupt_callback, NULL) != NRFX_SUCCESS) {
            printk("PWM initialization failed\n");
            return;
        }
    
        printk("PWM initialized\n");
        nrfx_pwm_complex_playback(&pwm_instance, &pwm_seq0, &pwm_seq1, 8, 
                NRFX_PWM_FLAG_SIGNAL_END_SEQ0 | NRFX_PWM_FLAG_SIGNAL_END_SEQ1 | NRFX_PWM_FLAG_STOP);
        while (1) {
            k_sleep(K_MSEC(5000));
        }
    }

    For this I am getting following output

    [2024-12-13 19:12:39.341] *** Booting nRF Connect SDK v2.7.0-5cb85570ca43 ***
    [2024-12-13 19:12:39.344] *** Using Zephyr OS v3.6.99-100befc70c74 ***
    [2024-12-13 19:12:39.348] PWM initialized
    [2024-12-13 19:12:39.374] NRFX_PWM_EVT_END_SEQ0 triggered
    [2024-12-13 19:12:39.398] NRFX_PWM_EVT_END_SEQ1 triggered
    [2024-12-13 19:12:39.422] NRFX_PWM_EVT_END_SEQ0 triggered
    [2024-12-13 19:12:39.446] NRFX_PWM_EVT_END_SEQ1 triggered
    [2024-12-13 19:12:39.469] NRFX_PWM_EVT_END_SEQ0 triggered
    [2024-12-13 19:12:39.493] NRFX_PWM_EVT_END_SEQ1 triggered
    [2024-12-13 19:12:39.517] NRFX_PWM_EVT_END_SEQ0 triggered
    [2024-12-13 19:12:39.541] NRFX_PWM_EVT_END_SEQ1 triggered
    [2024-12-13 19:12:39.565] NRFX_PWM_EVT_END_SEQ0 triggered
    [2024-12-13 19:12:39.589] NRFX_PWM_EVT_END_SEQ1 triggered
    [2024-12-13 19:12:39.613] NRFX_PWM_EVT_END_SEQ0 triggered
    [2024-12-13 19:12:39.637] NRFX_PWM_EVT_END_SEQ1 triggered
    [2024-12-13 19:12:39.661] NRFX_PWM_EVT_END_SEQ0 triggered
    [2024-12-13 19:12:39.685] NRFX_PWM_EVT_END_SEQ1 triggered
    [2024-12-13 19:12:39.709] NRFX_PWM_EVT_END_SEQ0 triggered
    [2024-12-13 19:12:39.733] NRFX_PWM_EVT_END_SEQ1 triggered

    Now if I change the PWM_TOP_VALUE to 28 and set the clock to 16MHz, I am getting following output

    [2024-12-13 19:13:33.322] *** Booting nRF Connect SDK v2.7.0-5cb85570ca43 ***
    [2024-12-13 19:13:33.326] *** Using Zephyr OS v3.6.99-100befc70c74 ***
    [2024-12-13 19:13:33.330] PWM initialized
    [2024-12-13 19:13:33.332] NRFX_PWM_EVT_END_SEQ0 triggered
    [2024-12-13 19:13:33.335] NRFX_PWM_EVT_END_SEQ0 triggered
    [2024-12-13 19:13:33.337] NRFX_PWM_EVT_END_SEQ1 triggered

    In My understanding this should have worked but not sure what is wrong in this.

    Please let me know if I have configured something incorrectly or what changes should I do to make it work.

  • Hi,

    I am sorry for the delay. Continuing in your private support ticket for now as that has updated information.

Related