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

Low-power PWM library: PWM doesnt stop if low_power_pwm_stop is called from handler. Is this a bug?

I am using SDK 12.0.0.

I am working with low_power_pwm_init() to initialise the pwm and I have passed a handler while initialising. I want to stop the pwm from the handler hence I am calling low_power_pwm_stop() from the handler. I observe that the pwm doesnt stop.

I tried to investigate the reason for this and found that pwm_timeout_handler() in low_power_pwm.c is restarting the pwm. Below is the snippet that is suspect.

if (p_pwm_instance->pwm_state == NRF_DRV_STATE_INITIALIZED)
{
    p_pwm_instance->pwm_state = NRF_DRV_STATE_POWERED_ON;
    err_code = app_timer_start(*p_pwm_instance->p_timer_id, p_pwm_instance->timeout_ticks, p_pwm_instance);
    APP_ERROR_CHECK(err_code);
}

In low_power_pwm_stop(), p_pwm_instance->pwm_state is assigned NRF_DRV_STATE_INITIALIZED and in the above snippet the timer is started if the driver state is NRF_DRV_STATE_INITIALIZED, causing the pwm to be ON again.

Is this a bug?

  • Hi,

    I can see that this will be the case and will report it internally.

    You can set a flag in the event handler and call the stop routine in main.

    Ole

  • FormerMember
    +1 FormerMember

    I modified the low_power_pwm.c to fix.

    static void pwm_timeout_handler(void * p_context)
    {
        ret_code_t err_code;
        uint8_t duty_cycle;
    
        low_power_pwm_t * p_pwm_instance = (low_power_pwm_t *)p_context;
    
        if (p_pwm_instance->evt_type == LOW_POWER_PWM_EVENT_PERIOD)
        {
            duty_cycle = p_pwm_instance->duty_cycle;
    
            if (duty_cycle == p_pwm_instance->period)    // Process duty cycle 100%
            {
                led_on(p_pwm_instance);
                p_pwm_instance->timeout_ticks = p_pwm_instance->period + APP_TIMER_MIN_TIMEOUT_TICKS;
            }
            else if (duty_cycle == 0)   // Process duty cycle 0%
            {
                led_off(p_pwm_instance);
                p_pwm_instance->timeout_ticks = p_pwm_instance->period + APP_TIMER_MIN_TIMEOUT_TICKS;
            }
            else // Process any other duty cycle than 0 or 100%
            {
                led_on(p_pwm_instance);
                p_pwm_instance->timeout_ticks = ((duty_cycle * p_pwm_instance->period)>>8) +
                                    APP_TIMER_MIN_TIMEOUT_TICKS;
                // setting next state
                p_pwm_instance->evt_type = LOW_POWER_PWM_EVENT_DUTY_CYCLE;
            }
    
            if (p_pwm_instance->handler)
            {
                p_pwm_instance->handler(p_pwm_instance);
            }
        }
        else
        {
            led_off(p_pwm_instance);
            p_pwm_instance->evt_type = LOW_POWER_PWM_EVENT_PERIOD;
            p_pwm_instance->timeout_ticks = (((p_pwm_instance->period - p_pwm_instance->duty_cycle) * p_pwm_instance->period)>>8) +
                                      APP_TIMER_MIN_TIMEOUT_TICKS;
        }
    
        if (p_pwm_instance->pwm_state == NRF_DRV_STATE_POWERED_ON)
        {
            err_code = app_timer_start(*p_pwm_instance->p_timer_id, p_pwm_instance->timeout_ticks, p_pwm_instance);
            APP_ERROR_CHECK(err_code);
        }
    }
    

    I hope it helps you.

Related