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?