cancel
Showing results for 
Search instead for 
Did you mean: 

How to send data at high speed via BLE

popfan
Associate
I need to send about 20K bytes of data per second over BLE (by STM32WB55), currently I am using the Custom_STM_App_Update_Char() function, which sends 148 Bytes each time, I using the following code:

 

while(dataRemain > 0){ Custom_STM_App_Update_Char( CUSTOM_STM_SENSORREAD, &audioSend[dataIndex] ); // each time send 48*2 = 148 bytes dataIndex = dataIndex + CHUNK_SIZE; dataRemain = dataRemain - CHUNK_SIZE; }

 

Unfortunately, on the receiving side, I can only receive 148*5 Bytes of data per second, which means only 5 frames.
So,what should I do to solve my problem? How can I make sure that I can send and receive all the data?

Code formatting applied - please see How to insert source code for future reference.
6 REPLIES 6
EJD1962
Associate II

I have some recent experience trying to get higher speed data transmissions using BLE, and I can share what I have learned.   I confess I have not achieved anything like the maximum rate I thought (and continue to think) should be possible with BLE. 

 

The best I got to was about 14 Kbytes per second. running in both directions concurrently, from client to server and back, in an echo testing framework.   I need to revisit this later to boost it by a factor of at least 5 to 10, raising it to at least 100 Kbytes per second.  I believe that should be possible,  but so far I have not figured out how to do it.  

 

Even to get to 14 Kbytes per second, I found it necessary to turn off message by message acknowledgement.  There is a difference between NOTIFCATIONS, and INDICATIONS.    A notification has no acknowledgement.  An indication has an acknowledgement. 

 

The problem with using message by message acknowledgements (ie- using INDICATIONS) is you only get to exchange one message every connection interval between the client and server (the BLE endpoints).  If the connection interval is 100 ms, this means you send the data in one connection interval, and I think you get the acknowledgment in the next, and that has used 200 ms.   You can repeat that about 5 times a second, thus 5 exchanges of your message (which apparently is 148 bytes), resulting in a pretty low data throughput rate.

 

You can improve things by shortening the connection interval (setting it to its minimum value of 6 results in a connection interval of 6 * 1.25 ms, which is 7.5 ms), at the expense of increased power usage.   But you rapidly find there is fundamental round trip latency that limits your throughput.  One solution is to switch to using NOTIFICATIONS (meaning no acknowledgement) on a message by message basis.  This allows multiple messages to be in flight at the same time.  Note I observe there was sufficient buffering in the windows bleak stack, to STM32 coprocessor, and back to a windows bleak stack to hold about 10 messages.  I found keeping a count of messages in flight and limiting that to about 5 seemed to work pretty well to avoid dropped messages.  But congestion can happen, in the RF space, or in the software real time load of the coprocessor, so messages can and do get dropped.    For reliability you then need to have a higher level mechanism to ensure you have not lost messages, and perhaps resend an entire block of messages or one missing message if one gets dropped.   At the very least it is useful to let the receiver detect that a message was lost.  

 

Using this approach I was able to get up to about 14 Kbytes per second of throughput. 


If anyone reading this knows the recipe to get up to 1 Megabit per second or 1.5 Megabits per second of throughput, please share it with me, because for now I cannot quite see how to do it. 

Hi,

 Thank you so much for sharing your experience, it's very helpful, and I will try and let you know the update :) 


@EJD1962 wrote:

You can improve things by shortening the connection interval (setting it to its minimum value of 6 results in a connection interval of 6 * 1.25 ms, which is 7.5 ms), at the expense of increased power usage.    


Unfortunately, the "host" is not bound to accept your request.

So this is fine if you have control of both ends of the link - but things like phones are unlikely to accept the request.

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.
EJD1962
Associate II

Good Point Andrew.    

I also read somewhere that Apple devices limit the connection interval to at least 15 milliseconds, so twice what an Android device can use (at least in theory, as you point out). 

 

One other tip, I found this recipe for achieving higher bandwidth throughput on the internet. I have not tried these tips out yet, but I should get to it in a few weeks.

*** Improve Throughput Performance by following these tips...
https://swaralink.com/2022/12/under-the-hood-how-swaralink-maximizes-ble-throughput/

I will update here with any relevant results once I have tried out the tips.

Have definitely seen Android devices refusing the smallest Connection Intervals.

Have seen it vary on the same device between one connection and another.

I guess the mobile OS must have its own views on how it feels it should allocate/prioritise its radio resources...

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.

@EJD1962 wrote:

If anyone reading this knows the recipe to get up to 1 Megabit per second or 1.5 Megabits per second of throughput. 


Those figures are the raw modulation rate - you're never going to reach that with payload throughput:

https://punchthrough.com/maximizing-ble-throughput-on-ios-and-android/#:~:text=1%20Mega%20bits%20per%20second%20is%20just%20wrong.%20That%20is%20the%20modulation%20frequency%20used%20to%20transfer%20a%20given%20BLE%20packet.%20Assuming%20this%20to%20be%20the%20maximum%20throughput%20is%20simply%20ig....

(from @popfan's link)

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.