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

PWM SEQ0 interrupt

I am trying to do a ramping PWM. I want to update PWM every 25ms by increasing the duty cycle by 10%. I tried to setup a timer, by calling app_start_timer() on repeat mod and then within the timer callback i use the update_duty_cycle() found in the pwm example. However, the timer never seems to trigger no matter what i do. I have other timers that operate fine, this is the only timer that doesn't seem to run.

I then tried to do it with SEQ1 interrupts, I am using a simple pwm. so i thought the SEQ1 would be trigger every cycle, turn off -> turn off -> SEQ1 end trigger -> SEQ0 -> SEQ1.... where SEQ0 and SEQ1 are the same in simple playback using MODE_INDIVIDUAL. It appears the event handler only gets called after i stop the PWM.

Is there something i am missing here as to why the a) timer is not working as expected or b) by the SQ1 interrupt is not trigger every cycle?

#define MOTOR_PWM_DUTY_CYCLE      90
#define PWM_TOP_VALUE             100
#define DUTY_CYCLE_RAMP_CHANGE_MS 25

APP_TIMER_DEF(pwm_duty_cycle_timer_id);

static nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0);
static uint8_t pwm_duty_cycle;

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


// Set duty cycle between 0 and 100%. This isinverse. Duty Cycls is OFF time
void pwm_update_duty_cycle(uint8_t duty_cycle)
{
    if(duty_cycle <= 0){
        seq_values->channel_0 = 0;
    }else{
        seq_values->channel_0 = duty_cycle;
    }
    nrf_drv_pwm_simple_playback(&m_pwm0, &seq, 1, NRF_DRV_PWM_FLAG_LOOP | NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ1);
}

static void pwm_event_handler(nrf_drv_pwm_evt_type_t event_type)
{

    if (event_type == NRF_DRV_PWM_EVT_END_SEQ1){
        if(pwm_duty_cycle > 0){
            pwm_duty_cycle -= 10;
            //nrf_drv_pwm_stop(&m_pwm0, false);
            pwm_update_duty_cycle(pwm_duty_cycle);
        }
    }

}

static void pwm_duty_cycle_timeout_handler(void * p_context)
{
    UNUSED_PARAMETER(p_context);

    if(pwm_duty_cycle > 0){
        pwm_duty_cycle -= 10;
        nrf_drv_pwm_stop(&m_pwm0, false);
        pwm_update_duty_cycle(pwm_duty_cycle);
    }
}

static void init_timers(void){
    uint32_t err_code;
    
    err_code = app_timer_create(&pwm_duty_cycle_timer_id,
                                APP_TIMER_MODE_REPEATED,
                                pwm_duty_cycle_timeout_handler);
    APP_ERROR_CHECK(err_code);
}

static void motor_drv_pwm_init(void)
{
    uint32_t err_code;

    nrf_drv_pwm_config_t const config0 =
    {
        .output_pins =
        {
            IN1_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_timers();

    err_code = nrf_drv_pwm_init(&m_pwm0, &config0, pwm_event_handler);
    APP_ERROR_CHECK(err_code);
}

bool motor_drv_forward(void)
{
    bool result = false;
    uint32_t err_code;

    if(s_initialized)
    {
        nrf_gpio_pin_write(EN_PIN, PIN_ACTIVE);
        nrf_delay_ms(300);
        
        app_timer_start(pwm_duty_cycle_timer_id, APP_TIMER_TICKS(DUTY_CYCLE_RAMP_CHANGE_MS), NULL);
        pwm_duty_cycle = 90;
        nrf_drv_pwm_simple_playback(&m_pwm0, &seq, 1, NRF_DRV_PWM_FLAG_LOOP | NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ1);
        result = true;
    }

    return result;
}

Parents
  • I was able to get a ramping using a complex pwm call. per below. but i am still curious to know the answers to my questions on why the timer and the pwm seq0 callback was not working

    uint16_t value = PWM_RAMP_TOP;
    uint8_t  i;
    for (i = 0; i < 10; i++){
    pwm_ramp_values[i] = value;
    value              -= PWM_RAMP_TOP / 10;
    }
    
    static nrf_pwm_sequence_t const ramp_seq0 =
    {
    .values.p_common      = pwm_ramp_values,
    .length               = NRF_PWM_VALUES_LENGTH(pwm_ramp_values),
    .repeats              = 200,
    .end_delay            = 0
    };
    
    static nrf_pwm_sequence_t const ramp_seq1 =
    {
    .values.p_common      = pwm_ramp_full_on,
    .length               = NRF_PWM_VALUES_LENGTH(pwm_ramp_full_on),
    .repeats              = 20000,
    .end_delay            = 0
    };
    nrf_drv_pwm_complex_playback(&m_pwm0, &ramp_seq0, &ramp_seq1, 1, NRF_DRV_PWM_FLAG_LOOP);

Reply
  • I was able to get a ramping using a complex pwm call. per below. but i am still curious to know the answers to my questions on why the timer and the pwm seq0 callback was not working

    uint16_t value = PWM_RAMP_TOP;
    uint8_t  i;
    for (i = 0; i < 10; i++){
    pwm_ramp_values[i] = value;
    value              -= PWM_RAMP_TOP / 10;
    }
    
    static nrf_pwm_sequence_t const ramp_seq0 =
    {
    .values.p_common      = pwm_ramp_values,
    .length               = NRF_PWM_VALUES_LENGTH(pwm_ramp_values),
    .repeats              = 200,
    .end_delay            = 0
    };
    
    static nrf_pwm_sequence_t const ramp_seq1 =
    {
    .values.p_common      = pwm_ramp_full_on,
    .length               = NRF_PWM_VALUES_LENGTH(pwm_ramp_full_on),
    .repeats              = 20000,
    .end_delay            = 0
    };
    nrf_drv_pwm_complex_playback(&m_pwm0, &ramp_seq0, &ramp_seq1, 1, NRF_DRV_PWM_FLAG_LOOP);

Children
Related