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

Increase Notification Frequency nrf51422

Hello there,

I'm sending IMU data (16bytes) using a notification from a custom board to a phone. My final goal is to send this packet of data (16 bytes) every 10 milliseconds. My first step was to generate a program that sends a new packet (16 bytes) as soon as the previous one has been sent (waiting for BLE_EVT_TX_COMPLETE)

this is my main.c:

    while(!papaya)getConnected(&papaya); //wait for phone to connect
    waitMS(5000);
    ble_hrs_heart_rate_measurement_send(&m_hrs, data);
    // Enter main loop.
    for (;;)
    {
        while(true){
          collectAvocados(data); //collects data from MPU9250
          while(!avocado)getSent(&avocado); //wait for previous packet to be sent
            ble_hrs_heart_rate_measurement_send(&m_hrs, data);
            avocado = 0;
        }
    }

this is my ble_thingy.c:

void getSent(int *avocado){
  if(flag1 == 1){
    *avocado = 1;
    flag1 = 0;
  }
}
void getConnected(int *papaya){
  if(flag2 == 1){
    *papaya = 1;
  }
}

void ble_hrs_on_ble_evt(ble_hrs_t * p_hrs, ble_evt_t * p_ble_evt)
{
    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            on_connect(p_hrs, p_ble_evt);
            flag2 = 1;
            break;

        case BLE_GAP_EVT_DISCONNECTED:
            on_disconnect(p_hrs, p_ble_evt);
            break;

        case BLE_GATTS_EVT_WRITE:

            on_write(p_hrs, p_ble_evt);
            break;
        case BLE_EVT_TX_COMPLETE :
            flag1 = 1;
            nrf_gpio_pin_set(14);nrf_gpio_pin_clear(14);
        break;
        default:

            // No implementation needed.
            break;
    }
}

If I touch the connection intervals in order to increase the frequency in which the TX buffer is emptied:

#define MIN_CONN_INTERVAL                MSEC_TO_UNITS(10, UNIT_1_25_MS)            /**< Minimum acceptable connection interval (0.4 seconds). */
#define MAX_CONN_INTERVAL                MSEC_TO_UNITS(10, UNIT_1_25_MS)            /**< Maximum acceptable connection interval (0.65 second). */
#define SLAVE_LATENCY                    0                                           /**< Slave latency. */
#define CONN_SUP_TIMEOUT                 MSEC_TO_UNITS(4000, UNIT_10_MS)             /**< Connection supervisory timeout (4 seconds). */

I can see that the frequency in which BLE_EVT_TX_COMPLETE activates is irregular (I use a gpio pin to output this: it changes from time to time) and doesn't happen every 10 ms. Next image is taken by a digital Logic 8 analyser: 

(Time between frames: 0.135s, 0.18s, 0.0897s, etc.)

How can I increase the frequency of my notification using a correct method that allows me to send 1 packet every 10ms?

ble_hrs.zip

main.c

Parents
  • Can you try to use nrf_gpio_pin_toggle(14); instead of nrf_gpio_pin_set(14);nrf_gpio_pin_clear(14);

    I have a feeling that the pin toggling is too fast for the logic analyzer

  • I tried what you proposed. Toggle extends the time to '1' of the gpio, but the period is still way far from 10 ms and it is not constant: 90ms, 90ms, 90ms, 135ms 90ms, 90ms 90ms, 90ms, 90ms, 135ms, 

  • Are you sure the connection interval is actually 10ms? In the end it is the central device that decides the connection interval. If you connect using nRF Connect, you can set the connection interval directly. Click on the settings icon -> Update connection.

  • For the moment I'm testing my code using the nRF51 DK board by connecting it with my phone. On the nrfConnect mobile app, I found "Request connection priority" which can be set HIGH (11.25-15ms), BALANCED(30-50ms), LOW POWER(100-125ms). After I set to HIGH option, I can see through the gpio pin that TX speed has increased from 90 ms to 30 ms. However, I'm still getting variations on the sending frequency (Sometimes is not 30 ms interval but 60.3 or 45.4ms):

    I understand the period of BLE_EVT_TX_COMPLETE may not be the adequated because of my central's configuration, but what I don't understand is the variations on the sending frequency. Do you think may be a central problem or the peripheral is not well configured? (I'm uploading my peripheral main.c and service (I used a modified version of the ble_hrs file) to the post)

    ps. Thank you for helping me solve this problem, I've spent so many hours and I'm running out of ideas to  solve this issue :)

  • So the peripheral device is the slave device when you look at the physical radio layer. This means that RX is turned on first, then TX. What happens is that it transmits on TX, waits one connection interval, it gets the ACK on RX, which is the BLE_EVT_TX_COMPLETE event. By the time the application finishes setting up the notification packet, the radio has already transmitted an empty packet on TX, and is waiting for the next connection interval to transmit the notification packet.

    So the method takes two connection intervals to transmit the packet. So when you connect to the cell phone it sets the interval to 15ms. This goes up into 30ms (every other connection interval), 45ms and 60ms. The reason why it's not consistent on 30ms is because you get packet loss, which happens from time to time, and a retransmission of the last packet.

    You can try to use radio notifications instead. With radio notifications you can set it up to trigger on an event X number of milliseconds before the actual radio event (connection event) and call the hrs send function.

    You should also look into using the nRF sniffer. It's a great tool for debugging. It allows you to sniff the packets on air, so you can see what is actually going on.

Reply
  • So the peripheral device is the slave device when you look at the physical radio layer. This means that RX is turned on first, then TX. What happens is that it transmits on TX, waits one connection interval, it gets the ACK on RX, which is the BLE_EVT_TX_COMPLETE event. By the time the application finishes setting up the notification packet, the radio has already transmitted an empty packet on TX, and is waiting for the next connection interval to transmit the notification packet.

    So the method takes two connection intervals to transmit the packet. So when you connect to the cell phone it sets the interval to 15ms. This goes up into 30ms (every other connection interval), 45ms and 60ms. The reason why it's not consistent on 30ms is because you get packet loss, which happens from time to time, and a retransmission of the last packet.

    You can try to use radio notifications instead. With radio notifications you can set it up to trigger on an event X number of milliseconds before the actual radio event (connection event) and call the hrs send function.

    You should also look into using the nRF sniffer. It's a great tool for debugging. It allows you to sniff the packets on air, so you can see what is actually going on.

Children
No Data
Related