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();
}

Parents
  • 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.

Reply
  • 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.

Children
  • 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.

  • I am perplexed why doing this worked

    { {DUTY_CYCLE, 0, 0, 0} } 

    I have been fighting this for like 2 days now almost ready to implement my own PWM. I am not a firmware expert by any means. Can yo uexplain why the double curly brakcets made it work and why  you had to add them?

  • Its because seq_values array contains strucure nrf_pwm_values_individual_t, so inner brackets encloses structure values, but outer array items. With double brackets we are creating array with one item, which holds structure containing four variables. As example You can assign { {DUTY_CYCLE_1, 0, 0, 0} , {DUTY_CYCLE_2, 0, 0, 0}} and playback_count in nrf_drv_pwm_simple_playback defines how many times each DUTU_CYCLE are repeated before changing to next in array. Without double brackets Your compiler can misinterpret which value is which.

Related