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

Reasoning behind nrf51-pwm-library implementation

FormerMember
FormerMember

Greetings,

Kudos for implementing a no glitch version of PWM with and without using timeslot.

github.com/.../nrf_pwm_noglitch.c.

Could the reasoning for the following be explained with the above PWM driver:

  • Why is pwm_max_value and pwm_value multiplied by 2 used for the timer instead of just these values?
  • Disabling of the PPI channels done in the IRQ routine? Could waiting for 1.5 or 2 times the PWM cycle work?

Also does this implementation have the infamous bug of the polarity inverting at times as mentioned in other posts in this forum? Thanks!

  • Hi

    Not yet sure about the two first questions that you ask. For your last question, this thread provides some reasoning for why the signal would flip and how to avoid it.

  • Thanks! This helps clear some stuff up. I'm looking for PWM for a max value of 1023 and with no prescalar of TIMER. This would result in ~15 kHz freq of PWM signal, but with the multiplication of 2 (question 1), the PWM freq reduces to ~7 kHz. Since the PWM freq is still below 64kHz limit mentioned in the link you sent, what is the reason that this is done?

    I have changed the code where the multiplying by 2 is not done and the PWM gets messed up. I still can't get my head around why though.

  • Updates from digging in: If I make sure that all the values that I pass to nrf_pwm_set_value is an even number it works well without multiplying pwm_max_value and pwm_value by two. Next step, figuring out why nrf_pwm_set_value can't handle odd numbers.

  • FormerMember
    0 FormerMember

    Answering my second question: yes, it is possible to wait longer and not use the timer IRQ to disable the PPI. But there is a better way. A bit of optimization of the library to remove the blocking of the processor for a PWM period which can be many microseconds. Could be costly when updating frequently.

    This can be done by commenting out nrf_delay_us(pwm_period_us); and changing the Timer IRQ to

    void PWM_IRQHandler(void)
    {
        PWM_TIMER->EVENTS_COMPARE[3] = 0;
        static bool alternate_flag = false;
    
        if(true == alternate_flag){
          PWM_TIMER->INTENCLR          = TIMER_INTENCLR_COMPARE3_Msk;
    
          ppi_disable_channels((1 << (PWM_MAX_CHANNELS * 2)) | (1 << (PWM_MAX_CHANNELS * 2 + 1)) | (1 << (PWM_MAX_CHANNELS * 2 + 2)));
          ppi_configure_channel_group(pwm_ppi_chg, 0);
          ppi_disable_channel_group(pwm_ppi_chg);
        }
        alternate_flag = (true == alternate_flag)?false:true;
    }
    

    Now the IRQ gets called twice with the actual PPI disabling done the second time. Since it is a low priority IRQ it does not block critical stuff. The CPU gets kept on for lesser time. The nrf_pwm_set_value() now returns immediately.

    With not using softdevice calls for configuring PPIs it is possible to call nrf_pwm_set_value() from high priority IRQ, especially now that the call is non-blocking.

    Makes sense to send a pull request to the library?

Related