LMIC_setDrTxpow() questions

For ABP LMIC_setDrTxpow() needs to be called explicitly .

As far as I’m aware, for OTAA this is not required and defaults are used.

However, the following included OTAA examples do call LMIC_setDrTxpow(DR_SF7,14) explicitly.

  • helium-otaa.ini
  • ttn-otaa-feather-us915.ino
  • ttn-otaa-feather-us915-dht22.ino
  • ttn-otaa-halconfig-us915.ino

Why this is done appears to be explained (only) in ttn-otaa-feather-us915-dht22.ino:

    // Set the data rate to Spreading Factor 7.  This is the fastest supported rate for 125 kHz channels, and it
    // minimizes air time and battery power. Set the transmission power to 14 dBi (25 mW).

In lmic_bandplan_eu868.h:

#define LMICbandplan_getInitialDrJoin() (EU868_DR_SF7)

In lmic_bandplan_us915.h:

#define LMICbandplan_getInitialDrJoin() (LORAWAN_DR0)

In lmic_bandplan_au915.h:

#define LMICbandplan_getInitialDrJoin() (LORAWAN_DR2)


  • I assume that for OTAA #define LMICbandplan_getInitialDrJoin() defines the initial DR/SF used for a join if no SF is explicitly set by the user.
    Is that correct?

  • My interpretation of “RP002-1.0.2 LoRaWAN Reginal Parameters” p31, for US915 is that LORAWAN_DR0 is the same as DR_SF10.
    Is that correct?

  • My interpretation of “RP002-1.0.2 LoRaWAN Reginal Parameters” p31, for AU915 is that LORAWAN_DR2 is the same as DR_SF10.
    Is that correct?

  • Does this mean that SF10 is the standard SF to start a join for both US915 and AU915?

  • If not, then why is SF10 set as default?

  • The US915 OTAA examples which call LMIC_setDrTxpow(DR_SF7,14) explicitly apparently do this to speed up the join process and use as little power as possible. This will however only have a positive effect if the gateway is near enough to use higher DR’s.
    Is it correct to assume that setting SF explicitly to SF7 (for ‘US like’) is application dependent or would you advise to use this in general?

  • In example ttn-abp.ino (and other examples) LMIC_setDrTxpow(DR_SF7,14) is called independent of any region settings check.
    Is it safe to call LMIC_setDrTxpow(DR_SF7,14) for all regions?

  • What about Tx power? Is there one default value for all regions or is there a separate default value per region?

It sets the initial DR/SF, full stop. User choices are lost during the JoinAccept processing.


Yes, because AU also support SF11 and SF12.

I use the LoRaWAN 1.0.3 regional params as the reference – that’s what the LMIC supports. But in fact, these two happen to coincide. It is accidental-on-purpose, I believe.

The code in all the examples for doing US was not working when I started work on the LMIC. We were trying to push changes up stream, and trying to maintain compatibility with upstream examples in 2017 or so; so these things are historical. (We wanted examples to work even if using the old LMIC.)

I think this is really only effective after the join. I don’t think the Join uses SF7 at all any more. However, without a call, the LMIC defaults to SF10 in the US after the join. LinkADR (if enabled) along with the LMICs automatic choice of higher data-rates to accommodate big payloads reduces or eliminates the need for this, in most cases.

When using networks like ChirpStack, the network does a number of other things like initializing the repeat count to three, and then reducing it as it concludes that it has device connectivity.

It is safe according to the specs. TX power of 14 dBm is pretty low, but is permitted.

Every region has different maximum power requirements. You’re likely to get best performance by not touching this at all (with current LMIC and current network servers). For example, US allows up to 30 dBm. EU allows much less (I think 14 is the always-safe value). Further complicating things is that the LMIC interprets TX power as “measured conducted power”, because that’s what the the SX1276 knows. This happens to be perfect for the US, but not so good for EU and other regions that use EIRP or ERP – also measured in decibels, but with an adjustment that depends on the antenna in use.

If you’re using a 3dB antenna, it turns out that 14 dB to the LMIC is roughly the same as 16 dB EIRP (because there’s always some loss between transmitter and antenna: EIRP = TX(dB) - Loss(dB) + AntennaGain(dB). That’s why all the examples (from Europe, after all, since the LMIC originally only supported Europe) set the transmit power to 14 dB.

There is an open bug to add an API that allows the LMIC to be informed about the antenna gain and system loss; that would allow for better handling of all this. But… it’s not done.

The region plans all have flags that (possibly incorrectly – always allow for the fact that this was all done in a hurry without review) indicate whether the region uses conducted power or EIRP: LMIC_REGION_EIRP.

So… the best thing would be to get rid of manual adjustment of Tx power and data rate in all OTAA sketches. I don’t know what to do about ABP; despite it’s reputation for simplicity, I find it very hard to use correctly and therefore think of it as an advanced feature. Since I don’t use it, I have no concrete basis for opinion on “what’s the right thing to do” – that would have to come out of field experience.

Thanks for your answers.

(I’ll probably have some related questions later.)

Wow, the ‘save edit’ checker is getting really annoying!
I am unable to edit the message and make some minor changes to it.
Therefore my post update now includes my annoyance about this Discourse feauture (I’ve never seen it in action before).

capture 2021-05-18 14·32·28

Yeah. It’s a bit officious. Maybe it can be disabled. I’ll take a quick look.

1 Like

There are many, many knobs – one of them might control this but not clear which one. Happy to take advice if there are any discourse experts around.

1 Like

Your answer is not fully clear.

Did you mean:

“YES, LMICbandplan_getInitialJoin() gets the initial DR/SF value used for a join but this initial value CAN be overruled by the user (by calling LMIC_setDrTxpow() after calling os_init() and LMIC_reset())”?


"NO, LMICbandplan_getInitialJoin() gets the initial DR/SF value used for a join and the initial value cannot be changed by the user by calling LMIC_setDrTxpow()"?

And the initial value will get lost during the JoinAccept processing (irrespective of whether default value determined by the library or its override set by the user).

I had the impression you meant the first but trying it in practice showed the second:

I tried to set the initial SF to DR_SF10 (EU868 for which DR_SF10 is 2) with LMIC_setDrTxpow() (with a slightly modified version of LMIC-node) but debug output showed the following:

000000080731:  setDrTxPow(2, 14)
000000083861:  Event: EV_JOINING
85801: engineUpdate, opmode=0x4

000000085834:  doWork job started
395969: engineUpdate, opmode=0x4
000000396012:  Event: EV_TXSTART
398084: TXMODE, freq=868500000, len=23, SF=7, BW=125, CR=4/5, IH=0
713699: setupRx1 txrxFlags 00 --> 01
start single rx: now-rxtime: 1
714328: RXMODE_SINGLE, freq=868500000, SF=7, BW=125, CR=4/5, IH=0

So it just used the default (EU868) initial value SF7, not SF10 that I set and wanted it to use.

Sorry, I misunderstood your question. I thought you were referring to what happens after join.

When initializing a join, the LMIC calls LMICbandplan_getDrJoin() douring initialization of the join loop, and immediately sends the first join request. So… there’s no effective way to change the first uplink SF.

It appears that it’s currently possible to change the SF of subsequent uplinks in EU, although that is not specified behavior (i.e., is fragile and indeed likely to break in future versions).

It is probably possible to do something similarly hacky in US/AU, but you would have to deal with the fact that the LMIC is itself changing SFs (to go between BW125kHz and BW500kHz).

So: the official behavior is (in fact): the DR is set by LMICbandplan_getInitialDrJoin() and you can’t reliably influence it, other than by patching that routine.