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

BLE packet delay with wireshark

Dear all,

I'm using nrf52-DK with PCA10040 as sniffer. I develop 2 custom board (nRF52840) (one acting as master, one as slave) and I would like to make some considerations about packets delay. What is the most correct method to do so? I know that the field "time" is the one append by UART and that the most accurate is the field "delta time": so if a I want to calculate delay beetween trasmission and reception, which fields do I have to use?

Moreover, I also tried calculating it putting the packets on 2 different serial port (after the trasmission and the reception), appending a timestamp and post-processing it, but the result (for packet bigger than 50B) is quite strange( figure: /resized-image/__size/320x240/__key/support-attachments/beef5d1b77644c448dabff31668f3a47-0514cb2d3e5046b48f0972c4924097bb/Figure_5F00_1.png). Any ideas about these?

Thanks in advance to everyone!

Parents
  • but the result (for packet bigger than 50B) is quite strange

     What exactly is strange?

    I checked out your graph. What is the X-Axis? Number of bytes in the packet? I don't understand what is strange about it. Is it the steps? How many bytes difference do you use in each sample? Is it the stair shape that you find strange?

    To measure the time between transmission and reception, one thing you can try is to just toggle a pin on the DK when you transmit (right before sd_ble_gatts_hvx()) and toggle a pin when you receive it on the other side, and use a logic analyzer to compare these two signals.

    What exactly is it that you want to measure? I don't know if you are aware about the "connection interval" in BLE and how that works? Basically, the connected devices will only communicate once every connection interval. So you will see a random delay between 0 and <connection_interval> ms.

    BR,

    Edvin

  • Hi Edvin, thanks for the fast reply. I forgot to rename the axis in english. The y-axis is the delay in ms, while the x-axis is only the number of packet (first packet, second packet, ecc ecc), with a payload of length 100B. What is strange for me is that the delay tx/rx improve during the communication, while in theory (as you said) it would be random beetween 0 and <connection_interval> (in the application 7.5 ms). 

    Of course I know about the connection interval and all the related stuff of BLE spec: I'm sending 100B over 1Mbps phy (Data Length extension and ATT_MTU size are set to the maximum, so I can send 100B (I have also debugged it with wireshark).

    The problem is that I can use an oscillosope/instrumentation only 1 times a week, and so I would like to find some strategy to compute the delay in a reliable way.

    So, do you agree with me that the figure is quite strange? With the time field of Wireshark can I compute the delay or only the connection interval?

    In theory with a payload of 100B (total PDU_SIZE = 133B), I will expect a delay around:

    delay = 133*8 = 1064 us

    Is this correct?

    Sorry for the long answer, I think that now it is all more clear.

    Thank you Edvin.

    Elia

  • Elia_pell said:
    What is strange for me is that the delay tx/rx improve during the communication

     Does it improve, or do you mean that it increases?

    If access to an oscilloscope/logic analyzer is a limitation, you can of course try to time this on one of the DKs. Start a timer that is not used by the application or the softdevice (the softdevice uses TIMER0), and sample the TIMER before TX. Then you can toggle a pin on the receiver DK. You can use this as a trigger to capture the TIMER again on the TX board using a breadboard cable. Then compare the two captures, and see how long the time is between the two. 

    If you have 3 DKs, you can run the timer application there, but you should be able to do with just two.

    The time can be measured by something like this:

    // Choose a free timer, e.g. TIMER3 (if it is not used by your application). 
    
    
    void egu_init()
    {
        NVIC_ClearPendingIRQ(SWI1_EGU1_IRQn);
        NVIC_EnableIRQ(SWI1_EGU1_IRQn);
        NRF_EGU1->INTENSET = (1 << 0) | (1 << 1);
    }
    void timer_init()
    {
        NRF_TIMER3->BITMODE                 = TIMER_BITMODE_BITMODE_32Bit << TIMER_BITMODE_BITMODE_Pos;     // 0<<0; = 0 
        NRF_TIMER3->PRESCALER               = 0;                                                            // previously 0;
        //NRF_TIMER3->SHORTS                  = TIMER_SHORTS_COMPARE0_CLEAR_Msk << TIMER_RELOAD_CC_NUM;       // 1<<0; = 1
        NRF_TIMER3->MODE                    = TIMER_MODE_MODE_Timer << TIMER_MODE_MODE_Pos;                 // 0<<0; = 0
        //NRF_TIMER3->CC[TIMER_RELOAD_CC_NUM] = TIMER_RELOAD;                                                 // 1000;
    }
    
    
    void timer_start()
    {
        NRF_TIMER3->TASKS_START = 1;
    }
    
    
    void ppi_init(uint32_t pin_in_select)
    {
        NRF_GPIOTE->CONFIG[0] = GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos |
                                GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos |
                                pin_in_select << GPIOTE_CONFIG_PSEL_Pos;
                                
        NRF_PPI->CH[0].EEP = (uint32_t)&NRF_GPIOTE->EVENTS_IN[0];
        NRF_PPI->CH[0].TEP = NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TIMER3->TASKS_CAPTURE[1];
        NRF_PPI->FORK[0].TEP = (uint32_t)&NRF_EGU1->TASKS_TRIGGER[0];
    }
    
    
    void compare_timers()
    {
        uint32_t time1 = NRF_TIMER3->CC[0];
        uint32_t time2 = NRF_TIMER3->CC[1];
        uint32_t diff_ticks = time2 - time1;
        
        NRF_LOG_INFO("diff ticks: %d", diff_ticks);
        
        //Timer is running at 32MHz, so time_in_ms = diff_ticks/32000;
    }
    
    void SWI1_EGU1_IRQHandler(void) //Used to propagate event to the application
    {
        if (NRF_EGU1->EVENTS_TRIGGERED[0] != 0)
        {
            NRF_EGU1->EVENTS_TRIGGERED[0] = 0;      //Reset event triggered register.
            
            compare_timers();
        }
    }
    
    
    void my_tx_function()
    {
        NRF_TIMER3->TASKS_CAPTURE[0] = 1;
        my_already_implemented_tx_function();
    }
    
    
    

    Note that the reason I am using PPI to read the TIMER registes is that your CPU may be busy doing something else when you receive the pulse on the pin, and ppi allows for this capture to happen without need to wait for the CPU. The EGU is used to propagate this event to the application, so that you can use it to check the difference in time.

    Now, this only show how you can measure, in order to minimize delay in the UART. I still think I don't understand your graph. Is the delay longer and longer for each message? If so, I suspect that there is something weird with your messages.

