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

How to get the time difference between each TWI sensor measurement (microsecond-level)

Hi, I'm using an nRF52805 TWI sensor (400kHz, 1 complete received data is 9 bytes = 72 bits). The ideal time difference between each TWI sensor measurement is 72bits/400kHz = 18us. 

Because my code contains TWI (low priority), SAADC and BLE, so TWI will be interrupted by other functions occasionally. The time difference between each received TWI measurement might be slightly different. I need a method to get the time difference (us level) between each TWI measurement. 

What's the best way to do it, please? Could you provide any example code, please? 

Thanks! 

Parents
  • If you have a timer running in parallell, then the simplest may be to create a ppi channel between the twi stopped event and the timer capture task. Every time the CAPTURE[n] task is triggered, the Counter value is copied to the CC[n] register. You can then read out the counter value from the CC register of the timer between twi transfers.

    For more accurate timing of transfers you may consider to do the opposite, e.g. you can setup a timer to trigger twi transfers, such that on every timer compare event you can have a ppi channel that start the twi transfer, this will ensure you always transfer twi every 18us. You can find that the \peripheral\saadc example in the nRF5 SDK show this, but instead of starting SAADC you will need to start TWI.

    Kenneth

  • Thank you very much, Kenneth, 

    I have a few more questions for nRF52805: 

    1) On my custom board, I don't have external clock. So my nRF52805 only has a 64MHZ system clock and 32.768kHz LFCLK. My TWI sensor operates at 400kHz, so it must use 64MHz HFCLK. However, if you look at twi_sensor SDK example, there is no code to define the timer/clock for TWI. So how could the chip know TWI should use 64MHz? I mean, which code defines the clock for TWI? 

    2) I already used a 1MHz timer1 for SAADC PPI interrupt every 50ms. Could I also use this timer1 for TWI PPI interruption every 1ms? 

    3) I want to use timer1 to check that my SAADC PPI interrupt is 50ms correctly. However, on PuTTY, the printed time duration value is about 860, or 17, or just 0 (see screenshot). Sometimes, even negative values. My timer1 is 1MHz, timer mode, 32-bit, priority 6. According to my code, the duration value is in the unit of millisecond already, right? Are the wrong values caused by overflow? How to solve it, please? Here is a part of my code: 

    void saadc_sampling_event_init(void)
    {
        ret_code_t err_code;
        // Initial PPI
        err_code = nrf_drv_ppi_init();
        APP_ERROR_CHECK(err_code);
        
        // Configure and initial timer 1
        // Open sdk_config.h to modify the NRF_DRV_TIMER_DEFAULT_CONFIG
        // Settings: 1MHz clock, timer mode, 32-bit, priority 6
        nrf_drv_timer_config_t timer_config = NRF_DRV_TIMER_DEFAULT_CONFIG;
        timer_config.frequency = NRF_TIMER_FREQ_1MHz;
    
        err_code = nrf_drv_timer_init(&m_timer, &timer_config, timer_handler);
        APP_ERROR_CHECK(err_code);
    
        /* setup m_timer for compare event */
        // Convert timer value to the # of ticks
        // Compare timer(i.e. # of ticks) with user-defined time interval
        uint32_t ticks = nrf_drv_timer_ms_to_ticks(&m_timer,SAADC_SAMPLE_RATE);
        // Clear the timer eveytime when the counter reaches the user-defined time interval
        nrf_drv_timer_extended_compare(&m_timer, NRF_TIMER_CC_CHANNEL0, ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false);
        nrf_drv_timer_enable(&m_timer);
        
        // Get timer event and SAADC event address for PPI 
        uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer, NRF_TIMER_CC_CHANNEL0);
        uint32_t saadc_sample_event_addr = nrf_drv_saadc_sample_task_get();
    
        /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
        err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
        APP_ERROR_CHECK(err_code);
        
        // Time-based interrupt: Timer Event --> PPI --> SAADC Task
        err_code = nrf_drv_ppi_channel_assign(m_ppi_channel, timer_compare_event_addr, saadc_sample_event_addr);
        APP_ERROR_CHECK(err_code);
    }
    
    
    
    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {
            
            uint32_t t1 = t2;
            uint32_t t2 = nrf_drv_timer_capture(&m_timer,NRF_TIMER_CC_CHANNEL0);
            uint32_t duration = t2-t1;
            printf("Duration = %d\r\n",duration);
            
            ...
            ...
        }
    }
    
    

    Thanks! 

  • 1. The clock frequency is set by the FREQUENCY register (it's derived from the HFCLK internally, so you only need to set the register):
    https://infocenter.nordicsemi.com/topic/ps_nrf52805/twim.html#register.FREQUENCY

    2. I assume the timer is setup to clear on 50ms, I don't see an easy way for the same timer to generate both 1ms and 50ms. Unless you update the timer every 1ms.

    3. Try to make the variables static, e.g. uint32_t static t2 (else t2 will likely be random).

    Kenneth

  • Thank you very much, Kenneth. Nordic is so helpful and professional! 

    As shown in the code, I have included uint32_t static t2, and I tried to print the timer1 value right after saadc_callback (interrupt every 50ms by PPI).

    uint32_t static t;
    
    ...
    ...
    
    
    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
        t = nrf_drv_timer_capture(&m_timer,NRF_TIMER_CC_CHANNEL0);
        printf("%d\r\n",t);
    
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {
          
          ...
          ...
        }
    }

    Q1)

    In theory, every time when the 1MHz timer1 reaches 50ms, timer1 gets cleared (i.e. timer1 value = 0). But why on PuTTY, the printed value is NOT always 0? Here are some printed timer1 values on PuTTY: 

    17
    0
    371
    17
    0
    372
    17
    0
    401
    17
    0
    395
    17
    0
    378
    17
    0
    405
    17
    0
    417
    17
    0
    370
    17
    0
    397
    17
    0
    372
    17
    0
    368
    17
    0
    371
    17
    0
    372
    17
    0
    366
    17
    0
    372
    29
    17
    0
    372
    17
    10
    0
    10
    0
    10
    0
    10
    0
    10
    0
    10
    0
    10
    0
    10
    0
    10
    0
    10
    0
    10
    0
    10
    0
    10
    0
    10
    0
    10
    0
    10
    0
    10
    0
    10
    0
    10
    0
    10
    0
    10
    0
    10
    0
    10
    0
    10
    0
    10
    0
    10

    Q2)

    Also, I would like to check that the timer1 PPI interruption is 50ms. How could I print the time1 value right before the interruption, please? 

    Q3) 

    My timer1 is 1MHz, 32-bit. Does that mean 1 tick = 1us, the max tick value is 2^32 = 4294967296? 

    If I change the timer1 to 125kHz and 8-bit, so 1 tick will be 1/125kHz = 8us, and the max tick value = 2^8 = 256 ticks = 2048 us, right? 

    Thanks again, Kenneth!  

  • In the saadc_callback() can you also print out the event type? 

    I suggest to get a logic analyzer or oscilloscope so you can measure the actual timing here.

    Kenneth

Reply Children
No Data
Related