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

How to start pwm sequence after particular time delay of gpio event?

I am working on an application where I need to start pwm sequence after particular delay (accurate delay of multiple of 100us).

I am quite new to nordic environment.

Here is my code . Can please guide me what is wrong here??

#define    Period    20000 //20ms

const nrf_drv_timer_t TIMER_LED = NRF_DRV_TIMER_INSTANCE(0);

APP_PWM_INSTANCE(PWM1,1); 

static int gpio_flag =0;

void pwm_update(void)
{
      uint32_t value;
      value = duty_1;
      ready_flag = false;
      /* Set the duty cycle - keep trying until PWM is ready... */
      
      

      while ((app_pwm_channel_duty_set(&PWM1, 0, value))&(app_pwm_channel_duty_set(&PWM1, 1, value)) == NRF_ERROR_BUSY);
 
      /* ... or wait for callback. */
      while (!ready_flag);
      APP_ERROR_CHECK(app_pwm_channel_duty_set(&PWM1, 1, value));
      APP_ERROR_CHECK(app_pwm_channel_duty_set(&PWM1, 0, value));

}


void in_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
   gpio_flag =1;
   nrf_drv_timer_enable(&TIMER_LED);

   
}

void timer0_handler(nrf_timer_event_t event_type, void* p_context)
{
  switch (event_type)
    {
        case NRF_TIMER_EVENT_COMPARE0:
             timer_flg =1;
             nrf_drv_timer_clear(&TIMER_LED);
             gpio_flag=0;
             pwm_update();
            break;

        default:
            //Do nothing.
            break;
    }
}


