How does ADR work? Possible problem with ADR


i had a sensor (Cubecell HTCC-AB01) using LoRaWAN with TTN in Europe. Joinig is done with OTTA.

The connection had an rssi about -120 db and an snr of -3.

Several packets were lost.

When does ADR increase the SF7BW125?

Is it possible to use ADR and start communication with for example with SF10BW125?



Thank you!

Can I start ADR with SF10B125?
Which command must i use?


please refer the picture.

Hello jasonXU,

thank you!

Some addittional question: You explained the join, but there is also a mechanism during working:

Adaptive Data Rate (ADR) is a mechanism for optimizing data rates, airtime and energy consumption in the network. ADR should be enabled whenever an end device has sufficiently stable RF conditions. This means that it can generally be enabled for static devices. If the static end device can determine that RF conditions are unstable (for example, when a car is parked on top of a parking sensor), ADR should (temporarily) be disabled. Mobile end devices should be able to detect when they are stationary for a longer times, and enable ADR during those times. End devices decide if ADR should be used or not, not the application or the network.

So i have a sensor CUBECELL that had bad radio connection, every 20 packages arrives!

So i now expect an adjustment of the data rate, but it stays at SF7B125. The Join has done!




i testet it!
Join is done with SF11B125 but the next package is send with SF7B125.

“time”: “2020-11-15T10:29:16.206804448Z”,
“frequency”: 868.1,
“modulation”: “LORA”,
“data_rate”: “SF11BW125”,
“coding_rate”: “4/5”,

So i had expected that the communication will continue with SF11B125 and then decrease step by step after some packets to SF7B125 when the radio communication is good enouth.

“time”: “2020-11-15T10:29:25.755650154Z”,
“frequency”: 867.9,
“modulation”: “LORA”,
“data_rate”: “SF7BW125”,
“coding_rate”: “4/5”,

In my opinion the node must wait 64 packets and then it will decrease it’s data rate step by step.

(If ADR_ACK_CNT reaches to ADR_ACK_LIMIT (= 64 frames for EU) it sets the ADRACKReq bit to 1 to ask the network whether it is receiving the uplink messages or not.)

What is wrong?

Greetings E_T

As far as the “How does it work part”, I’ll comment with what I “think” I understand from using US915, hopefully if any is incorrect someone will set me straight.

There are two mechanisms that come into play for ADR, if ADR is enabled at the device. One is controlled at the network side, the other at the device runtime side.

On the network side (TTN, Senet, Helium) the connection strength is tracked for each uplink. I don’t know what all is involved here , signal strength, noise ratio, retries I suppose.

There is an algorithm that decides whether or not the data rate at the device “can be” changed. The idea is to balance device battery usage with connectivity. Lower power means longer battery but less distance reach vs higher power which means shorter battery life but better to reach distant hot spots. I believe this is done over a series of uplink messages, I don’t know the specific number, could depend on a number of factors I suppose.

If the network senses a change can be made it returns via a downlink mac command, separate from or along with user payload data the “suggested” change. The device/runtime is free to accept or ignore the advice. This decision is controlled by the ADR setting at the device. ON to accept/implement the data rate change “if” the runtime supports dynamic data rate changes. OFF to ignore it.

This also assumes your network “supports” ADR, not all do. I believe TTN does but I have no experience there. Helium does not currently but should in the future. I have no clue about Senet.

The device side runtime part is also controlled by the ADR setting.
This is what you are seeing with the ADR_ACK_CNT and ADR_ACK_LIMIT. The idea here is that if the device has not received any downlink messages after a number of uplinks ( your 64) then the assumption is that you have lost communication with the network, the runtime “should” adjust the data rate hoping to restore the communication.

I believe this is a one way trip, data rate decrease no increase. Or used to be with the Cubecell runtime, may have changed recently. I don’t know about other runtimes.

One thing to look out for is if your device app is an uplink only app, where you do not deal with downlink messages. This device side ADR needs to have periodic downlinks in order to reset the counter. If the network does not send any downlinks then it is up to your device app to periodically send a “confirmed” uplink which should result in an ACK from the network, resetting the counter.

This device side ADR is independent of the what the network provides although I do not believe you have API control to turn on/off just one of them. It’s either both or none and perhaps that makes sense,

Also the data rate used for the join is different from that used for the connected communications. at least for US915. I suppose the idea here is to try the lowest power first, then the highest power. Once connected, then use whatever the default or app specified setting is. Again this probably varies by runtime implementation. From there the ADR can keep the balance power vs reach.

So, why is DR not changing sooner that the count of 64? I would suggest the network ADR suggestion is not being seen/handled.

  • Either the network is not suggesting a change, perhaps the algorithm is not being satisfied, not enough uplinks, ADR not supported?
  • The network is suggesting a change but the runtime is not honoring it.
  • The uplink is getting to the network part that does the calculation, but not on to where you can see the message.

Do you see any network downlink messages that may contain the ADR adjustment? This may mean you need to dig into the runtime and add some debug prints. Or perhaps you have access to downlinks via the TTN console?

Thank you leroyle for the detailed answer!

For verification I used the MCCI LoRaWAM LMIC arduino library with a TTGO board.

The join datarate would be kept and only increased after these 64 packets (SF decreased). So i think the network support ADR!

ADR for the CubeCell board is on but uplinkmode is unconfirmed, so i will test it!

I had some stationary nodes with poor reception signal, so i will start communication with SF10BW125 and then ADR can optimise the communication!



I forgot to mention, when the data rate is changed, the max allowable user packet size changes. DR0 ~= 11 bytes, DR3=some higher number of bytes, actual numbers vary by region. This is a regulatory thing.

Some runtimes will truncate the payload and not inform the device app of any transmit problem, others may send it anyway even though it violates the regulatory spec. I have not seen any documentation on which does what, just something to be aware of.
This can be problematic if your payload is larger than some of the possible adjusted data rates may allow.