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.
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
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.
I currently have a BLE peripheral device that streams 35 bytes of data every 100ms (arduino sketch). On my iOS device, I've tested using Adafruit's iOS UART program and verified that the iOS device can indeed receive the full 35 bytes of data every 100ms. They use the MQTT libraries.
I am using the CoreBluetooth library and in CBPeripheral's didUpdateValueForCharacteristic: method, the characteristic.value is always 20 bytes or less. It will usually be 20 bytes -> 100ms -> remaining 15 bytes -> 100ms...repeat.
I'd like to retrieve the entire 35 bytes in one transmission, but on the receiving end it breaks it up into 20 byte chunks whereas the adafruit iOS library using MQTT receives the entire transmission of 35 bytes in 1 shot every 100ms.
Upon further research, I noticed the use of CBPeripheralManager and the didReceiveReadRequest: method but I believe that only belong's on the peripheral BLE device, and not on the host iOS device which I am receiving the data from.
Does anyone have any idea how to retrieve the entire 35 byte transmission?
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.