void timer_init(void)
{
    uint32_t time_us = 500; 
    uint32_t time_ticks;
    uint32_t err_code = NRF_SUCCESS;

    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    err_code = nrf_drv_timer_init(&TIMER_LED, &timer_cfg, timer0_handler);
    APP_ERROR_CHECK(err_code);

    time_ticks = nrf_drv_timer_us_to_ticks(&TIMER_LED, time_us);
    nrf_drv_timer_compare(
         &TIMER_LED, NRF_TIMER_CC_CHANNEL0, time_ticks, true);

    
}

  • Could I also ask why you are using an external periodic signal to enable the Timer? Is this placeholder functionality for something you will implement later?

    I want to follow external periodic signal with some user defined delay that why I am starting timer from interrupt.

    My aim is here to create a same periodic signal of 50% duty cycle and 20ms period but with user defined delay(that is vary from 0 to 10ms ).

    Is the gpio_flag being set every 10 ms?

    For now I configured for 20ms but definitely aim is to get in every 10ms.

    It would also be helpful if you could share with me your sdk_config.h file, so I may take a look at your GPIOTE and TIMER configuration.

    3718.sdk_config.h

    Best regards,
    Ram

  • Hello again, ram

    Looking over your sdk_config.h I notice that you have both the NRFX_TIMER_ENABLED and legacy TIMER_ENABLED defined to 1.
    You should only have the one corresponding to the driver you intend to use present. In the current case, if you intend to use the nrfx driver the NRFX_TIMER_ENABLED will be overwritten by TIMER_ENABLED at compile-time.
    If you intend to use the nrfx driver, you should therefore remove the legacy *_ENABLED definitions from the sdk_config all together (remove or comment out, as they can not be left defined).

    In your case it seems that you are using the 16 MHz clock frequency with the 16 bit bit depth, could you try to increase this to 32 bit bit depth and see if that makes a difference on the behavior you are seeing? You could do this by defining NRFX_TIMER_DEFAULT_CONFIG_BIT_WIDTH to 3 (if using the nrfx driver, and having removed all mention of the legacy timer define's).

    Best regards,
    Karl

  • Hello Karl,

    If you intend to use the nrfx driver, you should therefore remove the legacy *_ENABLED definitions from the sdk_config all together (remove or comment out, as they can not be left defined)

    If I remove legacy *_ENABLED definitions then my PWM_UPDATE() function will not work. 

    You can get idea from the function ,So I am attaching here .

    void pwm_update(void)
    {
          uint32_t value;
          value = duty_1;
          ready_flag = false;
          /* Set the duty cycle - keep trying until PWM is ready... */
          
          
    
          while ((app_pwm_channel_duty_set(&PWM1, 0, value))&(app_pwm_channel_duty_set(&PWM1, 1, value)) == NRF_ERROR_BUSY);
     
          /* ... or wait for callback. */
          while (!ready_flag);
          APP_ERROR_CHECK(app_pwm_channel_duty_set(&PWM1, 1, value));
          APP_ERROR_CHECK(app_pwm_channel_duty_set(&PWM1, 0, value));
    
    }

    I tried with same logic with PWM_DRIVER but its not working.

    Here is my same logic with pwm_driver example from SDK.

    static nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0);
    
    
    
    
    
    // Declare variables holding PWM sequence values. In this example only one channel is used 
    nrf_pwm_values_individual_t seq_values[] = {0, 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
    };
    
    static void pwm_init(void)
    {
        nrf_drv_pwm_config_t const config0 =
        {
            .output_pins =
            {
                OUTPUT_PIN, // channel 0
                OUTPUT_PIN2,             // 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    = 20000,
            .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 pwm_update_duty_cycle(uint16_t duty_cycle)
    {
        if(duty_cycle == 0)
        {
         seq_values->channel_0 = duty_cycle ;
         seq_values->channel_1 = duty_cycle ;
        }
       else
        {
            seq_values->channel_0 = duty_cycle ;
            seq_values->channel_1 = duty_cycle | 0x8000;
        }
        
        
        nrf_drv_pwm_simple_playback(&m_pwm0, &seq, 1, NRF_DRV_PWM_FLAG_LOOP);
    }
    
    int main(void)
    {
       
        bsp_board_init(BSP_INIT_LEDS);
        gpio_init();
        pwm_init();
        
         
        unsigned int val;
        
        while (1)
        {
          
          if(gpio_flag == 1)
          {
           val= duty;
           gpio_flag=0;
           pwm_update_duty_cycle(val); 
     
          }
          else
          {
           pwm_update_duty_cycle(0);   
          }
           
        }
    }
    

    Best regards,
    Ram

  • Hello ram,

    RAM_MS said:
    If I remove legacy *_ENABLED definitions then my PWM_UPDATE() function will not work. 

    What do you mean when you say that the pwm_update function stops working? Please describe the behavior you observe and how it differs from what you would expect.
    Would you mind sharing with me the sdk_config.h file following your removal of legacy define's, so I may take a look?

    Did you try to configure the TIMER to use a bit depth of 32? Did you see any difference then?

    RAM_MS said:
    I tried with same logic with PWM_DRIVER but its not working.

    Please elaborate on what you mean when you say it is not working - does this produce the same result as when you were using the pwm library?
    If so, it may be related to the timer configuration rather than the PWM module usage.

    Best regards,
    Karl

  • Hello Karl,

    What do you mean when you say that the pwm_update function stops working? Please describe the behavior you observe and how it differs from what you would expect.

    Because my pwm_update () is from pwm library example .

    AND after commenting legacy definations, this error message coming during building the project.

    #error "No enabled TIMER instances. Check <nrfx_config.h>."

    Would you mind sharing with me the sdk_config.h file following your removal of legacy define's, so I may take a look?

    here is the sdk_config.h after commenting legacy defines.

    8765.sdk_config.h

    Did you try to configure the TIMER to use a bit depth of 32? Did you see any difference then?

    yes ,I tried but not see any difference.

    Please elaborate on what you mean when you say it is not working - does this produce the same result as when you were using the pwm library?

    working pwm with periodical interrupt is

    if(gpio_flag == 1)
        {
         gpio_flag = 0;
         pwm_update();
        }
        else
        {
         app_pwm_channel_duty_set(&PWM1, 1, 0);
         app_pwm_channel_duty_set(&PWM1, 0, 0);
        }
       

    where if I used pwm_driver then same code not working.

    if(gpio_flag == 1)
        {
         gpio_flag = 0;
          pwm_update_duty_cycle(10000);
        }
        else
        {
         pwm_update_duty_cycle(0);
        }

    where pwm_update () is inspired from pwm_library example and pwm_update_duty_cycle() is inspired from pwm_driver .

    As my pwm algorithm working with legacy defines ,So its better to remove nrfx_timer_driver .

    So if you guide me to generate delay from legacy timer then it may be immediate solution for my issue as per my understanding .

    Best regards,
    Ram

Related