BLE peripheral throughput limit - ios

We are developing a BLE sensor Peripheral to work with an iPad, that requires the following throughput of data on the BLE notification characteristic (no acknowledge) using a TI CC2541 BLE module and a custom profile:
One 20 bytes (GATT maximum standard packet) every 10ms, or since we appear to have a limit of 4 packets per connection interval, this equates to one connection interval every 40ms. Throughput required is 2,000 bytes per second, the TI website recommends the CC2541 BLE solution be used for several sensor devices requiring this level of data throughput.
The profile for the BLE module is set with min and max connection intervals of 20ms and 40ms respectively, which should suffice. The "Bluetooth Accessory Design Guidelines for Apple Products" document suggests that the minimum and maximum connection intervals we set, as above are correct. We are using the latest iPad and Apple tools for iOS 6 on a new Mac Mini / Mac Book.
With a simple test program on the iPad, we can get the link to work well sending 20 byte packets to the BLE Peripheral at intervals of 20ms, however once we lower this to 10ms as required we start loosing packets or getting corrupt packets, we have the FIFO empty interrupt turned off so we can handle the sending to the BLE module FIFO quicker, and we are using the maximum Baud rate of 230400 to send the 20 byte packets to the BLE TX FIFO from the micro.
We realise we are at the top end of the BLE transfer limit, and of what is possible. Can anyone advise if there is a solution to achieving 2000 bytes per second throughput using the TI CC2541 BLE chip / module with an up to date iPad?

We use TI 2540 (BLE stack version 1.3.2) succesfully with iPad/iPod/iPhone (iOS 6.x and 7.x). We currently send 75 notifications of 20 bytes per second => 1500 bytes/second. But I have tried to send 125 notifications and that worked as well.
Of course the more you send the greater likelihood of loosing data, e.g., less time to resend a NACK'ed message.
I have experienced that iOS' BLE stack may enter a mode where it begins to NACK messages continuously. If this happens you will loose a lot of messages. I have reported an error to Apple about this. (This problem seems to have been fixed in iOS 7.1.beta3/4.)
I currently have:
// Minimum connection interval (units of 1.25ms, 80=100ms) if automatic parameter update request is enabled
#define DEFAULT_DESIRED_MIN_CONN_INTERVAL 10
// Maximum connection interval (units of 1.25ms, 800=1000ms) if automatic parameter update request is enabled
#define DEFAULT_DESIRED_MAX_CONN_INTERVAL 20
Yes, it doesn't conform with Apple's guidelines. But I believe they can be relaxed in our case.
UPDATE: I have also tried to use an iDevice as peripheral, i.e., BTLE between two iDevices. Here I have sent 150 messages per second without any problems.

Are you sending "write without response" commands? You can send 4 packets per connection event this way. Using you previous 20ms connection interval, you would be sending 4 packets with 20 bytes every 0.02 seconds. Putting that together: 4*20/0.02 = 4000 bytes per second easy.
I highly doubt you are getting corrupt data. The link layer adds a CRC and a 2 bits of "next expected" to BLE packets to ensure A) all the bits are received correctly and b) packets were not sent out of order. The TI stack and iOS control the link layer so I doubt you've botched that.

Here are few observation on throughput that we found during our RnD on iPhone with BLE. The below data is based on write with response.
iPhone 8 (BLE 5.0) as Central and Linux desktop (Ubuntu 16.04 with BLE dongle 4.0): MTU = 2048 : Throughput - 2.5 KiloBytes per sec.
iPhone 8 (BLE 5.0) as Central and Android OS with BLE version 4.2 as Peripheral(Xiomi Mi A1): MTU = 180 : Throughput - 2.5 KiloBytes per sec.
iPhone 8 (BLE 5.0) as Central and iPhone 7 plus (BLE 4.2) as Peripheral : MTU = 512 : Throughput - 7.1 KiloBytes per sec.
iPhone 8 (BLE 5.0) as Central and Samsung S8 (BLE 5.0) as Peripheral : Samsung S8 failed to work as peripheral
iPhone 8 (BLE 5.0) as Central and iPhone 8 plus (BLE 5.0) as Peripheral : MTU = 512 : Throughput - 15.5 KiloBytes per sec.
As you can see, as the MTU value increases, we get maximum throughput. But we cannot increase to any limit. The above MTU values are the default maximum allowed MTU value as per the given configuration. [MTU - Maximum Transmission Unit. i.e maximum bytes that can be sent in one write request]
Comments are welcome to the above data.

