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

nrf_pwm library questions

I don't understand how the numbers in the nrf_pwm_init are calculated. Specifically these:

case PWM_MODE_LED_100:   // 0-100 resolution, 321Hz PWM frequency, 32kHz timer frequency (prescaler 9)
    PWM_TIMER->PRESCALER = 9; 
    pwm_max_value = 100;
    break;
case PWM_MODE_LED_255:   // 8-bit resolution, 122Hz PWM frequency, 32kHz timer frequency (prescaler 9)
    PWM_TIMER->PRESCALER = 9;
    pwm_max_value = 255;  
    break;
case PWM_MODE_LED_1000:  // 0-1000 resolution, 250Hz PWM frequency, 250kHz timer frequency (prescaler 6)
    PWM_TIMER->PRESCALER = 6;
    pwm_max_value = 1000;
    break;
case PWM_MODE_MTR_100:   // 0-100 resolution, 20kHz PWM frequency, 2MHz timer frequency (prescaler 3)
    PWM_TIMER->PRESCALER = 3;
    pwm_max_value = 100;
    break;
case PWM_MODE_MTR_255:    // 8-bit resolution, 31kHz PWM frequency, 8MHz timer frequency (prescaler 1)	
    PWM_TIMER->PRESCALER = 1;
    pwm_max_value = 255;
    break;
case PWM_MODE_BUZZER_255:  // 8-bit resolution, 62.5kHz PWM frequency, 16MHz timer frequency (prescaler 0)
    PWM_TIMER->PRESCALER = 0;
    pwm_max_value = 255;
    break;

If I wanted to drive an led with a pwm frequency of 1000Hz with 0-100 for the duty-cycle %, how do I do it?

How is the timer frequency chosen?

Can it be done using the external 32768Hz clock to save power?

Thanks.

  • Frequency (Hz) = 16,000,000 / ( 2 ^ prescalar ) / ( pwm_max_value + 1 )
    

    I think the first one is wrong, it's 312Hz according to my calculation, not 321Hz

    Turning the formula around, if you wanted 1000Hz with a 0-100 duty cycle then prescalar would have to be 7.3, but you can't have a fractional prescalar so you'd use the next lower at 7 and you'd then have to have pwm_max_value = 124 to get 1000Hz

    16,000,000 / ( 2 ^ 7 ) / ( 124 + 1 ) == 1000
    

    and you'd take the 0-100 duty cycle you wanted and multiply by 1.24 to get the pwm value to use, eg 50% duty would be 62.

    You can't use the RTC if you want every value of duty cycle between 0 and 100%, for that you need an underlying frequency of steps x 1000 = 100,000Hz which is bigger than 32.768kHz. If you can live with just 32 steps between 0 and 100% duty, you could use RTC. However, since you'd be using PPI, I believe that uses the HFCLK anyway so either you have to have that running (constant latency) or it'll be turned on and off every cycle (low power) and you'll get the startup current cost 2000 times a second plus some variable latency .. so it may not be worth it.

Related