Adaptive Data Rate (ADR)
ADR (Adaptive Data Rate) is a LoRaWAN mechanism in which the server chooses the device's data rate (DR), transmit power and the number of transmissions of each frame (NbTrans). ONS tracks the signal margin with which the gateway receives the device's frames and how many frames are lost, and sends the device new parameters with the LinkADRReq MAC command. When reception is good, the server raises the data rate and then lowers the power; when it is poor, the server raises the power and then lowers the data rate.
When ADR works
ADR works only when both conditions are met:
- ADR is enabled in the device settings — the
adrfield, the "ADR" checkbox in the interface; it is on by default; - the device sets the ADR bit (FCtrl.ADR) in its uplinks.
If at least one of them is not met, the server collects no ADR statistics and sends no commands. OrionM2M firmware enables ADR when it starts LoRaWAN; the device has no separate setting for it.
After each OTAA activation (join) the server rebuilds the device settings without the adr field and treats ADR as allowed. A cleared "ADR" checkbox takes effect again only after the device is saved in the ONS interface, and only until the next join.
The hint under the "ADR" checkbox in the interface reads "Only the end-device can enable / disable ADR". The device itself turns ADR mode on with the ADR bit, and the checkbox in the settings decides whether the server uses that mode.
The server does not decide on every frame but roughly once every adr_interval uplink frames (20 by default), see How the server decides. With adr_interval = 0 the server makes no decisions and sends no LinkADRReq. After each OTAA activation (join) the ADR statistics start over.
What the server measures
- One reception of a frame. A device frame may be received by several gateways. For ADR the server takes the copy with the highest RSSI among those that arrived before frame processing starts — about 0.6 seconds after the first copy. The SNR and DR of the frame come from that copy, and the gateway that received it counts as the best one.
- SNR. For the best gateway the server keeps a window of the last 20 SNR values and rates reception by the maximum in the window (SNRmax).
- Loss. The same window holds the FCnt of the last 20 frames. Loss is the share of FCnt gaps: missed frames / (last FCnt − first FCnt) × 100%.
- Windows per gateway. A separate window is kept for each gateway that has been the best one, but for no more than three gateways: when a fourth appears, the window of the gateway that has gone longest without being the best is deleted. The decision uses the window of the current best gateway.
- Repetitions are not counted. A repetition of a frame with the same FCnt (NbTrans) does not enter the ADR statistics.
How the server decides
When a decision is made
The server checks ADR at the start of preparing every downlink:
- after each new uplink, even if there is nothing to send. A repetition of an unconfirmed frame (NbTrans) does not start a check, a repetition of a confirmed frame does;
- when the device's best gateway reconnects while the device has downlink data in the queue — for a device of any class;
- class C has other occasions too, see Device classes.
The window of the best gateway has a counter. While the counter is below adr_interval at the start of a check, the check only adds to it the FCnt difference of the last two frames in the window, so lost frames are counted too. While the window holds no more than two frames, 1 is added. The addition happens on every such check, even if the window has not changed, for example on a repetition of a confirmed frame. When at the next check the counter is already not below adr_interval, it is reset to zero and the server makes a decision: with consecutive frames and adr_interval = 20, on every 21st check.
Signal margin
First the server calculates the signal margin and the number of steps:
- margin = SNRmax − required SNR of the current DR − 10 dB;
- NStep = margin / 3, with the fractional part dropped: 9.5 / 3 → 3, −7.5 / 3 → −2.
10 dB is the installation margin, and 3 is the number of decibels of margin per step. Both are server parameters, see Server parameters.
The required SNR is the same in all frequency plans of the server:
| DR | Required SNR, dB |
|---|---|
| DR0 (SF12) | −20 |
| DR1 (SF11) | −17.5 |
| DR2 (SF10) | −15 |
| DR3 (SF9) | −12.5 |
| DR4 (SF8) | −10 |
| DR5 (SF7) | −7.5 |
The DR-to-SF mapping (125 kHz bandwidth) in the table applies to all plans except US915.
Data rate and power
- NStep > 0. For each step the server raises the DR by one level until it reaches the highest DR for ADR (see Frequency plan). The remaining steps lower the power: the power index grows by 1 (−2 dB) up to the highest index of the plan.
- NStep < 0. For each step the server first raises the power — the index drops by 1 down to 0, the maximum power — and then lowers the DR, down to DR0.
- NStep = 0. The DR and power do not change.
Then the server applies the limits from the device settings — adr_min and adr_fix, see Device settings.
Examples for a plan whose highest DR for ADR is DR5 and whose power indexes are 0–7, for example KZ865-868:
| Before: DR, power index | SNRmax, dB | Margin, dB | NStep | After: DR, power index |
|---|---|---|---|---|
| DR0, 0 | +3 | 3 − (−20) − 10 = 13 | 4 | DR4, 0 |
| DR5, 0 | +12 | 12 − (−7.5) − 10 = 9.5 | 3 | DR5, 3 (−6 dB) |
| DR5, 0 | −5 | −5 − (−7.5) − 10 = −7.5 | −2 | DR3, 0 |
Number of transmissions NbTrans
NbTrans is how many times the device transmits each frame. The initial value is 1. The new value depends on the loss in the window and on the current NbTrans:
| Loss in the window | Current NbTrans 1 | Current NbTrans 2 | Current NbTrans 3 |
|---|---|---|---|
| Below 5% | 1 | 1 | 2 |
| 5–10% | 1 | 2 | 3 |
| 10–30% | 2 | 3 | 3 |
| 30% and above | 3 | 3 | 3 |
The new DR sets a ceiling: at DR0–DR2 NbTrans is always 1, at DR3 and above it is at most 3.
When no command is sent
- The DR, power index and NbTrans match those recorded on the server.
- The device's MAC command queue already holds a LinkADRReq.
- The device transmits at a DR above the highest DR for ADR, see Frequency plan.
- The device has the RU or UA plan: in the current version the server does not send LinkADRReq for these plans, see Frequency plan.
Otherwise the server queues LinkADRReq in the MAC command queue, and the command goes out with the next downlink frame.
Device settings
| Field | In the interface | Default | What it does |
|---|---|---|---|
adr | "ADR" | true | Allows ADR on the server. With false the server collects no ADR statistics and sends no LinkADRReq. After each OTAA activation the server treats ADR as allowed until the device is saved again in the ONS interface, see When ADR works |
adr_interval | "Adr interval" | 20 | After how many uplink frames, counted by FCnt increments, the server makes a decision. 0 — no decisions |
adr_min | "Adr min" | DR0 | Lower limit: at decision time the server raises the DR to adr_min even if the signal margin is not enough |
adr_max | "Adr max" | DR5 | Currently does not limit ADR, see below |
adr_fix | "Adr fix" | Not set | Fixed DR: the decision always equals adr_fix, and the server does not lower the power. Works only if ADR is enabled both in the settings and in the device |
adr_max currently does not limit ADR at any value: the server skips a value not above the highest DR of the plan, and a higher value has no effect. To limit the data rate, set adr_fix.
Saving the device in the ONS interface passes the new settings to the network server immediately; no new activation (join) is needed. A new adr_interval takes effect from the next ADR check.
In the WebSocket API the ADR fields are set in create_device_req and update_device_req and read with get_devices_req. The update_device_req command can neither turn ADR off, nor set DR0, nor reset adr_fix; when the network server learns about a change is described on the command page.
Frequency plan
- The highest DR for ADR is the highest DR with LoRa modulation and 125 kHz bandwidth among the plan's uplink channels. In all plans except US915-1…9 and AU915-9 it is DR5 (SF7, 125 kHz); in US915-1…9 it is DR3 (SF7, 125 kHz), in AU915-9 it is DR3 (SF9, 125 kHz). If the device transmits at a higher DR — for example DR6 (SF7, 250 kHz) — the server does not apply ADR to it.
- Power is set by an index: 0 is the maximum power, and each next index lowers it by 2 dB. The highest index is 7 (−14 dB) in the plans EU, KZ_OLD, RU, BY, UA, KG863-865, KZ865-868, EU863-870, KZ864-868, EU433, AS923-1…4, KR920, UZ926, UZ927 and KZ865-only; it is 10 (−20 dB) in IN865-867, IN865+KZ865, US915 and AU915.
- The RU and UA plans. In the current server version ADR does not work for devices with the RU (code 2) and UA (code 4) plans: the server does not send the LinkADRReq command and does not reply to the uplink after which it decided to change the device parameters — the queued data goes out after the next uplink. To keep the server from skipping the reply, set "Adr interval" to 0 for such devices. For a device on the UA plan channels choose the EU or BY plan.
- The device's power is not sent in the uplink. So if the DR of the next frame differs from the one recorded on the server, the server assumes the device is transmitting at maximum power again (index 0).
- Channel mask. The server takes ChMask and ChMaskCntl for LinkADRReq from the plan: the mask holds the plan's enabled channels. Extra channels from the "Radio parameters" panel are not included in the mask. ChMask examples, with channel numbers in the order of the ONS plan: EU863-870 —
FF00(channels 0–7), KZ865-868 —1F00(channels 0–4, 865.1–865.9 MHz), KG863-865 —1F00(channels 0–4, 863.7–864.5 MHz), EU, BY and KZ865-only —0700(channels 0–2); ChMaskCntl is 0. In the current server version, in plans with nine enabled channels — EU433, US915-1…7 and AU915-1…8 — the mask does not match the plan channels: the server sends ChMask01FF, that is, the first channel and the last eight channels of a 16-channel block. In EU433 a device that follows the LoRaWAN specification may reject such a command, and ADR does not take effect. In US915 and AU915 the device may accept the command and move to channels outside the plan sub-band — a gateway set to the plan sub-band then stops hearing part of its uplinks. For US915-8, US915-9 and AU915-9 the server does not build a correct LinkADRReq command: ADR does not work, and the reply that should carry the command may not be sent. For devices with US915 and AU915 plans set "Adr interval" to 0: the server then sends no LinkADRReq. - Extra channels outside the mask are turned off. The server passes the channels from the "Radio parameters" panel to the device under numbers starting from the plan's first optional channel, or from number 3 if the plan has no optional channels. OrionM2M firmware, having accepted LinkADRReq, replaces the whole channel mask. So after each LinkADRReq the device turns off extra channels whose numbers are outside the mask: in EU, BY and KZ865-only, all extra channels; in KZ865-868 and KG863-865, channels 5–7.
The LinkADRReq command in a frame:
| Byte | Contents |
|---|---|
| 1 | CID 03 |
| 2 | DR in the upper 4 bits, power index in the lower 4 bits |
| 3–4 | ChMask |
| 5 | ChMaskCntl in bits 4–6, NbTrans in the lower 4 bits |
For example, DR5, power index 2 and NbTrans 1 in the KZ865-868 plan give 03521f0001.
Region codes and plan channels are listed on the create_device_req page and in Frequency plans.
Device classes
- Class A. LinkADRReq goes out in the receive window after the uplink on which the server made the decision.
- Class C. The server checks ADR not only after an uplink but also when it queues a downlink, when a gateway becomes free after a transmission, and when it sends radio parameter reconciliation MAC commands immediately. Each such check also increases the counter, so a decision may come sooner than after
adr_intervaluplinks, and LinkADRReq goes out at once, in an immediate frame.
ADRACKReq. If the device has not received a downlink for a long time, it sets the ADRACKReq bit in its uplink, asking the server to respond. The server answers such an uplink with a downlink frame even if there is nothing to send, and sets the ACK bit in it. This does not depend on the adr setting. In OrionM2M firmware ADR_ACK_LIMIT = 64 and ADR_ACK_DELAY = 32: if the device is not at the lowest DR, after 64 uplinks without a downlink it sets ADRACKReq and switches to maximum power, and if there is still no response after 32 more frames, it lowers the DR by one level every 32 frames, down to the lowest.
More about classes is on the Device classes page.
How to check ADR
Every queued LinkADRReq command is written to the ADR log — the "Adr log" panel on the "Monitoring" tab of the node card, see Nodes. The newest rows are on top. If there is nothing to change, no row is written.
| Column | Meaning |
|---|---|
| "Time" | When the row was written |
| "Gateway" | The best gateway whose window the decision was based on |
| "Current dr", "Ideal dr" | The DR recorded on the server and the new DR from the command |
| "Current tx power", "Ideal tx power" | The power index recorded on the server and the new one: PWR0 is the maximum power, PWR1 is 2 dB lower, and so on up to PWR10 |
| "Current nbtrans", "Ideal nbtrans" | NbTrans recorded on the server and the new one |
| "Snr margin" | Signal margin, dB |
| "Max snr", "Avg snr" | Maximum and average SNR in the window, dB |
Whether the device applied the new DR is visible in the following uplinks: the SF column of the "Data" table on the same tab.
LinkADRReq and the device's LinkADRAns response are not written to the "MAC command log". The server handles LinkADRAns as follows:
- all three acknowledgements — channel mask, DR and power — are received: the server changes nothing;
- the device rejected the power while the index recorded on the server is 0: the server sets index 1 and no longer assigns index 0 to this device in this gateway's window;
- the server does not roll back other rejections: it reads the actual DR again from the next uplink.
Good to know
- Parameters are recorded when sent, not when acknowledged. The server treats the new DR, power and NbTrans as in effect as soon as it queues LinkADRReq. If the command did not arrive or was rejected and it changed the DR, the server sees the old DR in the next uplink and calculates from it, assuming maximum power (index 0). Power and NbTrans are not visible in the uplink: if only they changed, the server does not learn about the rejection — it treats the new values as in effect and does not resend the command until the decision changes.
- One LinkADRReq in the queue. While a LinkADRReq is in the MAC command queue, the server does not queue another one.
- Statistics are kept per gateway. If another gateway becomes the best, the server decides by that gateway's window and counter; for a gateway that has not been the best before, the window and counter start from zero. Frames received better by another gateway look like gaps in the current gateway's window, so when the best gateway changes often, the server sees higher loss than the actual one and may raise NbTrans.
- After a join — from scratch. On each OTAA activation the SNR and FCnt windows, counters and the MAC command queue are reset. The server rebuilds the device settings without the
adrfield and treats ADR as allowed; a cleared "ADR" checkbox takes effect again only after the device is saved in the ONS interface. - Restart. When the network server (the LWServer process) restarts, the ADR state is kept: it is stored in Redis for 30 days after the last write. This copy survives a restart of Redis itself only if Redis saves its data to disk.
adr_minraises the DR regardless of the signal. The server assigns a DR no lower thanadr_mineven if there is not enough signal margin for that data rate.
Server parameters
These parameters apply to all devices and are set by the startup arguments of LWServer, the ONS network server process. They are needed only by those who deploy ONS themselves.
| Argument | Default | What it sets |
|---|---|---|
--adr_margin | 10 | Installation margin in the margin formula, dB |
--adr_nstep_div | 3 | Decibels of margin per NStep step |
--adr_snr_stat | max | SNR estimate over the window: max — maximum, avg — average |
--adr_window | 20 | Size of the SNR and FCnt window, frames |
--adr_max_gateways | 3 | For how many gateways to keep windows of one device |
--adr_snr_mode | window | window — a window of the latest SNR values; decaying — a decaying maximum without a window: estimate = max(frame SNR, β × previous estimate). In decaying mode no average is kept, and --adr_snr_stat is forced to max |
--adr_decay | 0.9 | Coefficient β for decaying mode |
See also
- Nodes — ADR fields in the node card and the "Adr log" panel.
- Device classes — when a device receives a downlink.
- Frequency plans — channels and data rates of the plans.
create_device_req— ADR fields when registering a device.update_device_req— changing ADR settings through the WebSocket API.