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

Inverted PWM SDK 6.1.0 / SD 7.1

hello

we use nRF51822 QF AC A1 / IC rev 3 with SDK 6.1.0 / S110 7.1.0. We have produced and delivered to client > 1k units

pwm code nrf_pwm_noglitch 02.2015 from github.com/.../nrf51-pwm-library

void PWM_IRQHandler(void)

{
    PWM_TIMER->EVENTS_COMPARE[3] = 0;
    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);
}


void nrf_pwm_set_value(uint32_t pwm_channel, uint32_t pwm_value)

			if ((pwm_value * 2) > PWM_TIMER->CC[pwm_channel])
    {
        // New duty cycle is larger than the current one
        ppi_disable_channels(1 << (PWM_MAX_CHANNELS * 2));
        PWM_TIMER->CC[2] = pwm_value * 2;
        
        ppi_configure_channel(PWM_MAX_CHANNELS * 2, &PWM_TIMER->EVENTS_COMPARE[2], &PWM_TIMER->TASKS_CAPTURE[pwm_channel]);
        ppi_enable_channels(1 << (PWM_MAX_CHANNELS * 2));
        
        // Wait for one PWM clock cycle
        nrf_delay_us(pwm_period_us);
     
        // Disable PPI channels next cycle
        pwm_freq_int_set();
    }
    else
    {
        // New duty cycle is smaller than the current one
        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);
        ppi_configure_channel_group(pwm_ppi_chg, (1 << (PWM_MAX_CHANNELS * 2)) | (1 << (PWM_MAX_CHANNELS * 2 + 1)));
        
        ppi_configure_channel(PWM_MAX_CHANNELS * 2,     &PWM_TIMER->EVENTS_COMPARE[2], &NRF_GPIOTE->TASKS_OUT[pwm_gpiote_channel[pwm_channel]]);
        ppi_configure_channel(PWM_MAX_CHANNELS * 2 + 1, &PWM_TIMER->EVENTS_COMPARE[2], &PWM_TIMER->TASKS_CAPTURE[pwm_channel]);
        ppi_configure_channel(PWM_MAX_CHANNELS * 2 + 2, &PWM_TIMER->EVENTS_COMPARE[3], &NRF_PPI->TASKS_CHG[pwm_ppi_chg].EN);
        
        PWM_TIMER->CC[2] = pwm_value * 2;
        ppi_enable_channels(1 << (PWM_MAX_CHANNELS * 2 + 2));
        
        // Wait for one PWM clock cycle
        nrf_delay_us(pwm_period_us);
        
        // Disable PPI channels next cycle
        pwm_freq_int_set();
    }

We use 2 PWM channels on Timer 2 / PWM Frequency 6.5Khz / Resolution 1239

  • PWM Refresh ~1 Sekunde
  • Range from 3% .. 97%, we never use the PWM out of this range, Refresh_PWM only on value_change
  • we do not use powerdown, never change the powerstate

Sometimes after hours, days, or after Weeks the PWM becomes inverted. Its very hard to reproduce.

i ve read the discussion "sometimes PWM signal is reversed.", but this is about sdk 8.1 and im not shure if my problem will be fixed with 8.1.0 ? i think the SDK and SD migration to 8.x will not be easy.

Any idea what could be the problem and how it can be solved ?

Related