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

PWM not pulsing

I have a custom board SDK 15.2 API 6.1

I have a simple PWM going but it seems to just turn the low and set it high when i turn it on. It does not however seem to pulse according to my scope. Nor does it stop. This is in a ble application that has softdevices enabled and LFCLK source. I am tyring to use app_pwm.h instead of the nrf_drv_pwm. I am curious why a simple application doe snot seem to operate though.

static nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0);

nrf_pwm_values_individual_t seq_values[] = {DUTY_CYCLE, 0, 0, 0};
nrf_pwm_sequence_t const seq =
{
    .values.p_individual = seq_values,
    .length          = NRF_PWM_VALUES_LENGTH(seq_values),
    .repeats         = 0,
    .end_delay       = 0
};


void pwm_start(void)
{
    nrf_drv_pwm_simple_playback(&m_pwm0, &seq, 1, NRF_DRV_PWM_FLAG_LOOP);
}

void pwm_stop(void)
{
    nrf_drv_pwm_stop(&m_pwm0, false);
}

static void pwm_init(void)
{
    nrf_drv_pwm_config_t const config0 =
    {
        .output_pins =
        {
            OUTPUT_PIN, // channel 0
            NRF_DRV_PWM_PIN_NOT_USED,             // channel 1
            NRF_DRV_PWM_PIN_NOT_USED,             // channel 2
            NRF_DRV_PWM_PIN_NOT_USED,             // channel 3
        },
        .irq_priority = APP_IRQ_PRIORITY_LOWEST,
        .base_clock   = NRF_PWM_CLK_1MHz,
        .count_mode   = NRF_PWM_MODE_UP,
        .top_value    = 100,
        .load_mode    = NRF_PWM_LOAD_INDIVIDUAL,
        .step_mode    = NRF_PWM_STEP_AUTO
    };
    // Init PWM without error handler
    APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm0, &config0, NULL));
    
}

void int main(void){
    pwm_init();
    pwm_start();
    nrf_delay_ms(2000);
    pwm_stop();
}

  • What is value of DUTY_CYCLE (on line 3) ?

    If it set to 100% DC, then there is no pulses to see on scope only level change to high when turned on.

  • One idea I have is that You must increase playback_count in:

    nrf_drv_pwm_simple_playback(&m_pwm0, &seq, 1, NRF_DRV_PWM_FLAG_LOOP);

    for example from 1 to 1000 ant test it, as I remember this defines how long pulses are generated.

    For Looping manual says "To take advantage of the looping mechanism in the PWM peripheral, both sequences must be used (single sequence can be played back only once by the peripheral)", so I think curently Your sequence are played only once and for very short time.

    Currently I can't test on my hardware, only maybe later, but I remember that value in my case is 2000.

  • I feel like there may not be a clock operating. All the example i see do the following

    // Start clock for accurate frequencies
    NRF_CLOCK->TASKS_HFCLKSTART = 1; 
    // Wait for clock to start
    while(NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) ;

    However, i use LFCLK. Could me not doing that be an issue. If i do, ow to i enable both clocks, because i tried adding that intot he system and it made things worse.

    Are there setting in the sdk_config file i need to set. Right now i have 

    NRFX_TIMER_ENABLED = 1; APP_TIMER_ENABLED = 1; and TIMER_ENABLED = 1

    Am i getting conflicts?

  • For fast test I take sdk_config from examples/peripheral/pwm_driver/pca10040/blank/config and after fixing two lines about which armgcc complains Your code works as expected.

    I only changed {DUTY_CYCLE, 0, 0, 0} to { {DUTY_CYCLE, 0, 0, 0} } and "void int main(void){" to "int main(void){"

    ups I missed a point about app_pwm.h tested with nrf_drv_pwm.h

    Sorry, I newer used app_pwm, but examples/peripheral/pwm_library looks absolutely different PWM initialisation and usage.

Related