Skip to content

Commit 790a118

Browse files
Merge pull request #1460 from paul-szczepanek-arm/ble-guide
Add BLE guide for optimising performance
2 parents ae468ed + 05b0546 commit 790a118

File tree

2 files changed

+185
-0
lines changed

2 files changed

+185
-0
lines changed

docs.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,9 @@
834834
},
835835
{
836836
"path": "docs/api/connectivity/bluetooth/SecurityManager.md"
837+
},
838+
{
839+
"path": "docs/api/connectivity/bluetooth/Optimising_for_performance.md"
837840
}
838841
]
839842
},
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
# Optimising application for throughput and power consumption
2+
3+
BLE (Bluetooth Low Energy) devices are usually battery powered so performance might mean different things in different
4+
applications. You will need to decide what is more important in your application - minimising power consumption on one
5+
or both sides of the communication or maximising throughput and/or latency. Some optimisation steps can in fact achieve
6+
both.
7+
8+
This guide will discuss some trade-offs that should be considered and best practices that improve performance on all
9+
fronts.
10+
11+
## Power consumption
12+
13+
Any radio activity will consume power. Depending on what the stack is doing you have to power the radio even when no
14+
data is being sent. It is important to understand when radio is active.
15+
16+
### Connections
17+
18+
The most intuitive power consumption rate to understand is when using connections. Each device will take turns sending
19+
and receiving at set interval.
20+
21+
```
22+
CENTRAL
23+
┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐
24+
│send│ │recv│ │send│ │recv│ │send│ │recv│ │send│ │recv│
25+
└────┘ └────┘ └────┘ └────┘ └────┘ └────┘ └────┘ └────┘
26+
connection interval
27+
◄─────────────────────►
28+
29+
PERIPHERAL
30+
┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐
31+
│recv│ │send│ │recv│ │send│ │recv│ │send│
32+
└────┘ └────┘ └────┘ └────┘ └────┘ └────┘
33+
slave latency
34+
◄───────────────────────────────────────────►
35+
36+
▲ ▲ ▲
37+
connection event connection event connection event
38+
```
39+
40+
To maintain a connection, regardless if there is data transfer to be transferred, the central needs to transmit and
41+
receive once every connection interval.
42+
43+
The peripheral needs to acknowledge connection events to the central. Data ready to be transmitted is sent in the
44+
acknowledgement. To save power, if the peripheral has no data to transmit it may skip up to `slaveLatency` connection
45+
events.
46+
47+
More power is consumed if there is data to be exchanged. The exchange can continue until the next connection event would
48+
take place.
49+
50+
It's worth considering if keeping the connection active is worth it. Connection in BLE has little overhead and there are
51+
some cases when it is better to connect and disconnect each time you want to send a burst of data if for example you
52+
want to conserve power on one of the devices. This way only one side will have to run advertising/scanning all the time
53+
while the power limited device can turn the transmitter on only when it needs to.
54+
55+
The cost of the connection is proportionate to the negotiable connection interval. This can be set during `connect` or
56+
later through `updateConnectionParameters`. The lower the interval the more often radio is active. This is especially
57+
important for the peripheral which needs to enable the radio to receive packets.
58+
59+
This can be further helped by setting a high `slaveLatency` parameter. This allows the peripheral to skip
60+
connection events and save power not just by not sending any packets but by not even listening. This is not free for
61+
central as it increases latency of data transmission from central to peripheral. Central may have to attempt sending
62+
data multiple times before the peripheral accepts the transmission. The peripheral may send data at any connection event
63+
as the central must listen after every transmission.
64+
65+
### Advertising and scanning
66+
67+
Power draw during advertising affected by:
68+
- the advertising interval - lower interval uses more power,
69+
- use of Coded PHY which uses more power for extended effective range,
70+
- amount of data sent,
71+
- number of channels used - each advertising event is sent by default to three channels which you can limit to 2 or 1,
72+
- whether extended advertising is used - this will send additional packets on regular channels,
73+
- whether the type is connectable or scannable - it means the advertiser needs to listen on the radio after each
74+
advertisement for potential connection of scan requests.
75+
76+
```
77+
PERIPHERAL
78+
┌────┐ advertising interval ┌────┐
79+
channel 37 │adv │◄───────────────────────────────────────────►│adv │
80+
└────┘ └────┘
81+
┌────┐ ┌────┐
82+
channel 38 │adv │ │adv │
83+
└────┘ └────┘
84+
┌────┐ ┌────┐
85+
channel 39 │adv │ │adv │
86+
└────┘ └────┘
87+
88+
non-advertising ┌────────────────────┐
89+
channel │extended advertising│
90+
(indicated in regular └────────────────────┘
91+
advertising payload)
92+
```
93+
94+
Scanning power draw is proportional to time spent scanning. Additional power will be used if you run active scanning
95+
which will send a scan request and listen for the reply.
96+
97+
The interaction between scanning an advertising means that the less power the advertiser spends advertising, the more
98+
power the scanner will have to spend to see the advertising packets. The decision on balance will be dictated by your
99+
design of your devices (which one is more constrained).
100+
101+
### Connection vs advertising
102+
103+
Instead of connecting to the device you can consider transferring data in advertising packets. This depends on the
104+
nature of the data.
105+
106+
A transfer over a connection will allow you to use the ATT protocol, this can handle acknowledgement for you. This might
107+
be a good choice if you're sending data that must get through reliably.
108+
109+
If your data is non-critical then advertising might be cheaper. You might have to accept less reliability and no built
110+
in acknowledgment. Additional benefit is that multiple devices may receive the data and each scanner may make their own
111+
decisions about power consumption.
112+
113+
### Periodic advertising
114+
115+
Periodic advertising allows you to get best of both worlds by having the power characteristics of advertising for the
116+
peripheral but also saving power for the scanner. After finding periodic advertising through `createSync` the scanner
117+
will only have to turn on the radio when the expected packet is due.
118+
119+
## Increasing throughput
120+
121+
### Modulation schemes
122+
123+
Depending on controller support different modulation schemes are available in BLE through `setPreferredPhys()` and
124+
`setPhy()`. While the coded PHY will increase reliability in noisy environments and increase range at the cost of
125+
power consumption, 2M PHY will increase the throughput saving power ber bit. If both devices support it and the signal
126+
quality is good then this is recommended to be enabled.
127+
128+
### Data length and ATT_MTU
129+
130+
Packet overhead strongly affects throughput. Newer controllers allow you to negotiate bigger MTUs thus decreasing the
131+
fragmentation overhead.
132+
133+
There are two separate MTUs to consider: the `ATT_MTU` (which affects ATT protocol operations) and data length extension
134+
(which affects transport packets). Increasing the sizes will increase memory usage but greatly increase throughput.
135+
`ATT_MTU` and data length are independent of each other.
136+
137+
The size of ATT_MTU doesn't have any other overhead than memory and should only be limited by your biggest attribute
138+
and available memory.
139+
140+
The default value of data length supported by all controllers is 23 octets. If both controllers support data length
141+
extension and a higher value is negotiated, the BLE stack will call `onDataLengthChange` in the `Gap::EventHandler`
142+
registered by the user. The supported length is set in the link layer with a maximum of 251. For Cordio Link Layer it
143+
is derived from the config option `cordio_ll.max-acl-size`.
144+
145+
Larger data length greatly increases throughput (although diminishing returns quickly set in above 80). The only
146+
potential drawback is in noisy environments where longer packets may cause slower effective transfer due to
147+
retransmissions (this is only related to data length, ATT_MTU does not affect this).
148+
149+
### ATT protocol
150+
151+
GATT client writes and GATT server updates come in two versions - with and without confirmation. Requiring confirmations
152+
limits the throughput severely so to maximise throughput you can move reliability up from the stack to your application.
153+
Without confirmations more than a single Peripheral <=> Central data exchange can be made per connection event. With
154+
confirmations, the connection event ends when the peripheral replies as it needs to prepare the acknowledgement which
155+
will be sent possibly in the next event.
156+
157+
### Packet timings
158+
159+
If you're not constrained by battery power it might be tempting to use maximum/minimum values where possible.
160+
Advertising at maximum frequency and scanning continuously will speed up connecting. Setting intervals on connections
161+
will minimise latency and maximise number of connection events.
162+
163+
One key thing to consider when setting the connection interval low is that you are creating a boundary between which a
164+
sequence of packets must fit. This means that the last transfer must end before the next connection event starts
165+
(plus 150us of inter packet space). This dead time may become significant if the connection interval is short and packet
166+
length is long.
167+
168+
The connection interval shouldn't be shorter than what your data requires in terms of latency.
169+
170+
# Test and measure
171+
172+
Due to complexity of the stack the only reliable way to truly maximise performance is to test your application with
173+
representative data and measure the throughput and power usage. It's important to keep in mind that tweaking
174+
parameters by trial and error and fine-tuning them will only be reliable for sequential operations on known stacks.
175+
176+
Many behaviours are implementation dependant and many operations are best effort and not guaranteed to succeed. The
177+
stack has a lot of latitude to change its behaviour in accordance with resource constrains and other commitments. For
178+
example your advertising may be severely affected by other operations that take precedence like keeping up a connection.
179+
180+
If your device needs to communicate with an unknown device or you run a non-trivial combination of concurrent
181+
operations your fine-tuning should give way to sound principles since stack behaviours vary and you cannot test against
182+
all stacks and sequences of operations.

0 commit comments

Comments
 (0)