Reply
  • Elia_pell said:
    What is strange for me is that the delay tx/rx improve during the communication

     Does it improve, or do you mean that it increases?

    If access to an oscilloscope/logic analyzer is a limitation, you can of course try to time this on one of the DKs. Start a timer that is not used by the application or the softdevice (the softdevice uses TIMER0), and sample the TIMER before TX. Then you can toggle a pin on the receiver DK. You can use this as a trigger to capture the TIMER again on the TX board using a breadboard cable. Then compare the two captures, and see how long the time is between the two. 

    If you have 3 DKs, you can run the timer application there, but you should be able to do with just two.

    The time can be measured by something like this:

    // Choose a free timer, e.g. TIMER3 (if it is not used by your application). 
    
    
    void egu_init()
    {
        NVIC_ClearPendingIRQ(SWI1_EGU1_IRQn);
        NVIC_EnableIRQ(SWI1_EGU1_IRQn);
        NRF_EGU1->INTENSET = (1 << 0) | (1 << 1);
    }
    void timer_init()
    {
        NRF_TIMER3->BITMODE                 = TIMER_BITMODE_BITMODE_32Bit << TIMER_BITMODE_BITMODE_Pos;     // 0<<0; = 0 
        NRF_TIMER3->PRESCALER               = 0;                                                            // previously 0;
        //NRF_TIMER3->SHORTS                  = TIMER_SHORTS_COMPARE0_CLEAR_Msk << TIMER_RELOAD_CC_NUM;       // 1<<0; = 1
        NRF_TIMER3->MODE                    = TIMER_MODE_MODE_Timer << TIMER_MODE_MODE_Pos;                 // 0<<0; = 0
        //NRF_TIMER3->CC[TIMER_RELOAD_CC_NUM] = TIMER_RELOAD;                                                 // 1000;
    }
    
    
    void timer_start()
    {
        NRF_TIMER3->TASKS_START = 1;
    }
    
    
    void ppi_init(uint32_t pin_in_select)
    {
        NRF_GPIOTE->CONFIG[0] = GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos |
                                GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos |
                                pin_in_select << GPIOTE_CONFIG_PSEL_Pos;
                                
        NRF_PPI->CH[0].EEP = (uint32_t)&NRF_GPIOTE->EVENTS_IN[0];
        NRF_PPI->CH[0].TEP = NRF_PPI->CH[0].TEP = (uint32_t)&NRF_TIMER3->TASKS_CAPTURE[1];
        NRF_PPI->FORK[0].TEP = (uint32_t)&NRF_EGU1->TASKS_TRIGGER[0];
    }
    
    
    void compare_timers()
    {
        uint32_t time1 = NRF_TIMER3->CC[0];
        uint32_t time2 = NRF_TIMER3->CC[1];
        uint32_t diff_ticks = time2 - time1;
        
        NRF_LOG_INFO("diff ticks: %d", diff_ticks);
        
        //Timer is running at 32MHz, so time_in_ms = diff_ticks/32000;
    }
    
    void SWI1_EGU1_IRQHandler(void) //Used to propagate event to the application
    {
        if (NRF_EGU1->EVENTS_TRIGGERED[0] != 0)
        {
            NRF_EGU1->EVENTS_TRIGGERED[0] = 0;      //Reset event triggered register.
            
            compare_timers();
        }
    }
    
    
    void my_tx_function()
    {
        NRF_TIMER3->TASKS_CAPTURE[0] = 1;
        my_already_implemented_tx_function();
    }
    
    
    

    Note that the reason I am using PPI to read the TIMER registes is that your CPU may be busy doing something else when you receive the pulse on the pin, and ppi allows for this capture to happen without need to wait for the CPU. The EGU is used to propagate this event to the application, so that you can use it to check the difference in time.

    Now, this only show how you can measure, in order to minimize delay in the UART. I still think I don't understand your graph. Is the delay longer and longer for each message? If so, I suspect that there is something weird with your messages.

Children
Related