You seem to be doing a lot of the things that will generally improve throughput. So, I will just touch some of the points that might be relevant for additional performance boost.
For starters, all connection parameters must be negotiated by the connecting accessory. there is nothing you can do in an app that will change those.
And as for the accessory negotiating these parameters, there are some certain rules it has to follow, otherwise the request can be rejected, and iOS will set the parameters to defaults.
These rules are explained in detail in the Accessory Design
Guidelines for Apple
Devices but here is a summary:
Connection parameter requests may be rejected if they do not meet the guidelines in this section.
General connection parameter request guidelines:
- Peripheral Latency ≤ 30 connection intervals.
- Supervision Timeout from 6 seconds to 18 seconds.
- Interval Min ≥ 15 ms.
- Interval Min ≤ 2 seconds.
- Interval Min is a multiple of 15 ms.
-- One of the following:
- Interval Max at least 15 ms greater than Interval Min.
- Interval Max and Interval Min are both 15 ms.
- Interval Max * (Peripheral Latency + 1) of 6 seconds or less.
- Supervision Timeout greater than Interval Max * (Peripheral Latency + 1) * 3.
As you can see, you cannot make a request of 7.5 ms and it will be rejected. Hence the rest of the connection parameters are probably getting set to defaults. What you would want to do is to make sure the request meets the guidelines to be accepted. You can try 15ms, but is that really the best? I'll discuss more below.
Note: even with the correct parameter requests, the iOS device may still not be able to accept the parameters if the current device conditions do not allow them. Based on device state and what else might be going on with the device at that time
That said, a faster CI may not always result in a higher throughput. What you are trying to accomplish is sending as many packets as you can in a connection interval. And the optimum throughput will be a balance between the interval duration and the number of packets that can be transferred in one interval. You may want to test the best outcome for your use case with different CI values to see if being able to squeeze more packets will be more beneficial than a short interval.
So, for the best throughput you would want to do the following:
- Write Without Response, which you are obviously doing
- Larger MTU, which I also see in your table
- Extended Data Length - which would be 251, which you mark as the MTU in your table. If you are not actually using EDL, do look into it
- 15ms Interval, which you should try to see if you can fit as many packets in an interval
- LE 2Mbps, which you are also already using
The only thing I don't see a mention of, and which is something you can actually implement in your app is L2CAP
If you are not using L2CAP, I suggest you should look into that, as it will dramatically increase your throughput by reducing GATT protocol overhead.
Hope this helps.
Argun Tekant /
DTS Engineer /
Core Technologies