ADR steht für Adaptive Data Rate und ermöglicht es dem Node seinen Spreading Factor (SF) automatisch zu ändern. Dieses ist für feste Nodes eher uninteressant, jedoch für sich bewegende Nodes schon eher. Nicht überall habt ihr optimalen Empfang ein Node der fest mit SF7 sendet, verbraucht zwar minimal Airtime, wird aber eventuell nicht oft genug empfangen. ADR kann dieses verbessern, da der Node damit in regelmäßigen Abständen eine Bestätigung vom Netzwerk verlangt. Bleibt diese aus, wird der SF angepasst und erhöht. Somit wird versucht einen optimalen Empfang des Nodes zu erreichen. Wenn der Node besseren Empfang hat, wird er durch das Netzwerk aufgefordert seinen SF wieder zu verringern. ADR funktioniert nur mit OTAA Nodes, bei ABP wird alles fest eingestellt.
Die Wahl der richtigen Library
Ich hatte schon vor etwas längerer Zeit angekündigt etwas zu dem Thema zu schreiben. Da ich aber massive Probleme mit ADR hatte und es nicht funktionierte, habe ich es gelassen. Das Problem lag an der verwendeten LMIC-Bibliothek.
Bis dato habe ich immer die LMIC-Arduino library von Matthijs Kooijman verwendet und jedem zu ihr geraten, der Probleme mit dem Speicher hatte. Diese hatte aber anscheinend einen Fehler im ADR, bzw Link Check eingebaut. Verwendet man ADR ohne Link Check, dann steigert der Node langsam seinen SF, bis er irgendwann bei 12 angekommen ist und bleibt dort auch. Auf MAC Kommandos des TTN Netzwerkes reagiert er auch nicht. Aktiviert man dazu dann auch noch den Link Check, dann stellt der Node den Sendebtrieb ein, wenn er einen fehlenden Link erkennt. Nur nach einem Reset, fängt er wieder an. Mag auch sein, das ich hier den Fehler gemacht habe, ich kam jedenfalls nicht weiter.
Nun habe ich den Fork von MCCI getestet und hatte sofortigen Erfolg. Ich habe nichts an meinem Sketch angepasst und ADR funktioniert auf Anhieb. Zusätzlich wird der Fork weiterentwickelt und regelmäßig erscheinen Updates.
Anpassung der Library
Eine kleine Gemeinheit wartet auf euch, wenn ihr die Library von GitHub zieht. In dem Unterverzeichnis project_config liegt die Datei lmic_project_config.h . Mit dieser Datei wird der Frequenz-Plan und die verwendete Hardware angepasst. In der GitHub Variante ist dort US aktiv, und somit werdet ihr von eurem Node nichts empfangen. Also einfach CFG_eu868 aktivieren und es sollte keine Probleme geben. CFG_sx1276 ist passend zum beliebten RFM95W. Das sind die minimalen Anpassungen. Zusätzlich können Features wie PING und BEACONs deaktiviert werden, um Speicher zu sparen. Class A Nodes benötigen diese eh nicht. Mehr dazu findet ihr auf GitHub.
// project-specific definitions
#define CFG_eu868 1
//#define CFG_us915 1
//#define CFG_au921 1
//#define CFG_as923 1
// #define LMIC_COUNTRY_CODE LMIC_COUNTRY_CODE_JP /* for as923-JP */
//#define CFG_in866 1
#define CFG_sx1276_radio 1
//#define LMIC_USE_INTERRUPTS
Konfiguration von ADR
Ihr müsst eigentlich nur zwei Stellen anpassen, dann sollte es auch schon funktionieren. In vielen Sketches, wird im Joined Event, der Link Check Mode abgeschaltet, dieses müsst ihr ändern und entsprechende Zeile auskommentieren.
case EV_JOINED:
debugPrintLn(F("EV_JOINED"));
//LMIC_setLinkCheckMode(0);
break;
Zusätzlich aktivieren wir ADR und den Link Chekc Mode im Setup. Die Einträge kommen nach dem LMIC_reset(); Wenn ihr Probleme mit dem Join habt, dann fügt auch den setClockError Eintrag hinzu, der kann euch einiges an Suche ersparen.
void setup() {
...
LMIC_setAdrMode(1);
LMIC_setLinkCheckMode(1);
LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);
...
}
Das Ergebniss – Wie sieht ADR aus?
In dem unten dargestellten Test kann man schön sehen, wie der Node seinen SF von 7 auf 9 erhöht und anschließend wieder auf 7 absenkt. Weitere Tests werden folgen, aber es sieht erst mal sehr gut aus.
Mir ist jedoch eine relativ große Verzögerung aufgefallen. Es brauchte, in meinem Fall, ca. 70 (es sind 64) fehlerhafte Uplinks, bevor der SF gewechselt wurde. Das ist viel, ich würde mir ein schnelleres Ansprechverhalten wünschen, aber evtl. ist es so auch besser. Über den Punkt kann man sicherlich streiten. Ein zu aggressives Verhalten der Nodes wäre sicherlich auch schädlich für das Netzwerk.
Anmerkungen 25.02.2019: Dank dieses Beitrages im Forum, bin ich auch etwas schlauer. Nach 64 Uplinks, verlangt der Node ein ADR ACK. Dieser werte sind in den regionalen LoRaWAN Parameters definiert und sind somit auch fest vorgegeben. Wenn der Node diesen ACK nicht innerhalb von 32 weiteren Uplinks empfängt, bzw. den nachgeschalteten Downlink, dann steigert er seinen SF. Danach fangen die Counter wieder bei 0 an. Es werden also mindestens 96 Uplinks benötigt, um den SF um einen Wert anzupassen. Hier ist nochmals alles beschrieben.
ADR_ACK_LIMIT 64
ADR_ACK_DELAY 32
Hier nochmals ein anderer Test aus Sicht der Konsole. Der Node kann sein 98. Paket wieder senden und erhält daraufhin eine Bestätigung. Das Paket 99 wird auch wieder bestätigt und danach wird ohne ACK weitergesendet. Dabei hat der Node seinen SF von 9 auf 7 angepasst.
Darf es noch etwas mehr sein?
Eine Kleinigkeit habe ich noch für euch. Ihr könnt eurem Node anweisen, den Join mit einem höheren SF zu starten. Damit ist die Chance größer, das er auch eine Verbindung aufbauen kann. Sollte es der die Empfangsqualität zulassen, wird er dieses automatisch anpassen. In folgendem Beispiel, wird der Node einen Join mit SF10 versuchen. Nach den nun bekannten 64 Paketen, wird er den SF notfalls anpassen.
case EV_JOINING:
LMIC_setDrTxpow(DR_SF10,14);
break;
Ich hoffe ich konnte euch helfen und ihr könnt für euch erfolgreich ADR einsetzen.
Hi Björn,
danke für diesen coolen Blogeintrag. Ich beschäftige mich auch gerade mit LoRa und TTN. Demnächst wollte ich das Thema OTAA und ADR angehen und hätte das gleiche Problem gehabt, da ich bisher auch die Lib von Matthijs Kooijman verwende.
Ich werde definitiv an dich denken, wenn ich zum ersten mal ADR aktiviere 😉