I need accurace timer.

Hello everybody!

There is a problem and help is needed.

With the help of hardware timers, I need to generate a signal with a given accuracy. The frequency is 998 Hz. I'm using an example from ncs NRFX-timer. The timer does not fire at one point in time. There is a spread. How can I fix it? The picture shows the variation of the timer trigger time. I am changing the GPIO state in an interrupt. How do I get maximum accuracy?

  • Hello Mikhail,
    Just to see if I understand your picture correctly, you set the GPIO high at T0 and then expect the GPIO to go low after the same amount of time which would be 1/998Hz = 1.002004ms? But you see the IRQ to set it low is varying? The timing between each HIGH is stable and at the right interval?
    Which timer are you using and what is the clock source? How have you configured the timer itself? Are you using PPI to change the GPIO state?
    Best regards
    Asbjørn 
  • Hello Asbjørn. Thanks for your interest!

    I am using the nordic code of the nrfx_timer example
    to receive an interrupt with an accurate time interval.
    Here I change the pin state via gpio_pin_toggle_dt(&timerr_);
    But unfortunately I get different time intervals between interrupts.
    I did not use PPI. Can you please advise me how to look at an example with PPI?
    The code is applied.

    Best wishes!


    prj.conf

    CONFIG_NRFX_TIMER1=y


    main.cpp


    static constexpr std::uint32_t FrequencyToTicks(float frequency) {
    NRFX_ASSERT(frequency >= 0.1F && frequency < 1000.F); // NOLINT
    constexpr double TIMER_TICK_DURATION_NS{62.5};
    constexpr double COEFFICIENT{config::CONVERT_FREQ_COEFFICIENT}; // NOLINT
    const double periodNs{static_cast<double>(1e9 / frequency)};
    return static_cast<std::uint32_t>(
    (periodNs / TIMER_TICK_DURATION_NS) * COEFFICIENT);
    }



    #include <nrfx_timer.h>

    #define TIMER_INST_IDX 1


    #define TIMERR DT_ALIAS(timerr)
    const struct gpio_dt_spec timerr_ = GPIO_DT_SPEC_GET(TIMERR, gpios);

    static void timer_handler(nrf_timer_event_t event_type, void * p_context)
    {
    if(event_type == NRF_TIMER_EVENT_COMPARE0)
    {
    gpio_pin_toggle_dt(&timerr_);
    }
    }

    int main()
    {
    nrfx_err_t status;
    (void)status;

    LOG_INF("Starting nrfx_timer basic example:");

    if (!gpio_is_ready_dt(&timerr_)) {
    NRFX_ASSERT(false);
    }
    if (int ret = gpio_pin_configure_dt(&timerr_, GPIO_OUTPUT); ret < 0) {
    NRFX_ASSERT(false);
    }

    nrfx_timer_t timer_inst = NRFX_TIMER_INSTANCE(TIMER_INST_IDX);
    uint32_t base_frequency = NRF_TIMER_BASE_FREQUENCY_GET(timer_inst.p_reg);
    nrfx_timer_config_t config = NRFX_TIMER_DEFAULT_CONFIG(base_frequency);
    config.mode = NRF_TIMER_MODE_TIMER;
    config.bit_width = NRF_TIMER_BIT_WIDTH_32;
    config.p_context = nullptr;
    status = nrfx_timer_init(&timer_inst, &config, timer_handler);
    NRFX_ASSERT(status == NRFX_SUCCESS);

    #if defined(__ZEPHYR__)
    IRQ_DIRECT_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_TIMER_INST_GET(TIMER_INST_IDX)), IRQ_PRIO_LOWEST,
    NRFX_TIMER_INST_HANDLER_GET(TIMER_INST_IDX), 0);
    #endif

    nrfx_timer_clear(&timer_inst);
    uint32_t desired_ticks = FrequencyToTicks(998.0F) / 2UL;

    nrfx_timer_extended_compare(&timer_inst, NRF_TIMER_CC_CHANNEL0, desired_ticks,
    NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
    nrfx_timer_enable(&timer_inst);

    while (1)
    {
    k_sleep(K_MSEC(500UL));
    }
    }
  • Hi Mikhael
    I'd recommend you to have a look at the example to set up example with ppi and the timer. It also does and ADC reading, but you can disreagard that and have a look at the timer and ppi configuration.
    I asked if you see the correct timing on the start (rise) event every time and if it's only when the GPIO is set low IRQ that is varying? As it seems from the screen capture it's only the timing for the transition from HIGH to LOW that is shifting and changing. 
    Best regards
    Asbjørn
  • Asbjørn, Thank you!

    The PPI was the answer to my problem.

    Best regards
    Mikhail
Related