Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Timer and gpiote for generation of IR pulses

Hello,

I am currently trying to implement an IR sending functionality. My plan is to use a timer to toggle gpiote through ppi. For the width of an IR pulse (or mark) and space, I count the number of timer pulses generated.

Now I can clearly see the generated pulses with correct period (26us for 38kHz). However, the number of pulses is always several pulses more than expected. The following is my timer event handler codes, and configurations. The handler will be called every 13us, and basically the test codes send 99 sets of mark and space pairs (mark 500us, space 400us)

void IRsendBase::mark(uint16_t time)
{
  next_target = (2 * time * mFreqKHz) / 1000;
  nrfx_gpiote_out_task_enable(mPinNumber);

  extent += time;
}

void IRsendBase::space(uint16_t time)
{
  next_target = (2 * time * mFreqKHz) / 1000;
  nrfx_gpiote_out_task_disable(mPinNumber);

  extent += time;
}

void IRsendBase::handleTmrEvent(nrf_timer_event_t event_type)
{
  if(NRF_TIMER_EVENT_COMPARE0 == event_type)
  {
    if (next_target == tick_cnt++)
    {
      //    current_cnt = tick_cnt-1;
      // if(send_index == sizeof(data)/2 - 1)
      if (send_index == 99 - 1)
      {
        space(0);
        tick_cnt = 0;
        send_index = 0;
        next_target = 0;
        //      current_cnt = 0;
        nrfx_timer_disable(&gIRLib2SendTimer);
        return;
      }

      if (send_index & 1)
      {
        //      space(data[send_index++]);
        space(400);
      }
      else
      {
        // mark(data[send_index++]);
        mark(500);
      }
      send_index++;
      tick_cnt = 0;
    }
  }
  
}

(code is based on IRLib2 for arduino, but with much different implementation of sending function)

nrfx_gpiote_out_config_t gpiote_config;
gpiote_config.init_state = NRF_GPIOTE_INITIAL_VALUE_LOW;
gpiote_config.task_pin = true;
gpiote_config.action = NRF_GPIOTE_POLARITY_TOGGLE;

Any suggestion is welcomed, or other better solution please advise.

Thanks a lot

Bo

Parents
  • Hi,

    Do you need an exact number of pulses? If so, then you would probably want to handle this in HW using PPI so that it would be deterministic. You could use for instance a timer in counter mode to count pulses and stop the timer when the correct number of pulses has been generated. This requires you to use a GPIOTE input connected to the output pin though, so a better solution could be to simply use a separate timer which is started at the same time as the timer generating the output frequency. Then use that to decide when you should stop, again using PPI.

    If you want to continue doing this in SW you have to account for the delay. However, this may not be deterministic, for instance if you get a higher priority interrupt at a bad time.

Reply
  • Hi,

    Do you need an exact number of pulses? If so, then you would probably want to handle this in HW using PPI so that it would be deterministic. You could use for instance a timer in counter mode to count pulses and stop the timer when the correct number of pulses has been generated. This requires you to use a GPIOTE input connected to the output pin though, so a better solution could be to simply use a separate timer which is started at the same time as the timer generating the output frequency. Then use that to decide when you should stop, again using PPI.

    If you want to continue doing this in SW you have to account for the delay. However, this may not be deterministic, for instance if you get a higher priority interrupt at a bad time.

Children
Related