Skip to main content

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 adr field, 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.

Warning

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:

DRRequired 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 indexSNRmax, dBMargin, dBNStepAfter: DR, power index
DR0, 0+33 − (−20) − 10 = 134DR4, 0
DR5, 0+1212 − (−7.5) − 10 = 9.53DR5, 3 (−6 dB)
DR5, 0−5−5 − (−7.5) − 10 = −7.5−2DR3, 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 windowCurrent NbTrans 1Current NbTrans 2Current NbTrans 3
Below 5%112
5–10%123
10–30%233
30% and above333

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​

FieldIn the interfaceDefaultWhat it does
adr"ADR"trueAllows 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"20After how many uplink frames, counted by FCnt increments, the server makes a decision. 0 — no decisions
adr_min"Adr min"DR0Lower limit: at decision time the server raises the DR to adr_min even if the signal margin is not enough
adr_max"Adr max"DR5Currently does not limit ADR, see below
adr_fix"Adr fix"Not setFixed 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
Warning

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 ChMask 01FF, 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:

ByteContents
1CID 03
2DR in the upper 4 bits, power index in the lower 4 bits
3–4ChMask
5ChMaskCntl 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_interval uplinks, 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.

ColumnMeaning
"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 adr field 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_min raises the DR regardless of the signal. The server assigns a DR no lower than adr_min even 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.

ArgumentDefaultWhat it sets
--adr_margin10Installation margin in the margin formula, dB
--adr_nstep_div3Decibels of margin per NStep step
--adr_snr_statmaxSNR estimate over the window: max — maximum, avg — average
--adr_window20Size of the SNR and FCnt window, frames
--adr_max_gateways3For how many gateways to keep windows of one device
--adr_snr_modewindowwindow — 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_decay0.9Coefficient β for decaying mode

See also​