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

Directly modify Link Layer packet

Hello, 

I am very new to BLE and NRF and trying to understand what the best way would be to send data from one device to another

From the documentation and messing around with ble_app_blinky on my nrf52833 DK as I understand it there is a Link Layer that is responsible for advertising and establishing connection. Once the connection is established the one device sends 27-byte data payload packet and gets a response from the other at an established interval. 

With the nrf sdk how to I directly modify the 27 byte payload?

All the examples in the SDK seem to set up a GATT as a data model but I would like to simply access the 27 byte payload on one nrf52833 DK, put my own 27 bytes into it and receive it on another nrf52833 DK. As I understand this would allow for the highest throughput and eliminate any overhead from the higher layers.

  • Hi,

    BLE 4.2 and upper allows you to enlarge your payload up to 247 bytes, allowing throughput close to theoretical maximum. Also you can use custom upper-layer protocol instead of GATT with L2CAP connection-oriented channels. Another way is to use some protocol with lower overhead, for example esb.

  • Hi Dmitry, thanks for your quick response, the L2CAP information is very helpful

    After reading more about L2CAP it seems that basic L2CAP frames will allow for the smallest overhead while still supporting connection to a BLE device. Carefully setting up the L2CAP MTU will avoid data fragmentation. 

    For example lets say I have a data packet of 32 bytes. I can set up Link Layer payload to be 36 octets

    //From att_mtu_throughput example
    err_code = nrf_ble_gatt_data_length_set(&m_gatt, BLE_CONN_HANDLE_INVALID, 36

    then use basic L2CAP which will have a 4 octet header (Length = 32, Channel ID = 0x0001 - 0x007F) and my 32 bytes of data.

    ESB seems very close to what I need, unfortunately it only supports up to 8 devices. I am looking for up to 12.

    My end goal is to have multiple devices that sample 32 bytes of data at 100Hz to stream that data to a single central device. I though I could set the connection interval to 10ms and directly set up the Link Layer MTU to be 32 bytes and just put the data in. However it seems there is no direct access to the Link Layer packet. So as I understand it L2CAP will give me the smallest overhead. For example I can set the connection interval to 20ms, set the Link Layer MTU to be 68 bytes then set up L2CAP on each device with Length 64 and different channel IDs. Finally on each device I put together 2 32 byte data samples and they get sent. Is my thinking correct that this will maximize throughput from multiple devices to a single one?

    Is there an L2CAP example using the sdk? I only found ones using GATT. 

    Thanks a ton

  • Hi,

    there is an object transfer service example that uses L2CAP channels. I don't have any experience with them, sorry.

    You missed another thing: minimal event length for BLE is 2.5ms, thus you cannot have 50 events for 12 different devices per second, you're limited with 400 events/sec. Samples will be grouped by two packets in a connection interval, so it's better to send 128 bytes at once. I don't think you can win anything with L2CAP channels.

  • You can find various throughput numbers here depending on configuration:
    https://infocenter.nordicsemi.com/topic/sds_s140/SDS/s1xx/ble_data_throughput/ble_data_throughput.html 

    As you can see you may get slightly higher throughput (e.g. 771.1 kbps -> 803 kbps). However, whether it is worth the additional development time to get it right (firmware and application), and the drawback of likely not being compatible with many phone vendors I will let be up for discussion.

    If you need multiple links please check out:
    https://infocenter.nordicsemi.com/topic/sds_s140/SDS/s1xx/multilink_scheduling/suggested_intervals_windows_s132.html 

    Best regards,
    Kenneth

  • Hi Kenneth, thanks a lot, I think I am getting closer to understanding the possible throughput for my case and BLE in general.

    Looking at the throughput tables I think I can correctly calculate theoretical maximum for some of the table. Here is my thinking:

    Connection interval is time between two data transfer events, event length is how long the data transfer event is. Minimal event length is 2.5ms during which 2 Link Layer packets get transferred. 

    This lines up with the throughput numbers you provided for some rows of the table, for example with a connection interval of 7.5ms

    Protocol ATT MTU size Event length Method Maximum data throughput (LE 1M PHY) Maximum data throughput (LE 2M PHY)
    GATT SERVER 23 2.5ms Send Notification 42.6kbps

    To calculate the 42.6kbps we have 1000/7.5 =133.333 connections per second. Each connection has one event of 2.5ms. During each event 2 Link Layer packets are transferred. Each packet has 23-3 bytes payload. 

    So we will have 1000/7.5*2 packets transfered, since each packet has (23-3) bytes of payload we can calculate the throughput in bps as 1000/7.5*2*(23-3)*8 = 42.6kbps. 

    However I must be missing something since this does not work for other rows of the table when we have event length larger than 2.5ms. For example: 

    GATT Client 23 7.5 ms Receive Notification 192.0 kbps 256.0 kbps

    I was thinking now since event length is 7.5 instead of 2.5 we will send 3 times as many Link Layer packets however

    1000/7.5*2*(23-3)*8*3 = 128.0kbps and not 192.

    Also as I understand BLE is 1MBPS using LE 1M PHY, at 1MBPS each bit takes a microsecond. so 2500 bits can be send in a 2.5ms interval. For ATT MTU size of 158 as in the table does this mean only 1 Link Layer packet is sent every 2.5ms since the number of bits in two packets 158*2*8 is just a little larger than 2500? How is the row with 158 ATT_MTU computed?

    GATT Server 158 7.5 ms Send Notification 248.0 kbps 330.6 kbps

    Following last table it seems that for 12 devices at a connection interval of 40ms, event length of 2.5, and ATT_MTU 158 assuming only 1 Link Layer packet gets sent per event I can get a theoretical throughput of 1000/40*(158-3) = 3875 bytes per second. Since the events would not overlap.

Related