iOS 7 seems to have made some optimizations regarding the throughput levels for BLE transfers. Try it again on an iOS 7 device.

You don't really pose a question, but I can verify that your desired limit of 2000 bytes/sec is possible.
check out the selected answer on this forum post (http://e2e.ti.com/support/wireless_connectivity/f/538/p/353327/1244676.aspx#1244676) to see how we made it work.

Related

Is there any difference in packet length of BLE between iOS device?

I am trying implement an APP with BLE function.
Tried to get data back from UpdatedCharacterteristicValue().
But I found out that when I am expecting to receive about 200 bytes long data.
On my iPhone 12 Pro(iOS 15). It works fine.
On my iPhone 8(iOS 12). It's not working.
If I am expecting to receive about 60 bytes long data.
Both device works fine.
What would be the difference between these two device that cause this result?
Check the negotiated ATT MTU after the connection is established and use it to determine the maximum characteristic size.
The maximum characteristic size you can use on the link is ATT MTU - 3, as 1 byte is used for op-code, and 2 bytes as attribute handle.

How can an iOS BLE central receive more than 182 bytes from a peripheral in notify mode?

I have a custom BLE peripheral that can send a notification data packet to a central. The device sends packets of 234 bytes at a time, and the central is expected to register for notification of characteristic updates on the device. Peripheral is sending the 234 bytes of data to central but iOS device receiving only 182 bytes of data in the didUpdateValueForCharacteristic function.
In android, The central software just works with no problems and the phone (central) receives 234 bytes in a single notify event. - this works just fine in Android but having an issue with iOS devices.
Is there any configuration required for the iOS device to receive the full length of data from the BLE peripheral? Any help would be appreciated!
iOS devices have a maximum ATT_MTU of 185 bytes, which means you can send a maximum of 182 data bytes per packet (the other 3 bytes are overhead for L2CAP). In the beginning iOS devices only supported 158 bytes and then this was increased to 185.
The way ATT_MTU works is that there's a negotiation upon connection where the central sends its maximum ATT_MTU (i.e. for iPhones it is 185) and the peripheral replies with its own ATT_MTU (i.e. in your case it is 237), and then the connection's ATT_MTU will be the minimum between the two (i.e. 185). So to answer your question, no there isn't a way to configure your iOS device to send the full length of data because this is a low level configuration that Apple don't allow access to.
Have a look at the following links for more information:-
iOS BLE Get Negotiate MTU
Maximizing BLE Throughput Part 2: Use Larger ATT_MTU
A Practical Guide to BLE Throughput

Maximum Number of BLE Advertising Packets Receivable per Second

I have a quick question regarding BLE packets with iOS.
Say I have an iPhone app that sends out BLE advertising packets once a second in the background. This same app is also configured to receive advertising packets in the background. Say there are 30 other devices running this same app within Bluetooth range of the original device. Is there a theoretical maximum to the amount of packets any one device can receive within a given time interval? Could the app receive and process all the advertising packets from the thirty phones, or even 100 phones? Thanks for your help!
Depends on peripheral advertising speed/interval. If you have 20 ble device around ios device and start scan.
Then first get nearest device and which devices who advertising interval is fast.
Well the BLE advertisements run at 1 MBit/s so that means one microsecond per bit.
In an advertisement packet the overhead is, on top of the advertisement data, the address of 6 bytes and then 10 bytes extra for BLE header and CRC.
If two packets are transmitted by two devices at the same time, they will interfere and possibly none of these packets can be detected at all.
With this information you should be able to calculate the rest of the Math yourself.

NRF51 - iOS BLE advertising interval - Increase speed of connection

I am looking at speeding up the connection time between my iOS application and the peripheral.
I have looked up Apples Documentation on the subject: https://developer.apple.com/library/content/qa/qa1931/_index.html
Originally (prior to reading the doc above) I had the advertising interval set to 2 seconds to, what I had thought would be, a good compromise between power consumption and connection time. Having read the documentation further I have changed the interval to 1285 ms.
#define ADVERTISING_INTERVAL 2056 ble_obj.setAdvertisingInterval(ADVERTISING_INTERVAL);
The device is always discovered quickly by the app but the problem comes when trying to connect.
However, I have seen no increase in speed in connection time between my application and the peripheral device. Connections between the devices can take anything from 3-4 seconds up to 30+ seconds.
Is there something I am missing? Either on the peripheral or the central side?
Peripheral BT chip is the Nordic Semiconductor NRF51822.
On examining the devices advertisement packet on the Nordic Semiconductor app I can see that the advertisement interval normally varies from 1275 ms to about 1295 ms (as expected? due to the random time added to the advertisement packet)
NOTE
Have also tried with an advertising interval of 152.5 ms and am still not seeing any major improvement in connection speed. I am , obviously, seeing a marked improvement in speed of discovery
What you observe is normal. Don't expect fast connection setup with an advertising interval of more than a second.
Core Bluetooth uses a high duty scan window/interval for the initiation the first seconds. If it doesn't connect then it continues to scan with much more power restrictive parameters.

iOS Bluetooth LE: Code=6 "The connection has timed out unexpectedly."

I have a BLE peripheral device (for which I control the firmware) and two mobile apps acting as centrals, one on Android, the other on iOS 8.1.
The Android app works fine. The iOS does not. It will spontaneously disconnect some time after connection. The error is:
Code=6 "The connection has timed out unexpectedly."
The time between connection and this disconnection is random. I've measured from 40s to 4m30s.
All the peripheral device is doing with the BLE connection is writing some firmware logging messages to the mobile app UI. Just a few writes to that one characteristic in quick succession every few minutes. There is no error in the peripheral device firmware.
How do I find the cause of the disconnection?
After some extensive support from Nordic Semiconductor, the manufacturer of the BLE module on the peripheral, we're pretty sure the cause of this is an inaccurate clock on the iPhone 5C BLE module. That is, it's less accurate than stated in the connection request. Here's my question on the Nordic forums:
https://devzone.nordicsemi.com/question/51258/ios-8-disconnection-code6-the-connection-has-timed-out-unexpectedly/
So I was facing this problem with Microchip BM78 Bluetooth module talking with iOS. I found this tech note which was very helpful:
https://developer.apple.com/library/archive/qa/qa1931/_index.html
These settings are flashed onto the BM78 module. Here are the Apple 'rules' from the above tech note:
Interval Min ≥ 15 ms (multiples of 15 ms)
Interval Min + 15 ms ≤ Interval Max (Interval Max == 15 ms is allowed)
Interval Max * (Slave Latency + 1) ≤ 2 seconds
Interval Max * (Slave Latency + 1) * 3 < connSupervisionTimeout
Slave Latency ≤ 30
2 seconds ≤ connSupervisionTimeout ≤ 6 seconds
My values (working well):
Interval Min = 15ms
Interval Max = 30ms
Slave Latency = 4
Connection Supervision Timeout =~ 5 seconds
The same issue happened to me when I developed Bluetooth on iOS14. I adjusted the roles mentioned by Jim Holland at first, but the issue still occurred. Then I doubted it because of the low RSSI of the signal. After moving the test phone closer to the device, the issue disappeared! After some tests, I found this issue occasionally shows when RSSI is lower than -90.

Resources