Timer 2 Capture at Low Frequency Input

I am currently using a Capture Event on Timer 2. I will post my initialization code for that event. I am sending a square wave (incoming wave is 10Vpp with a 2.5 V offset and 50% duty cycle signaled down to a 3V input for the nrf52832 GPIOTE input) to mimic a car's speed and tachometer sensor to translate the timer ticks into a car speed in mph or engines revs in rpm. At frequencies below 50 Hz, the timer seems to capture at times inconsistent values, causing the pointer to jump erratically before stabilizing. At frequencies above 50 Hz, I do not have this issue. Any reason why these low frequencies could be causing this? I have scoped the incoming signal and it is smooth and consistent, so no issues there. The period of the incoming signal becomes jumpy at these lower frequencies.  

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//setup a timer for Speedo/Tach pulses
nrf_drv_timer_config_t timer_cfg2 = NRF_DRV_TIMER_DEFAULT_CONFIG; //default settings should use NRF_TIMER_FREQ_8MHz, changable in sdk_config.h
timer_cfg2.frequency = NRF_TIMER_FREQ_8MHz;
timer_cfg2.interrupt_priority = APP_IRQ_PRIORITY_HIGH;
err_code = nrf_drv_timer_init(&system_timer_cc_0_2, &timer_cfg2, system_timer_cc_0_2_handler);
APP_ERROR_CHECK(err_code);
//set up timer compare on CC[1] for overflow on Timer 2, SPD_COUNT_MAX = 66535 for 16bit timing
nrf_drv_timer_extended_compare(&system_timer_cc_0_2, NRF_TIMER_CC_CHANNEL1,SPD_COUNT_MAX, NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK, true);
system_timer_cc_0_1_init(); //setup system timer 1 events and tasks
system_timer_cc_0_2_init(); //setup system timer 2 events and tasks
void system_timer_cc_0_2_init(void)
{
uint32_t capture_task_addr;
uint32_t compare_evt_addr;
uint32_t gpiote_task_addr;
uint32_t time_ticks;
ret_code_t err_code;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Parents Reply Children
  • Yes that is true. The issue starts to occur around 50 Hz and below. There is a single jumpy reading causing the RPM's to spike, but then it recovers and stays consistent. 

  • I unfortunately don't have time to try out your code, but an alternative you may consider is to connect&use the pin as a counter for e.g. timer4, and then you only instead peridically check the counter value of timer4 from another timer (running of 16MHz clock, e.g. every 10ms) to find how many counts have elasped during the 10ms period.

    Kenneth

  • Are you saying to set up Timer2 as a counter and use the app timer to check every 10ms? Or set up Timer 2 as a counter and then set up another hardware timer to check?

  • Both can work, but my suggestion was the second one.

    Kenneth

  • I have it set up as follows to stop the first timer after 100ms and capture the value of the second timer (pulse counter). The CC value is always 0 and is not recording the pulses now. 

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    //setup a timer for Speedo/Tach pulses
    nrf_drv_timer_config_t timer_cfg2 = NRF_DRV_TIMER_DEFAULT_CONFIG; //default settings should use NRF_TIMER_FREQ_8MHz, changable in sdk_config.h
    timer_cfg2.frequency = NRF_TIMER_FREQ_62500Hz;
    timer_cfg2.bit_width = NRF_TIMER_BIT_WIDTH_16;
    timer_cfg2.interrupt_priority = APP_IRQ_PRIORITY_HIGH;
    err_code = nrf_drv_timer_init(&system_timer_cc_0_2, &timer_cfg2, system_timer_cc_0_2_handler);
    APP_ERROR_CHECK(err_code);
    //set up timer compare on CC[1] for 100ms interval on Timer 2
    nrf_drv_timer_extended_compare(&system_timer_cc_0_2, NRF_TIMER_CC_CHANNEL1, PULSE_READ_INTERVAL, NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK, true);
    //setup a counter for Speedo/Tach pulses
    nrf_drv_timer_config_t timer_cfg3 = NRF_DRV_TIMER_DEFAULT_CONFIG; //default settings should use NRF_TIMER_FREQ_8MHz, changable in sdk_config.h
    timer_cfg3.bit_width = NRF_TIMER_BIT_WIDTH_32;
    timer_cfg3.mode = NRF_TIMER_MODE_LOW_POWER_COUNTER;
    timer_cfg3.interrupt_priority = APP_IRQ_PRIORITY_HIGH;
    err_code = nrf_drv_timer_init(&system_timer_cc_0_3, &timer_cfg3, system_timer_cc_0_3_handler);
    APP_ERROR_CHECK(err_code);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX