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

Notification timing not correct.

Hello Devzone,

I've been working on a system to set notifications on time ready for transmission.

The client sends a WWR package to my peripheral and I want my peripheral to send a notification back in the same connection interval.

The client and peripheral both have a 7.5ms min and max connection interval.

To my knowledge a notification has to be set before the transmission moment occurs.

My approach is to have one free running timer captured as soon as I get the WWR message, I'll add that captured value with x (roughly 6ms in timer ticks) to a new compare register to create an event to set a notification ready for the next connection interval.

When the compare event strikes I do a sd_ble_gatts_hvx(....) and set my notification ready.

I've added a picture to help understand what I'm trying to achieve. 

The problem I'm having is that the notification is not send as I pictured here.

Instead the notification is set at the right time but instead of being transmitted in the following connection interval, it is being transmitted in the connection interval after the intended interval.

I've tried changing the time for when the notification is set ready for transmission but this either resulted in ERROR_NO_RESOURCES or in the same behavior.

When I change the WWR and notification time so it is transmitted every 15ms instead of 7.5ms I get the following behavior.

This is really bugging me and I cannot find what I'm doing wrong here.  

Can anyone help me with my struggles?

Kind regards

Parents
  • Hello,

    Remember that you can queue packets at any time. If they are queued enough time before the next connection event, it will be transmitted that event. If it is queued too late, the softdevice doesn't have time to process the packet, and it will be sent the next event instead.

    Have you tried queuing the packet directly after the previous notification was sent (and you get the TX_COMPLETE event). In that case it should be sent the very next connection event.

    An alternative is to use something called radio notifications, whic is a module that makes it possible to get events a given amount of time before the next connection event. 

    Please check out this guide for how to setup and use radio notifications:

    https://devzone.nordicsemi.com/nordic/short-range-guides/b/software-development-kit/posts/radio-notification

    What you are probably seeing is that you start an app_timer right after a connection event. This timer will not be started until the softdevice is done, so perhaps you queue it too late? How much data do you send before you start the timer? If you have enabled data length extension and event length this may actually take a lot of time.

    I suggest either using the TX_COMPLETE event (called BLE_GATTS_EVT_HVN_TX_COMPLETE. Add this to your ble_evt_handler) to queue the next notification, or look into using the radio notifications, and experiment with different timings (NRF_RADIO_NOTIFICATION_DISTANCE_800US). Depending on how much data you queue, you need a different amount of time.

    Best regards,

    Edvin

  • Hello Edvin,

    Even if I queue my notification right after it is being sent I still get the the same problem. I have changed the wait value from 1ms to 6ms with 500us increments but it didnt help at all.

    I do not use an app_timer, I have configured NRF_TIMER2 to be free running from the start. I use PPI and the EGU to trigger my events and tasks. 

    The data length of my notification is 100 bytes and I have set data length extension correctly.

    I use the BLE_GATTS_EVT_HVN_TX_COMPLETE event in addition to my timers (logical OR from events) to trigger writing the notification.

    The thing is that I cannot explain what is going on in picture 2 and 3 in my original post.

  • What chip, Softdevice and SDK version do you use?

    I read through your description again, and I realize that you want to react on an incoming (RRW) packet, and send the reply in the next interval, right?

    Have you tried to call the sd_ble_gatts_hvx() in the event when you receive the data from the central? I did that as a test, and I see from the sniffer trace that in this case, the peripheral will send the reply in the next connection event:

    Is there a reason for why you need to wait using a timer before calling sd_ble_gatts_hvx()?

    Best regards,

    Edvin

  • The chip is nRF52832, SD 132 and SDK 15.0

    I read through your description again, and I realize that you want to react on an incoming (RRW) packet, and send the reply in the next interval, right?

    This is correct. I want to use this WWR event to set data ready for the next time that a WWR occurs. 

    Is there a reason for why you need to wait using a timer before calling sd_ble_gatts_hvx()?

    I need to wait with calling sd_ble_gatts_hvx because our goal is to have up to 6 devices connected to the client, all receiving a WWR and all have to respond with a notification.In the mean time a peripheral is gathering data that has to be transmitted after the WWR is received.

    I want the data that the peripheral is gathering to be as recent as possible.

    If I delay that notification in the next connection interval I have 90ms of data to be transmitted instead of the 45ms data I intent to send.

Reply
  • The chip is nRF52832, SD 132 and SDK 15.0

    I read through your description again, and I realize that you want to react on an incoming (RRW) packet, and send the reply in the next interval, right?

    This is correct. I want to use this WWR event to set data ready for the next time that a WWR occurs. 

    Is there a reason for why you need to wait using a timer before calling sd_ble_gatts_hvx()?

    I need to wait with calling sd_ble_gatts_hvx because our goal is to have up to 6 devices connected to the client, all receiving a WWR and all have to respond with a notification.In the mean time a peripheral is gathering data that has to be transmitted after the WWR is received.

    I want the data that the peripheral is gathering to be as recent as possible.

    If I delay that notification in the next connection interval I have 90ms of data to be transmitted instead of the 45ms data I intent to send.

Children
  • Well. if the hvx softdevice call is too close to the next event, then the packet will not be sent until the next event after that. I am not sure I understood your explanation. Perhaps you can try to read out the TIMER counter in your timeout callback to see how much time has passed since the actual timeout to see if it is before or after the next connection event. Also, how do you gather this data? I presume this takes some time as well? More than one connection interval? More than the time from your timeout until the connection interval is over?

    Did you look into the radio notifications module? This event will be before the radio event.

    BR,
    Edvin

  • I haven't checked out the radio notification module yet. 

    I have a capture in almost every state between receiving the WWR, transmitting the notification and setting the notification ready for the next interval and all are within the connection interval time.

    WWR triggered at 0ms
    Notification sent at ~600us after

    Notification set at 6ms after the WWR.

    WWR triggered at 7.5ms

    no notification sent here.

    Notification set at 13.5ms

    ....

    The strangest thing I've seen is that if I keep the peripheral side the same and do not send WWR's it does send notifications every 7.5ms

  • Ive made an Excel sheet with some information about the timing if that helps.

  • After doing some more testing I've found out that the HVX complete event is set after the connection interval. Please correct me if I'm wrong.

    By trying to set a new notification before this event happened I probably got the message NO_RESOURCES. So does this mean I am unable to send a WWR + notification every connection interval?

  • You don't need to wait for a notification to send a WWR. But of course, if your WWR depends on the content of the notification, you need to do so. As I mentioned in the beginning of this post, I tested this using the ble_app_uart and ble_app_uart_c together, and then I send some data (WWR) in the notification event directly. This was sent the very next connection interval. Have you tried this?

Related