This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Please give me advice on nrf pwm driver.

I want a waveform as below for motor control.
I am trying to create this using nrf pwm driver.

I set the pwm sequence as below and checked the output.
2nd duty repeat does not work.

I added an unused 3rd dummy duty (line 91).
It seems to be working well.

However, increasing the playback count to 2 introduces a delay between the outputs.

What should I do to get the waveform I want?
Give me advice .
Thanks.

Parents
  • I want a waveform as below for motor control.
    I am trying to create this using nrf pwm driver.


    I set the pwm sequence as below and checked the output.
    2nd duty repeat does not work.


    I added an unused 3rd dummy duty (line 91).
    It seems to be working well.


    However, increasing the playback count to 2 introduces a delay between the outputs.


    What should I do to get the waveform I want?
    Give me advice .
    Thanks.

  • Hi,

    Have you tried passing NRF_DRV_PWM_FLAG_LOOP to nrf_drv_pwm_simple_playback()? Could you also share your code?

    regards

    Jared

  • Hi there,

    Would you mind sharing a minimal example that can be flashed on a DK that highlights the issue? It would make it much easier for me to understand the issue if I could reproduce it at my side. 

    regards

    Jared 

  • #include <stdio.h>
    #include <string.h>
    #include "nrf_drv_pwm.h"
    #include "app_util_platform.h"
    #include "app_error.h"
    #include "boards.h"
    #include "bsp.h"
    #include "app_timer.h"
    #include "nrf_drv_clock.h"
    #include "nrf_delay.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    static nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0);
    
    #define PERIOD 1000
    
    #define DUTY		75
    #define HIGH		(PERIOD * (100 - DUTY) / 100)
    #define LOW			PERIOD
    
    static nrf_pwm_values_individual_t /*const*/ seq_values[] =
    {
    	{HIGH, LOW, LOW, LOW},
    	{LOW, HIGH, LOW, LOW},
    };
    nrf_pwm_sequence_t const seq =
    {
    	.values.p_individual = seq_values,
    	.length              = NRF_PWM_VALUES_LENGTH(seq_values),
    	.repeats             = 4
    	,
    	.end_delay           = 0
    };
    
    static void demo(void)
    {
        nrf_drv_pwm_config_t const config0 =
        {
            .output_pins =
            {
                24,
                25,
                NRFX_PWM_PIN_NOT_USED,
                NRFX_PWM_PIN_NOT_USED
            },
            .irq_priority = APP_IRQ_PRIORITY_LOWEST,
            .base_clock   = NRF_PWM_CLK_1MHz,
            .count_mode   = NRF_PWM_MODE_UP,
    		.top_value    = 1000,
            .load_mode    = PWM_DECODER_LOAD_Individual,
            .step_mode    = NRF_PWM_STEP_AUTO
        };
        APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm0, &config0, NULL));
    }
    
    
    void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info)
    {
        app_error_save_and_stop(id, pc, info);
    }
    
    int main(void)
    {
    
    	demo();
    	
        for (;;)
        {
    		(void)nrf_drv_pwm_simple_playback(&m_pwm0, &seq, 1, NRFX_PWM_FLAG_STOP);
    
    		nrf_delay_ms(1000);
        }
    }



    Code and output waveform

  • Hi there,

    Although it's not well explained in the product specification, the PWM peripheral has a limitation in that it will stop the execution of a sequence too early. Some effort has been done to explain it in some part in this thread

    Nevertheless, the best way for your use case is to something like this:

    #include <stdio.h>
    #include <string.h>
    #include "nrf_drv_pwm.h"
    #include "app_util_platform.h"
    #include "app_error.h"
    #include "boards.h"
    #include "bsp.h"
    #include "app_timer.h"
    #include "nrf_drv_clock.h"
    #include "nrf_delay.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    static nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0);
    
    #define PERIOD 1000
    
    #define DUTY		75
    #define HIGH		(PERIOD * (100 - DUTY) / 100) //250
    #define LOW			PERIOD //1000 
    
    static nrf_pwm_values_individual_t /*const*/ seq_values[] =
    {
        
    	{HIGH, LOW, LOW, LOW},
    	{HIGH, LOW, LOW, LOW},
        {HIGH, LOW, LOW, LOW},
        {HIGH, LOW, LOW, LOW},
        {LOW, HIGH, LOW, LOW},
        {LOW, HIGH, LOW, LOW},
        {LOW, HIGH, LOW, LOW},
        {LOW, HIGH, LOW, LOW},
    };
    nrf_pwm_sequence_t const seq =
    {
    	.values.p_individual = seq_values,
    	.length              = NRF_PWM_VALUES_LENGTH(seq_values),
    	.repeats             = 0
    	,
    	.end_delay           = 0
    };
    
    static void demo(void)
    {
        nrf_drv_pwm_config_t const config0 =
        {
            .output_pins =
            {
                3,
                4,
                NRFX_PWM_PIN_NOT_USED,
                NRFX_PWM_PIN_NOT_USED
            },
            .irq_priority = APP_IRQ_PRIORITY_LOWEST,
            .base_clock   = NRF_PWM_CLK_1MHz,
            .count_mode   = NRF_PWM_MODE_UP,
    		.top_value    = 1000,
            .load_mode    = PWM_DECODER_LOAD_Individual,
            .step_mode    = NRF_PWM_STEP_AUTO
        };
        APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm0, &config0, NULL));
    }
    
    
    void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info)
    {
        app_error_save_and_stop(id, pc, info);
    }
    
    int main(void)
    {
    
    	demo();
    	
        for (;;)
        {
    		(void)nrf_drv_pwm_simple_playback(&m_pwm0, &seq, 4 , NRFX_PWM_FLAG_STOP);
    
    		nrf_delay_ms(1000);
        }
    }

    Note, I changed the pins so you should probably change them back ;)

    Instead of using the repeat, I hardcoded the sequence pattern and use the playback_count parameter to nrfx_pwm_simple_playback() to decide the number of times the pattern should be repeated. Here is a trace from the logic analyzer with playback_count set to 4:

    best regards
    Jared
  • In the example code I posted, repeat is set to a constant 4.
    But in my actual application repeat needs to depend on external settings.
    In this case, the sequence cannot be pre-coded.
    Any other options?

Reply Children
No Data
Related