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

low_power_pwm duty_cycle seems buggy.

I've been trying to figure out the duty cycle on the low_power_pwm and it looks pretty buggy to me (SDK v13.0.0). Some of the low_power_pwm code considers duty cycle to be a scale, and some of it considers it to be an absolute value.

The documentation for low_power_pwm_duty_set() says:

[in]	duty_cycle	New high pulse width. 0 means that the pin is always off. 255 means that it is always on.

So it seems to be a scale value. But then if you call low_power_pwm_duty_set with a value higher than the period, it returns an error. In the pwm_timeout_handler there is this code:

   if (duty_cycle == p_pwm_instance->period)    // Process duty cycle 100%
    {
        pin_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%
    {
        pin_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%
    {
        pin_on(p_pwm_instance);
        p_pwm_instance->timeout_ticks = ((duty_cycle * p_pwm_instance->period)>>8) + 
                            APP_TIMER_MIN_TIMEOUT_TICKS;
    }

This code considers a duty cycle equal to the period to be 100% on. But in the normal case, it calculates the on time as (duty_cycle * period) / 256 which uses duty_cycle as a scale value.

So for a period of 100 ticks and a duty cycle of 100, the pin will be on for 105 ticks. For a period of 100 ticks and a duty cycle of 99, the pin will be on for 43 ticks and then off for 5 ticks.

Also, I know it's documented as not accurate, but it seems like just always adding the 5 tick fudge factor to make sure it's above the minimum instead of comparing it and making sure it's above the minimum adds some needless inaccuracy.

Related