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

    
}

  • Hello again,

    RAM_MS said:
    Thank you so much Karl ,this was the problem in my code after arranging this correcting now I am able to get exact TIMING Delay .

    No problem at all, Ram - I am happy to hear that this resolved the added delay issue!

    RAM_MS said:
    Sorry ,You are right I shared the code that was used to test the TIMER's accuracy.
    RAM_MS said:
    Yes ,you are right I am using that variable to store it and pass it to the PPI assign function.
    RAM_MS said:
    As always Yellow one is INPUTTED PWM SIGNAL and Blue one is my OUTPUT PWM .

    Thank you for clarifying these things.

    RAM_MS said:

    For testing purpose I generated inputting PWM signal from PIN NO 11( that is PWM_PIN 11) in the code you might seen it and giving it to (PIN_IN 22). 

    But in real case the inputting PWM will come from outside .

    So for create this scenario I created inputted PWM signal from a different NRF52 DK .

    And what I observed is my Generated PWM Signal is Shifting with time.

    For your reference I am attaching the video of it.

    That is very strange indeed. Perhaps there is something amiss with the sequence looping.

    Could you share the newest version of the code - the code you ran when you observed this - so I may see if I can spot any potential explanation for this?

    Best regards,
    Karl

  • Hello Karl,

    I am happy to hear that this resolved the added delay issue!

    I am really happy that we patiently progress up to this stage.

    And Thank you a lot .

    That is very strange indeed. Perhaps there is something amiss with the sequence looping.

    Could you share the newest version of the code - the code you ran when you observed this - so I may see if I can spot any potential explanation for this?

    For your reference I am attaching code here.

    7384.main.zip

    As earlier I said for testing purpose I generated 1st in the same DK in PWM_PIN(11).

    But for now I commented this part by commenting pwm1_init();

    And giving INPUTTED PWM Signal from Different DK in PIN_IN (22);

    Best regards,
    Ram

  • RAM_MS said:

    I am really happy that we patiently progress up to this stage.

    And Thank you a lot .

    No problem at all, Ram - I am happy to help!

    RAM_MS said:

    As earlier I said for testing purpose I generated 1st in the same DK in PWM_PIN(11).

    But for now I commented this part by commenting pwm1_init();

    And giving INPUTTED PWM Signal from Different DK in PIN_IN (22);

    Thank you for clarifying this.

    RAM_MS said:
    For your reference I am attaching code here.

    I do not immediately see the reason for why the phase shift would be happening, but I suspect that it might be because the PPI channels are left enabled throughout the run of the application, so that there might be happening a brief stopping and re-starting of the waveform generation, or similar, causing the phase shift.
    Could you try to implement the stopping / disabling of the GPIOTE pin, TIMER instance and PPI channels when the PWM is successfully started, like we talked about earlier?

    By the way, you can change your GPIOTE_CONFIG_IN_SENSE_LOTOHI(true); back to false again - since this was not the cause of the added delay earlier.

    I also notice that you are still not using the pwm start task address returned from the nrf_drv_pwm_simple_playback call, since it is overwritten by the call to nrf_pwm_task_addr_get in the ppi_init - this should not matter though, since they should point to the same address - but I point it out to avoid any confusion since you have stated earlier that it is this return address that is being used.

    Best regards,
    Karl

  • Hello Karl,

    By the way, you can change your GPIOTE_CONFIG_IN_SENSE_LOTOHI(true); back to false again - since this was not the cause of the added delay earlier.

    Yes ,I did that.

    I also notice that you are still not using the pwm start task address returned from the nrf_drv_pwm_simple_playback call, since it is overwritten by the call to nrf_pwm_task_addr_get in the ppi_init - this should not matter though, since they should point to the same address - but I point it out to avoid any confusion since you have stated earlier that it is this return address that is being used.

    Yes ,actually that was just a by mistake . I made it proper.

    I do not immediately see the reason for why the phase shift would be happening, but I suspect that it might be because the PPI channels are left enabled throughout the run of the application, so that there might be happening a brief stopping and re-starting of the waveform generation, or similar, causing the phase shift.
    Could you try to implement the stopping / disabling of the GPIOTE pin, TIMER instance and PPI channels when the PWM is successfully started, like we talked about earlier?

    How to check if PWM is successfully started ?

    Is there any function in SDK which return this ?

    Because I checked with return value from pwm_init () which is NRF_SUCCESS.

    But this is not right way may be .

    So can you please guide me here.

    Best regards,
    Ram 

  • Hello Ram,

    RAM_MS said:
    Yes ,actually that was just a by mistake . I made it proper.

    Great - it is no problem at all, I just thought I should mention it since I noticed.

    RAM_MS said:

    How to check if PWM is successfully started ?

    Is there any function in SDK which return this ?

    Because I checked with return value from pwm_init () which is NRF_SUCCESS.

    But this is not right way may be .

    So can you please guide me here.

    You could check that the EVENTS_SEQSTARTED[n] event happens. This will indicate that the sequence has started.
    You can add this event as a case in the pwm handler, and then either add a breakpoint or a logger statement to indicate that the event is generated as expected.
    You could use this event to indicate that the PWM is successfully running, so that you may disable the GPIOTE, TIMER and PPI channels used to set it up.

    Best regards,
    Karl

Related