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

PWM Resolution in app_pwm.c

Hi all,

I was looking into using a PWM for LED dimming, and in an attempt to smooth out transitions between light states, I found that there was visible flicker as the internal LED value was quantized to the 0-100% PWM duty cycle.

Fortunately, since the PWM duty cycle was implemented as a uint16_t, I was able to change the following lines to improve PWM resolution -

uint32_t app_pwm_channel_duty_set(app_pwm_t const * const p_instance,
                                  uint8_t channel, app_pwm_duty_t duty)
{
    uint32_t ticks = (nrf_drv_timer_capture_get(p_instance->p_timer,
                      (nrf_timer_cc_channel_t) PWM_MAIN_CC_CHANNEL) * (uint32_t)duty) / **1000UL**;
    return app_pwm_channel_pulsewidth_ticks_set(p_instance, channel, ticks);
}


app_pwm_duty_t app_pwm_channel_duty_get(app_pwm_t const * const p_instance, uint8_t channel)
{
    uint32_t value = (nrf_drv_timer_capture_get(p_instance->p_timer,
                                                (nrf_timer_cc_channel_t)(channel)) * **1000UL**) \
                     / nrf_drv_timer_capture_get(p_instance->p_timer,
                                                 (nrf_timer_cc_channel_t) PWM_MAIN_CC_CHANNEL);

    return (app_pwm_duty_t)value;
}

While this works for my application, I was wondering -

  1. Are there any technical reasons why the duty cycle was limited to 0-100 while the allocated space was 16bit (and then casted to 32bit anyway?) Seems like one would use a uint8_t then.
  2. Was it removed to solve any errata I am missing?
  3. If none of the above, would it be possible to implement maybe a PWM units enumeration to allow someone to use a higher-resolution PWM duty? I would prefer to avoid using a modified SDK.

Thanks, -Alex

Related