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

SDK 11 app_timer inaccurate

I need an accurate timer to generate pulses about 20ms. With simple timer this is workiong fine, but I need more then one timer simultaneously. So I would like to use app_timer. I do not need a SD. And I do not need external crystal(only the internal RC). I'm working with SDK 11.

When I use the app_timer I will get this:

image description

Its always the same timer. (The low pulse have to be 20 ms). The low pulse duration is always random different. Why? I know from the previous application on nRF51 that the timers are very accurate.

This is how I setup the timer

APP_TIMER_DEF(m_box_timer);

#define APP_TIMER_PRESCALER             2    // Value of the RTC1 PRESCALER register.

#define APP_TIMER_OP_QUEUE_SIZE         3    // Size of timer operation queues.

static void lfclk_request(void)
{
    uint32_t err_code = nrf_drv_clock_init();
    APP_ERROR_CHECK(err_code);
    nrf_drv_clock_lfclk_request(NULL);
}

static void create_timers()
{   
    uint32_t err_code;

    err_code = app_timer_create(&m_box_timer,APP_TIMER_MODE_REPEATED,timeout_handler);

    APP_ERROR_CHECK(err_code);   
}

Start timer:

app_timer_start(m_box_timer, APP_TIMER_TICKS(20, APP_TIMER_PRESCALER), NULL);

In Main:

lfclk_request();
APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false);
create_timers();

in nrf_drv_config.h file:

#define CLOCK_ENABLED 1

#if (CLOCK_ENABLED == 1)
#define CLOCK_CONFIG_XTAL_FREQ          NRF_CLOCK_XTALFREQ_Default
#define CLOCK_CONFIG_LF_SRC             NRF_CLOCK_LFCLK_RC
#define CLOCK_CONFIG_IRQ_PRIORITY       APP_IRQ_PRIORITY_LOW
#endif

#define TIMER1_ENABLED 1

#if (TIMER1_ENABLED == 1)
#define TIMER1_CONFIG_FREQUENCY    NRF_TIMER_FREQ_1MHz
#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

I'm sure that I can have accurate app_timer without external crystal. But why do I get random timeout times?

Is there an example with app_timer for peripheral projects in SDK11?

Any help?

ADD Here will be the timer started:

if((data_array[index - 1] == '\n') || (index >= (3)))
{
   if(data_array[0] == 0x53 && data_array[1] == 0x31)
   {
      Box1Schloss();
   }
}

void Box1Schloss(void)
{
  app_simple_timer_start(APP_SIMPLE_TIMER_MODE_SINGLE_SHOT, timeout_handler, 65000, NULL);            
  //app_timer_start(m_box_timer, APP_TIMER_TICKS(100, APP_TIMER_PRESCALER), NULL);
  nrf_gpio_pin_set(BOX1_SCHLOSS);
}

void timeout_handler(void * p_context)
{                                                                                                  
   nrf_gpio_pin_clear(BOX1_SCHLOSS);
}
  • nowhere in that code shows what you're doing in the timer handler or what generates the other piece of the pulse, if you have a low and a high, you need two timers .. unless something else is triggering the high to low transition. You've posted code, but not really the relevant code and have left out too many details to be really useful.

  • The high time is not relevant. I have an UART connection which will fire a timer when I recieve an S1. After S1 is recieved over UART, I have to set a GPIO for min. 20ms low. After this 20 ms the GPIO has to be High again. I will add this part of the code to this post.

  • it's very relevant and leads me to suspect that you don't want a repeating timer for the low pulse timout.

    you can't tell from the trace which is in seconds but I would guess that all your low-to-high transitions are exact multiples of 20ms apart from each other.

  • Your assumption is right. I want a singleshot timer. I send the S1 command randomly over an terminal program to chip. So the time when the pin is High is not relevant

  • Hi Inspectron

    You need to periodically calibrate the lfclk RC, otherwise it is going to be fairly inaccurate. When the lfclk RC is calibrated, the accuracy should be within 250ppm. I have created an example that uses app timer to generate interrupts. The example does not use softdevice, but instead manually starts the lfclk and calibrates it periodically. I have measured the timing accuracy of the interrupts, and they seem to be acceptable. Instruction on how to operate the example is given at the top of the main.c file in the example.

    app_timer_example.zip

    Having that said, I don't think the large timing variation in your case is because of lack of calibration. The variation is too large. I suspect that the application timer interrupt is occasionally blocked because of something else happening in your application. That could be fixed with raising the priority of the RTC1 interrupt, which application timer library uses in the background. But that may also not be convenient as you will raise the priority of all your timers.

    Since you are not using softdevice, RTC0 should be free to use for anything that needs more accurate timing. You could raise the priority of the RTC0, but still have the RTC1 interrupt priority low for application timers.

Related