Arduino LMIC: cannot receive downlink messages

Yes, the time for the RX1 and RX2 windows is at 1 second and 2 seconds after the transmission has finished:

I was assuming that the reason why I am not receiving the download packets is that there is something wrong with the way my code is working.

Would I be wrong to assume, for now, that receive portion of the code is not waking up in time for the download message to be processed or is closing too quickly.

That said, I was wondering how I could track the start and end times when each window opened once the TxDone function was completed.

In each line of the log from the application there is the os tick when this log message was generated. You can check and print the value for OSTICKS_PER_SEC which is a define of the library. For my Arduino this is 62500, but it might be different for your board. With this value you can calculate the actual time value from the ostick value.

Start of the transmission is the TXMODE line and RX1 and RX2 are the RXMODE_SINGLE lines.

Are you sure the backend is using the frequency you expect in the RX2 window? When the band g2 frequency is used, you cannot receive it in the RX2 windows with the current configuration.

That is a very good question and one that needs to be confirmed.
I assume that the only indication of the frequency is the G3 value in the Thingpark log as shown below:


Also the fact that there is an error makes your question extremely valid


There is also the

RX1/RX2Delay: 2000

If this is the total value it seems to be ok, but if this is the delay per window, then it is too long. The software on the device uses 1 second delay for each window.

1 Like

Do you by any chance know how the downlink data is collected?
By that I mean, is there an interrupt, that has to be triggered during the RX 1 and Rx2 window open time, for the data to be download data to be read in?

No. When LMiC prints RXMODE_SINGLE it’s actually listening for a short time, to see if it can recognise the “preamble”, and if it finds that, it will just read the downlink for you. (Actually the LoRa chip will do that for you, when LMiC tells it to.)

As the clock of the node might not be very precise, using MAX_CLOCK_ERROR one can make LMiC start listening a bit earlier, and listen a bit longer.

Also, don’t ignore:

And what did you intend to write here?

First, apologies for the interruption.
I have been trying to figure out how to receive downlink messages, but I am not able to receive anything. Uplink works fine with no problems. The build I am using is the Dragino kit (LG01-P Single-Channel Gateway, Arduino Uno + Dragino LoRa Shield) for US915 MhZ. The IoT server is TTN, activation mechanism is ABP, and the library used is LMIC.

Gateway configuration →

TTN Gateway Traffic →

As Bernd first mentioned (our setup is similar), the gateway packet forwarder code seems to support downlink, and it is indeed receiving downlink from the TTN and transmitting what has been received. →


Node logs →

As shown in the images, I am using 903.3 (SF7BW125) for uplink, and 923.3 (SF12BW500) for downlink.

I have tried incorporating

LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);

in the code, but it didn’t solve the problem.
From what I have observed, the gateway seems to report receiving the downlink and transmitting it just as the node’s log report the second


Thus, I thought of trying to increase the delay value of the RX_1 receive window from the lorabase.h file, but that didn’t help.
Any suggestions? :sweat_smile:

Thanks in advance

Please don’t post logs as images. Now I’ll leave it up to you pinpoint that some of your setup mentions SF9 for downlinks, while the gateway logs shows TTN uses SF12 instead.

See also

Thank you for your reply Arjan. Sorry about the image logs!
I believe you’re referring to the gateway transmit spread factor? I changed it to 12, but no luck.

I just tried changing the SF of the first RX_WINDOW to SF12 to test if it changes anything, but I am still nothing. However, the gateway’s log now reports receiving a downlink and transmitting it just after the node’s serial monitor shows the first RXMODE_SINGLE (I guess the timings are more aligned now?).
Regarding the TTN frequency plans page - am I missing something?

I am quite new to all of this, forgive the ignorance :slight_smile:

Too bad your single channel gateway is apparently using a fixed frequency and SF for downlinks (if I understand the setup screen correctly); for downlinks it could easily use whatever TTN tells it to use. I’m not sure how to read the frequency plan, but TTN and your node are probably using the same settings, while your single channel test gateway seems to use specific settings.

You can see if RX1 or RX2 is supposed to be used by comparing the tmst of the uplink and the downlink. The difference is the time in microseconds. For your previous screenshot it was 2 seconds, hence RX2 indeed.

Hi, one thing that I am still checking out, based on an earlier question of " Are you sure that the backend is broadcasting on the expected frequency?"

It seems that, in my case, we are using the 868 MHz specification, but the Thingpark backend is using, according to their specification, the G3 subband which operates at 434.04 - 434.79 MHz…

