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

Unable to Toggle PWM Module Off and On

Hello,

I have an issue that I can't seem to sort out involving the PWM module. I am currently using SDK9.0 and SoftDevice S110 V8.0 and I am using the stock PWM files from the SDK. The problem I am having is that I can't seem to disable and then re-enable the PWM module. I want to turn the PWM module off when I don't need it to save on battery life and power consumption. I am using a total of three PWM channels on 2 instances that I Init in the following way:

APP_PWM_INSTANCE(PWM1,1);
APP_PWM_INSTANCE(PWM2,2);

bool pwm_1_ready_flag;
bool pwm_2_ready_flag;

void pwm_1_ready_callback(uint32_t pwm_id)
{
  pwm_1_ready_flag = true;
}

void pwm_2_ready_callback(uint32_t pwm_id)   
{
  pwm_2_ready_flag = true;
}

void pwm_init(void)
{
  ret_code_t err_code;

  /* 2-channel PWM, output on LED pins. */
  app_pwm_config_t pwm1_cfg = APP_PWM_DEFAULT_CONFIG_2CH(10000L, LED_RED, LED_GREEN);
  app_pwm_config_t pwm2_cfg = APP_PWM_DEFAULT_CONFIG_1CH(10000L, LED_BLUE);

  /* Set the polarity of the channel. */
  pwm1_cfg.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_HIGH;
  pwm1_cfg.pin_polarity[1] = APP_PWM_POLARITY_ACTIVE_HIGH;
  pwm2_cfg.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_HIGH;

  /* Initialize and enable PWM. */
  err_code = app_pwm_init(&PWM1,&pwm1_cfg,pwm_1_ready_callback);
  APP_ERROR_CHECK(err_code);
  err_code = app_pwm_init(&PWM2,&pwm2_cfg,pwm_1_ready_callback);
  APP_ERROR_CHECK(err_code);
}

Then I enable the PWM module using:

void enable_pwm(void)
{
  app_pwm_enable(&PWM1);
  app_pwm_enable(&PWM2);
}

Next I display some blinking LED patterns using PWM and then I turn off the PWM module with:

void disable_pwm(void)
{
  app_pwm_disable(&PWM1);
  app_pwm_disable(&PWM2);
}

I then verify that the power consumption is a lot lower. Everything is good up until this point. I then try to turn the PWM module back on using:

enable_pwm()

and then I execute the following:

for(int i =0; i < 100; i=i+5)
{
	if(i <= red_led_value)
	{
		while (app_pwm_channel_duty_set(&PWM1, 0, i) == NRF_ERROR_BUSY);
	}
	if(i <= green_led_value)
	{
		while (app_pwm_channel_duty_set(&PWM1, 1, i) == NRF_ERROR_BUSY);
	}
	if(i <= blue_led_value)
	{
		while (app_pwm_channel_duty_set(&PWM2, 0, i) == NRF_ERROR_BUSY);
	}	
	nrf_delay_ms(10);
}

This should make the RGB LED that I have on my board glow to a bright white. Instead my RGB turns yellow and gets stuck at:

while (app_pwm_channel_duty_set(&PWM2, 0, i) == NRF_ERROR_BUSY);

Its almost as if the app_pwm_enable(&PWM2) call didn't turn the second channel of my PWM module back on.

Here is the Timers section of the nrf_drv_config.h file for reference:

/* TIMER */
#define TIMER0_ENABLED 0

#if (TIMER0_ENABLED == 1)
#define TIMER0_CONFIG_FREQUENCY    NRF_TIMER_FREQ_16MHz
#define TIMER0_CONFIG_MODE         TIMER_MODE_MODE_Timer
#define TIMER0_CONFIG_BIT_WIDTH    TIMER_BITMODE_BITMODE_32Bit
#define TIMER0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW

#define TIMER0_INSTANCE_INDEX      0
#endif

#define TIMER1_ENABLED 1

#if (TIMER1_ENABLED == 1)
#define TIMER1_CONFIG_FREQUENCY    NRF_TIMER_FREQ_16MHz
#define TIMER1_CONFIG_MODE         TIMER_MODE_MODE_Timer
#define TIMER1_CONFIG_BIT_WIDTH    TIMER_BITMODE_BITMODE_16Bit
#define TIMER1_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW

#define TIMER1_INSTANCE_INDEX      (TIMER0_ENABLED)
#endif

#define TIMER2_ENABLED 1

#if (TIMER2_ENABLED == 1)
#define TIMER2_CONFIG_FREQUENCY    NRF_TIMER_FREQ_16MHz
#define TIMER2_CONFIG_MODE         TIMER_MODE_MODE_Timer
#define TIMER2_CONFIG_BIT_WIDTH    TIMER_BITMODE_BITMODE_16Bit
#define TIMER2_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW

#define TIMER2_INSTANCE_INDEX      (TIMER1_ENABLED+TIMER0_ENABLED)
#endif

#define TIMER_COUNT (TIMER0_ENABLED + TIMER1_ENABLED + TIMER2_ENABLED)

Do you have any thoughts or suggestions as to why my PWM module isn't working as expected? Any help or advice you can offer is greatly appreciated. I also need to mention that I am executing all of the LED patterns, PWM Enable, and PWM Disable calls using the scheduler.

Thanks for your help and support!

-Cory

  • I believe there may be an error in the app_pwm.c file, specifically regarding the app_pwm_enable function. When I look at the app_pwm disable function:

    void app_pwm_disable(app_pwm_t const * const p_instance)
    {
      app_pwm_cb_t * p_cb = p_instance->p_cb;
      ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED);
      nrf_drv_timer_disable(p_instance->p_timer);
      pwm_irq_disable(p_instance);
      p_cb->state = NRF_DRV_STATE_INITIALIZED;
      return;
    }
    

    There is a function that disables the IRQ for that instance:

    nrf_drv_timer_disable(p_instance->p_timer);
    

    But if we look at the function declaration for app_pwm_enable:

    void app_pwm_enable(app_pwm_t const * const p_instance)
    {
      app_pwm_cb_t * p_cb = p_instance->p_cb;
      ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED);
      nrf_drv_timer_enable(p_instance->p_timer);
      p_cb->state = NRF_DRV_STATE_POWERED_ON;
      return;
    }
    

    There is no function to enable the IRQ for the specified instance. By adding the following line:

    pwm_irq_enable(p_instance);
    

    to the app_pwm_enable function we end up with:

    void app_pwm_enable(app_pwm_t const * const p_instance)
    {
      app_pwm_cb_t * p_cb = p_instance->p_cb;
      ASSERT(p_cb->state != NRF_DRV_STATE_UNINITIALIZED);
      nrf_drv_timer_enable(p_instance->p_timer);
      pwm_irq_enable(p_instance);
      p_cb->state = NRF_DRV_STATE_POWERED_ON;
      return;
    }
    

    This seems to have fixed the problems with PWM that I was having. Was this just a bug in the SDK or was I doing something wrong? I can now toggle PWM on and off and everything else appears to be functioning properly. Any clarification or confirmation would be great and I hope this helps anyone else who may be struggling with the same issue.

    Thanks!

  • The power enable/disable and power consumtion related issues has been fixed in SDK v10.0 available here: developer.nordicsemi.com/.../ .

Related