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

initial pulse while starting a PWM application

Hi,

A short summary, while using the app_PWM on our application I noticed an initial pulse on the PWM pin, its a 3V 1ms pulse that happens about 1 sec after powering on the nRF52832... 

The PWM configuration and initializations code is quite standard:

int main(void)

{
    initialize();
    // Initializing the PWM instance in main() function
    ret_code_t err_code;
    app_pwm_config_t pwm1_cfg = APP_PWM_DEFAULT_CONFIG_1CH(1000L, ON_OFF_LED);
    pwm1_cfg.pin_polarity[1] = APP_PWM_POLARITY_ACTIVE_LOW;
    err_code = app_pwm_init(&PWM1,&pwm1_cfg,pwm_ready_callback);
    app_pwm_enable(&PWM1);
    while ( app_pwm_channel_duty_set(&PWM1, 0, MIN_LIGHT_INTENSITY) == NRF_ERROR_BUSY);
    APP_ERROR_CHECK(err_code);

    execution_start(start);

Is there something I need to configure / disable / initialize on the PWM or the Startup sequence so I don't get this initial pulse? 

  • The good news is: I found the "problem":

    pwm1_cfg.pin_polarity[1] = APP_PWM_POLARITY_ACTIVE_LOW;

    that should be:

    pwm1_cfg.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_LOW;

    The bad news is that now all the logic behind my usage of the PWM is reversed... this was a question we had few weeks ago: https://devzone.nordicsemi.com/f/nordic-q-a/40002/pwm-library-issues/156496#156496 

    so before I rewrite all the logic of my application, is there any way to keep current implementation with:

    pwm1_cfg.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_HIGH;

    Without getting this initial pulse? I tracked down this to the app_pwm_enable(&PWM1);

    it doesn't help to invert 

    while ( app_pwm_channel_duty_set(&PWM1, 0, MIN_LIGHT_INTENSITY) == NRF_ERROR_BUSY);
    
    And
    app_pwm_enable(&PWM1);

    I tried:

    int main(void)
    
    {
        initialize();
        // Initializing the PWM instance in main() function
        ret_code_t err_code;
        app_pwm_config_t pwm1_cfg = APP_PWM_DEFAULT_CONFIG_1CH(1000L, ON_OFF_LED);
        pwm1_cfg.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_LOW;
        err_code = app_pwm_init(&PWM1,&pwm1_cfg,pwm_ready_callback);
    while ( app_pwm_channel_duty_set(&PWM1, 0, MIN_LIGHT_INTENSITY) == NRF_ERROR_BUSY); app_pwm_enable(&PWM1); APP_ERROR_CHECK(err_code); execution_start(start);

    But didn't help, when executing 

    app_pwm_enable(&PWM1);

    I get that initial pulse anyways...

  • Hi,

    The GPIO output pin is initially configured based on the pin polarity. So when you call app_pwm_init() with the polarity configuration set to APP_PWM_POLARITY_ACTIVE_LOW this will set the pin high. It will not change state until you call app_pwm_channel_duty_set(). If you want the default state to be low, you should use APP_PWM_POLARITY_ACTIVE_HIGH.

    I don't follow what you mean by logic being reversed. If you want to keep the same scale for duty cycle after changing polarity you could set the duty cycle as (100 - duty_cycle).

  • Hi,

    The question is not about polarity... its about an unwanted/ unexpected initial pulse... in short, there is an initial pulse when enabling a PWM even when set:  app_pwm_channel_duty_set(&PWM1, 0, 1000), as I mentioned I tried:

    int main(void) { initialize(); // Initializing the PWM instance in main() function ret_code_t err_code; app_pwm_config_t pwm1_cfg = APP_PWM_DEFAULT_CONFIG_1CH(1000L, ON_OFF_LED); pwm1_cfg.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_LOW; err_code = app_pwm_init(&PWM1,&pwm1_cfg,pwm_ready_callback);
    while ( app_pwm_channel_duty_set(&PWM1, 0, MIN_LIGHT_INTENSITY) == NRF_ERROR_BUSY); app_pwm_enable(&PWM1); APP_ERROR_CHECK(err_code); execution_start(start);

    And it still has that initial pulse... so it looks like the app_pwm_channel_duty_set dont work until the app_pwm_enable is called?

    About the logic being reversed, the initial code had a bug: instead of setting polarity on channel 0 it was setting the polarity on channel 1... that is not in use... I didn't catch that one until now... so all my dimming logic was written with the default polarity LOW... if I change the polarity now to HIGH I would need to rewrite the dimming logic, anyways... my question is: is there a way to keep the default active polarity (LOW) without that initial pulse? It looks like the app_pwm_channel_duty_set dont work if used before app_pwm_enable... in other words it seems we cant set the duty cycle and then enable the PWM?

  • I was not commenting on the problem where you mixed up the channels, as you wrote that you had solved it. Everything in my previous answer related to the initial pulse.

    What I attempted to describe was that the initial pulse is because during initialization the output pin is set to high if the pin polarity is configure APP_PWM_POLARITY_ACTIVE_LOW (and vise versa). It keeps that state until you configure a duty cycle. What you are seeing is not a bug, but is the behavior you should expect with the code you are using. Therefore I mentioned how you can get the behaviour (I think) you want by simply reversing the polarity in the initialization and reversing the duty cycle in your call to app_pwm_channel_duty_set(). That way you will not get the initial pulse.

  • Hi,

    When you say

    simply reversing the polarity in the initialization and reversing the duty cycle in your call to app_pwm_channel_duty_set()

    what it means is that I would need to reverse all my calls to app_pwm_duty_set()... in other words, I would need to reverse the whole dimming logic... thats what I meant...

    It keeps that state until you configure a duty cycle. What you are seeing is not a bug, but is the behavior you should expect with the code you are using.

    thats my question, so lets see, I do the configuration:

    app_pwm_config_t pwm1_cfg = APP_PWM_DEFAULT_CONFIG_1CH(1000L, ON_OFF_LED);

    Then set polarity:

    pwm1_cfg.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_LOW;

    Then initialization:

    err_code = app_pwm_init(&PWM1,&pwm1_cfg,pwm_ready_callback);

    Then I set the duty cycle:

    while ( app_pwm_channel_duty_set(&PWM1, 0, 1000) == NRF_ERROR_BUSY);

    And finally I enable the PWM:

    app_pwm_enable(&PWM1);

    And then the PWM is at 100%? shouldn't the set instruction set the PWM to 0%? and when enabling the PWM should be 0%?

Related