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