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

    
}

Parents Reply Children
  • Hello Karl,

                   Thank you for your valuable inputs .

                   I tried with your code and timer is triggering but instead of 1ms delay its coming increments                         automatically.

                   For your better understand I am attaching both project .zip and my configuration aim in .png file

                  Also I am adding video of my outputs.

    pwm_library_timer_delay.zip

    The yellow signal is the interrupt signal and the blue signal is my pwm signal .

    Thanks & regards,
    Ram

  • Hello again, Ram

    RAM_MS said:
    Thank you for your valuable inputs .

    No problem at all, I am happy to help you.

    RAM_MS said:
    I tried with your code and timer is triggering but instead of 1ms delay its coming increments                         automatically.

    I am not sure that I understand what you mean by this - are you not seeing the button trigger a configurable timer, which calls pwm_update on expiration?
    Keep in mind that the pwm_update function is not populated in my example, so you will have to have it do something worthwhile in the pwm_update example before the example outputs anything useful when the delay expires.

    RAM_MS said:

     For your better understand I am attaching both project .zip and my configuration aim in .png file

                  Also I am adding video of my outputs.

    Oh, I see - I was under the impression that you wanted to update a PWM's duty cycle after a given delay. I was not aware that you wanted to output the same waveform out that you have received in, with an added delay.

    The simplest implementation of this would perhaps be to just have the GPIOTE IN event trigger a timer with the provided delay, that in turn sets the output pin high or low?
    You could use the PPI peripheral to have the GPIOTE in event start the TIMER, and the TIMER CC event toggle the output GPIO directly, so that none of it requires CPU intervention.

    Best regards,
    Karl

  • Hello Karl,

    The simplest implementation of this would perhaps be to just have the GPIOTE IN event trigger a timer with the provided delay, that in turn sets the output pin high or low?
    You could use the PPI peripheral to have the GPIOTE in event start the TIMER, and the TIMER CC event toggle the output GPIO directly,

    I am not getting you here .

    Can you please elaborate little more or give me a small demo of it what you are explaining.

    Thanks & regards,
    Ram

  • Hello Ram,

    RAM_MS said:
    I am not getting you here .

    I do not understand what you mean by this, could you clarify?

    RAM_MS said:
    Can you please elaborate little more or give me a small demo of it what you are explaining.

    I do not have a demo for this, but to elaborate you could start by taking a look at how the SAADC example connects a TIMER event to a SAADC task.
    You could use the exact same approach to connect a GPIOTE EVENTS_IN event to a TIMER START task through PPI. This will make the GPIOTE event (such as a LOW to HIGH event) start the delay TIMER.
    Then, you can use the PPI peripheral in the same manner to also have the TIMER CC EVENT (timer expired) trigger a GPIOTE SET task - setting the GPIO high when the delay has passed.

    There might be other good ways of doing this as well, depending on the assumptions one could make about your application. For example, will the duty cycle of the incoming PWM always be the same, or will this change as well? Is your end goal to output the exact same waveform out, as it was received in, with only the delay added, or will you do make any sort of changes to the incoming waveform?

    Best regards,
    Karl

  • Hello Karl,

    I do not have a demo for this, but to elaborate you could start by taking a look at how the SAADC example connects a TIMER event to a SAADC task.
    You could use the exact same approach to connect a GPIOTE EVENTS_IN event to a TIMER START task through PPI. This will make the GPIOTE event (such as a LOW to HIGH event) start the delay TIMER.

    I will definitely do this a try.

    There might be other good ways of doing this as well, depending on the assumptions one could make about your application. For example, will the duty cycle of the incoming PWM always be the same, or will this change as well? Is your end goal to output the exact same waveform out, as it was received in, with only the delay added, or will you do make any sort of changes to the incoming waveform?

    Definitely ,Because I did it STM32 by using TIMER in one pulse mode and its working properly .

    As BLE is needed in this application ,I am trying to do in Nordic.

    And yes duty cycle of incoming PWM always will be same .

    Yes ,My goal is to output the same waveform out ,as it was received in, with only the delay added from (100 µs to 10ms).

    Here I am attaching the pictures of what I achieved in STM32 for your reference.

    Thanks & regards,
    Ram

Related