So based the fact that you are also not receiving downloads, I would suggest that you also make sure, that the backend is using the expected download frequencies.

TTN frequency plan shown in the link you provided me displays 8 channels for uplink, each channel corresponding to a downlink as well (903.9 → 923.3… 904.1 → 923.9… etc). All un-used ones were disabled (as I am using a SCG).

Therefore, I think specific settings are applied on all 3 sides (TTN, gateway, and node). Logs from the gateway show that every time a downlink message is received, it is received in the same configuration as the ones before.

Then I assume that if I set RX1 & RX2 to (SF12BW500), I’d be guaranteeing receiving it every time if timing is correct? (Since all downlinks coming from TTN seem to be using the same SF, BW, and frequency. Only difference in windows used).

Thanks for your reply sir. I first checked the LMIC library’s lorabase.h file to confirm what frequency is used for downlinks if CFG_915 is used (since I am using US915), and it matches what I specified for downlinks. Also, I have taken a look at the gateway traffic in the TTN console, TTN also seems to be using 923.3.

lorabase.h file

// Default frequency plan for US 915MHz
enum { US915_125kHz_UPFBASE = 902300000,
US915_125kHz_UPFSTEP = 200000,
US915_500kHz_UPFBASE = 903000000,
US915_500kHz_UPFSTEP = 1600000,
US915_500kHz_DNFBASE = 923300000,
US915_500kHz_DNFSTEP = 600000
enum { US915_FREQ_MIN = 902000000,
US915_FREQ_MAX = 928000000 };

Downlink messages seem to have (288 - 329ms) airtime. Is this normal? Uplinks average at 66ms.

Thanks in advance

The devices I have seen operate either in the 868 MHz band or in the 433 MHz band, because the HF part has to be tuned to the specific frequency range. Therefore I think it is highly unlikely that the backend responds in the 433 MHz range when the join request and the uplink operates in the 868 MHz range.

But, as I don’t know the Thingpark backend, I cannot say this for sure.

I total agree with you - currently discussions with local technical folk.
It seems that they are unable to confirm what the download frequency is at the moment, but they are looking into it.
I am now setting up a Microchip dev board as a test bed to see if I have the same problems as on the Feather board.

I have played around with the dragino gateway and I found that the downlink feature is kind of implemented but hardly usable.

First you have to make sure that the packet forwarder is installed on the arduino in the gateway and that it is the version ending with 003.

Then you have to uncomment the following line in the config.h of the LMIC library:


In the main program I set the delay for the first RX window to 3 seconds and increased the value for the clock error to 10%

LMIC.rxDelay = 3;
LMIC_setClockError(MAX_CLOCK_ERROR * 10 / 100);

With these settings I was able to receive a downlink message, but this is hardly usable for more than testing.

It also seems that the downlink message is transmitted by the gateway after the second uplink message from the device. After the first uplink message the downlink counter in the TTN is incremented und probably also sent to the gateway. It seems that the gateway then stores the message and transmits it after the next uplink message was sent. This is somewhat usable as long as just one node device is working with the gateway. As soon as a second device is added it is very likely that the downlink messages are sent to the wrong device.

The current implementation of the dragino packet forwarder seems to have a very high latency which makes it impossible to get anywhere near the correct timing for downlink messages.


Thank you so much for your reply Mr. Bernd. I have successfully received downlink, though “Invalid downlink”, but something is being received nonetheless.

Precisely. It’s the same in my case as well after applying your fix. Downlink is only received after the 2nd uplink transmission is done.
Now I’ll move on to trying to read correct data instead of “Invalid downlinks”.

But for the uplink it specifies SF7 to SF10, while for the downlinks it lists SF7 to SF12. Also, the uplinks have 9 frequencies, the downlinks only 8, so I can only assume that 904.6 SF8 should not be used when relying on downlinks, like when using ADR? Not a clear specification if you’d ask me. Also, US has the notion of “hybrid” which is not mentioned at all?

If that’s true, then I’d not alter my application/node but I’d look for a different test gateway, or get a full gateway.

But indeed, if the downlink has not already been scheduled then TTN might not wait long enough for the application to return a downlink. But then TTN is scheduling it for the next opportunity, not the gateway; see My application's downlink is always queued for next uplink.

(This ESP8266 test gateway worked great for me, for EU868. See also @bluejedi’s list in Single Channel Packet Forwarder part 3 [Deprecated] .)

1 Like