Lolin32 ESP + OLG-02 Gateway Downlink Not Received

Hi there,

Currently I’m working on the setup using Lolin32 using RFM95 HopeRF communicating with the OLG-02 Dragino. The code I’m using is basically TTN-ABP code from Arduino-LMIC Library. I only change the pinmap, input the FILLMEIN section, and the frequency setting at the project config file. Things I’ve done this far:

  1. Adjusting LMIC_setClockError
  2. Adjusting the distance between gateway and the node
  3. Adjusting the Rx2 window to SF7 to adjust with the gateway TX window, and make sure either timing received by the gateway can be received by the node
  4. Updating the gateway firmware to the latest version

RXTX~ (RXPKT): [up] {“rxpk”:[{“time”:“2011-12-31T17:22:39.685198Z”,“tmst”:2561550987,“chan”:0,“rfch”:1, “freq”:923.200000,“stat”:1,“modu”:“LORA”,“datr”:“SF7BW125”,“codr”:“4/5”,“lsnr”:8 .0,“rssi”:-92,“size”:26,“data”:“QA8YBCaAAAAB1V59GB7xuSnChmheVbqX/7U=”}]}
Sun Jan 1 00:22:40 2012 lg02_pkt_fwd[4365]:
Sun Jan 1 00:22:40 2012 lg02_pkt_fwd[4365]: RXTX~ (TXPKT): [down] { “txpk”:{“imme”:false,“tmst”:2562550987,“freq”:923.2,“rfch”:0,“powe”:14,“modu”:“L ORA”,“datr”:“SF7BW125”,“codr”:“4/5”,“ipol”:true,“size”:24,“ncrc”:true,“data”:“oA 8YBCYAIQMBeykk2dDHz2V/xhSW//6S”}}
Sun Jan 1 00:22:40 2012 lg02_pkt_fwd[4365]: jitqueue.c:219:jit_enqu eue(): Current concentrator time is 2562176078, pkt_type=0
Sun Jan 1 00:22:40 2012 lg02_pkt_fwd[4365]: jitqueue.c:196:jit_sort _queue(): sorting queue in ascending order packet timestamp - queue size:1
Sun Jan 1 00:22:40 2012 lg02_pkt_fwd[4365]: jitqueue.c:198:jit_sort _queue(): sorting queue done - swapped:0
Sun Jan 1 00:22:40 2012 lg02_pkt_fwd[4365]: jitqueue.c:531:jit_prin t_queue(): INFO: [jit] queue contains 1 packets:
Sun Jan 1 00:22:40 2012 lg02_pkt_fwd[4365]: jitqueue.c:532:jit_prin t_queue(): INFO: [jit] queue contains 0 beacons:
Sun Jan 1 00:22:40 2012 lg02_pkt_fwd[4365]: jitqueue.c:538:jit_prin t_queue(): - node[0]: count_us=2562550987 - type=0
Sun Jan 1 00:22:40 2012 lg02_pkt_fwd[4365]: jitqueue.c:397:jit_enqu eue(): enqueued packet with count_us=2562550987 (size=24 bytes, toa=61000 us, ty pe=0)
Sun Jan 1 00:22:40 2012 lg02_pkt_fwd[4365]: jitqueue.c:512:jit_peek (): peek packet with count_us=2562550987 at index 0
Sun Jan 1 00:22:40 2012 lg02_pkt_fwd[4365]: jitqueue.c:527:jit_prin t_queue(): INFO: [jit] queue is empty
Sun Jan 1 00:22:40 2012 lg02_pkt_fwd[4365]: jitqueue.c:441:jit_dequ eue(): dequeued packet with count_us=2562550987 from index 0
Sun Jan 1 00:22:40 2012 lg02_pkt_fwd[4365]:
Sun Jan 1 00:22:40 2012 lg02_pkt_fwd[4365]: INFO~ Transmit at SF7BW 125 on 923.200000.
Sun Jan 1 00:22:40 2012 lg02_pkt_fwd[4365]: INFO~ Donwlink done: co unt_us=2562550987

9881: TXMODE, freq=923200000, len=26, SF=7, BW=125, CR=4/5, IH=0
Packet queued
75247: setupRx1 txrxFlags 00 --> 01
start single rx: now-rxtime: 4
75880: RXMODE_SINGLE, freq=923200000, SF=7, BW=125, CR=4/5, IH=0
rxtimeout: entry: 76919 rxtime: 75872 entry-rxtime: 1047 now-entry: 5 rxtime-txend: 62126
137497: setupRx2 txrxFlags 0x1 --> 02
start single rx: now-rxtime: 4
138129: RXMODE_SINGLE, freq=923200000, SF=7, BW=125, CR=4/5, IH=0
rxtimeout: entry: 139681 rxtime: 138122 entry-rxtime: 1559 now-entry: 5 rxtime-txend: 124376
139699: processRx2DnData txrxFlags 0x2 --> 00
139760: processDnData_norx txrxFlags 00 --> 20
140020: EV_TXCOMPLETE (includes waiting for RX windows)

TTN Console

I’m looking forward to hearing any more suggestions :smiley:

Note that Dragino do not recommend the LG-02 for connection to TTN, from their own product page;

“For Private LoRa Protocol, Not recommend for LoRaWAN use.”

1 Like

Yes, I am actually very aware of this. OLG-02 itself is a dual channel gateway and I reckon if the TX RX frequrency for both channels are configured properly, it should still be able to communicate properly, no?

…and you are also aware that using a single/dual packet forwarder engine such as this vs a full LoRaWAN compliant 8 channel (minimum) gateway on TTN potentially disrupts the use of TTN for other users who arent configuring their nodes specifically to work with your GW’s fixed/limited channel offering, causing confusion, apparent mis-operation, lost packets, delayed/in effective joins or confirmed packets/downlinks etc. costing them time effort and money?! Big hint as called out on other threads such devices are not recomeneded and are considered deprecated within the community… but still it might work for you and you want to use it right?! :wink: (Sorry if that sounds brutal/sacrcastic - british humour :slight_smile: - but have been burnt by these before costing me real money and have just had one pop up close to some deployed GW’s in one community and we are seeing impact :frowning: ) Pls use on a private network if you must…

1 Like

Unfortunately, what you are saying is true :slight_smile: and I completely agree with you. However, the circumstances here in our region fortunately, there hasn’t been any LoRaWAN gateway set-up around our area and this work we do now is used for a pilot project that act as our private network :smiley: and decides for future upgrade for full compliance with LoRaWAN standard. I’m though still working to make this work, if you have any suggestions for me to tweak or work on would probably be very helpful and appreciated :smiley:

We had a single channel one locally pop up… Absolute pain with our nodes

The problem with your setup is that it is making your life more difficult because you are using a ‘gateway’ which is not suited for the task. In stead of having to debug just the node side, you now have two unknowns which need debugging.
In principle it should work, however if it doesn’t there is a lot that might cause the issues and it is hard to debug.

Looking at the logging the response should be in the RX1 window at the frequency the module is listening. However timing could be the issue, is the LG02 transmitting at the right moment? Is the node listing at that time? There is no easy way to debug this.


Sorry I had to post here because I dont have the rights to post yet.

Starting with some context, Im on an internship in a small company in Morocco and Im required to grab data from some sensors (for beehives) and send them through a gateway to a network server (TTN which a guy here told me) using LoraWAN (which i know nothing of).

I read a whole 150 pages LoRaWAN book from a university in the alliance, I understood how it operates and everything. And this week I’ve been trying to move to practice. What the company has is HopeRF RFM95 LoRa transceiver modules (plug onto arudino UNOs) and dragino OLG02 gateways.

This week, I first registered my gateway on TTN under the EU863-870 frequency plan and configured the IoT server on my gateway.(It connected)

Primary LoRaWAN Server
Service Provider	
Custom / Private LoRaWAN
Server Address
Uplink Port	
Downlink Port	

I then manually configured my gateway (since it has only 2 channels one for TX and one for RX) like in the picture below.

Then I moved to my arduino uno, i plugged the rfm95 on the default spi connections (10-13), and the plugged the DIO0-2 on 2,3,4.

The activation method im using is OTAA.

Im using the latest MCCI LMIC library, and I went to try my setup on the ttn-otaa example of the library.

Since my gateway has hardcore limitations (only one downlink fixed channel, one uplink fixed channel), I manually setup in the code 1 uplink channel on 868.1,SF7Dr and 14 dBm transmit power and setup the RX2 window freq on 869.525 and datarate to SF9.

I also correctly modified the …_config.h :

// project-specific definitions
#define CFG_eu868 1
//#define CFG_us915 1
//#define CFG_au915 1
//#define CFG_as923 1
//#define LMIC_COUNTRY_CODE LMIC_COUNTRY_CODE_JP      /* for as923-JP; also define CFG_as923 */
//#define CFG_kr920 1
//#define CFG_in866 1
//#define CFG_sx1272_radio 1
#define CFG_sx1276_radio 1
#define DISABLE_PING // Used in class B, useless for A
#define DISABLE_BEACONS //same 
#define LMIC_ENABLE_arbitrary_clock_error 1

I’ll come to why I did somethings later. But at that time, I defined the CFG_eu868 and the sx1276 radio (since my hoperf got a rf96 on it, i didnt find othing in the datasheet about sx1276, but chatgpt told me rf96 indicates that it’s a sx1276 ^^')

Here is my code :

 * Copyright (c) 2015 Thomas Telkamp and Matthijs Kooijman
 * Copyright (c) 2018 Terry Moore, MCCI
 * Permission is hereby granted, free of charge, to anyone
 * obtaining a copy of this document and accompanying files,
 * to do whatever they want with them without any restriction,
 * including, but not limited to, copying, modification and redistribution.
 * This example sends a valid LoRaWAN packet with payload "Hello,
 * world!", using frequency and encryption settings matching those of
 * the The Things Network.
 * This uses OTAA (Over-the-air activation), where where a DevEUI and
 * application key is configured, which are used in an over-the-air
 * activation procedure where a DevAddr and session keys are
 * assigned/generated for use with all further communication.
 * Note: LoRaWAN per sub-band duty-cycle limitation is enforced (1% in
 * g1, 0.1% in g2), but not the TTN fair usage policy (which is probably
 * violated by this sketch when left running for longer)!

 * To use this sketch, first register your application and device with
 * the things network, to set or generate an AppEUI, DevEUI and AppKey.
 * Multiple devices can use the same AppEUI, but each device has its own
 * DevEUI and AppKey.
 * Do not forget to define the radio type correctly in
 * arduino-lmic/project_config/lmic_project_config.h or from your BOARDS.txt.

#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>

// For normal use, we require that you edit the sketch to replace FILLMEIN
// with values assigned by the TTN console. However, for regression tests,
// we want to be able to compile these scripts. The regression tests define
// COMPILE_REGRESSION_TEST, and in that case we define FILLMEIN to a non-
// working but innocuous value.
# define FILLMEIN 0
# warning "You must replace the values marked FILLMEIN with real values from the TTN control panel!"
# define FILLMEIN (#dont edit this, edit the lines that use FILLMEIN)

// This EUI must be in little-endian format, so least-significant-byte
// first. When copying an EUI from ttnctl output, this means to reverse
// the bytes. For TTN issued EUIs the last bytes should be 0xD5, 0xB3,
// 0x70.
static const u1_t PROGMEM APPEUI[8]={0x34, 0x12, 0x2F, 0xA7, 0x49, 0xB5, 0xBD, 0xC1};
void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8);}

// This should also be in little endian format, see above.
static const u1_t PROGMEM DEVEUI[8]={0x01, 0x8B, 0x06, 0xD0, 0x7E, 0xD5, 0xB3, 0x70};
void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8);}

// This key should be in big endian format (or, since it is not really a
// number but a block of memory, endianness does not really apply). In
// practice, a key taken from ttnctl can be copied as-is.
static const u1_t PROGMEM APPKEY[16] = {0x22, 0x7F, 0xBA, 0x65, 0xA1, 0xCF, 0xA3, 0x80, 0x07, 0xFE, 0x6A, 0x9C, 0x3B, 0xDA, 0xCC, 0x04};
void os_getDevKey (u1_t* buf) {  memcpy_P(buf, APPKEY, 16);}

static uint8_t mydata[] = "Hello, world!";
static osjob_t sendjob;

// Schedule TX every this many seconds (might become longer due to duty
// cycle limitations).
const unsigned TX_INTERVAL = 120;

// Pin mapping
const lmic_pinmap lmic_pins = {
    .nss = 10,
    .rxtx = LMIC_UNUSED_PIN,
    .rst = 5,
    .dio = {2, 3, 4},

void printHex2(unsigned v) {
    v &= 0xff;
    if (v < 16)
    Serial.print(v, HEX);

void onEvent (ev_t ev) {
    Serial.print(": ");
    switch(ev) {
        case EV_SCAN_TIMEOUT:
        case EV_BEACON_FOUND:
        case EV_BEACON_MISSED:
        case EV_BEACON_TRACKED:
        case EV_JOINING:
        case EV_JOINED:
              u4_t netid = 0;
              devaddr_t devaddr = 0;
              u1_t nwkKey[16];
              u1_t artKey[16];
              LMIC_getSessionKeys(&netid, &devaddr, nwkKey, artKey);
              Serial.print("netid: ");
              Serial.println(netid, DEC);
              Serial.print("devaddr: ");
              Serial.println(devaddr, HEX);
              Serial.print("AppSKey: ");
              for (size_t i=0; i<sizeof(artKey); ++i) {
                if (i != 0)
              Serial.print("NwkSKey: ");
              for (size_t i=0; i<sizeof(nwkKey); ++i) {
                      if (i != 0)
            // Disable link check validation (automatically enabled
            // during join, but because slow data rates change max TX
	    // size, we don't use it in this example.
        || This event is defined but not used in the code. No
        || point in wasting codespace on it.
        || case EV_RFU1:
        ||     Serial.println(F("EV_RFU1"));
        ||     break;
        case EV_JOIN_FAILED:
        case EV_REJOIN_FAILED:
        case EV_TXCOMPLETE:
            Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
            if (LMIC.txrxFlags & TXRX_ACK)
              Serial.println(F("Received ack"));
            if (LMIC.dataLen) {
              Serial.print(F("Received "));
              Serial.println(F(" bytes of payload"));
            // Schedule next transmission
            os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
        case EV_LOST_TSYNC:
        case EV_RESET:
        case EV_RXCOMPLETE:
            // data received in ping slot
        case EV_LINK_DEAD:
        case EV_LINK_ALIVE:
        || This event is defined but not used in the code. No
        || point in wasting codespace on it.
        || case EV_SCAN_FOUND:
        ||    Serial.println(F("EV_SCAN_FOUND"));
        ||    break;
        case EV_TXSTART:
        case EV_TXCANCELED:
        case EV_RXSTART:
            /* do not print anything -- it wrecks timing */
        case EV_JOIN_TXCOMPLETE:
            Serial.println(F("EV_JOIN_TXCOMPLETE: no JoinAccept"));

            Serial.print(F("Unknown event: "));
            Serial.println((unsigned) ev);

void do_send(osjob_t* j){
    // Check if there is not a current TX/RX job running
    if (LMIC.opmode & OP_TXRXPEND) {
        Serial.println(F("OP_TXRXPEND, not sending"));
    } else {
        // Prepare upstream data transmission at the next possible time.
        LMIC_setTxData2(1, mydata, sizeof(mydata)-1, 0);
        Serial.println(F("Packet queued"));
    // Next TX is scheduled after TX_COMPLETE event.

void setup() {

    // interrupt setup
    //pinMode(2, INPUT_PULLUP);
    //pinMode(3, INPUT_PULLUP);

    LMIC_setClockError(MAX_CLOCK_ERROR * 2 / 100);

    // LMIC init
    // Reset the MAC state. Session and pending data transfers will be discarded.

    for (int channel = 0; channel < 9; channel++) {
        if (channel == 0) {
            LMIC_setupChannel(channel, 868100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI);
        } else {

    LMIC_setDrTxpow(DR_SF7, 14);

    LMIC.dn2Dr = DR_SF9; // Set downlink datarate for RX2 window (commonly SF12 in EU868)
    LMIC.dn2Freq = 869525000;
    // Start job (sending automatically starts OTAA too)

void loop() {

I also
I’ll give the chronological orders of events and what I did down below :
-First upload of the code onto my arduino, I got to see an uplink on my gateway on RXTX logread of my gateway, I was happy ^^. So a forward join accept downlink message has been issued by TTN.

  • First upset, I dont get any JoinAccepts on my arduino. I first thought there was something wrong with my code, downlink frequency or data rate, but I removed the doubt by seeing it on the frequency plan and also by thinking that if it’s properly (corresponding values) setup on the gateway and in my code then it should work.

-I kept trying uplinks, second upset! My gateway rarely catches my uplinks, I didnt get the motivation to sit yet and keep sending uplinks and see at what rate does my gateway hold onto my uplinks. But what I know for sure is that they are rarely caught (not as rare from what i’ve seen on my ttn history, an average of 6mins between each uplink caught, and it’s not a signal power problem (all the uplinks caught and forwarded to TTN are of a mid quality average SNR of 10 and average RSSI of 65 at a distance of 5m no walls, I mean there is a wall if we draw a straight line but if we take a small curve there is a door ^^). I also dont think it’s a duty cycle issue, cuz I believe that is handled on the hardware side and server side, and that my gateway should be able to intercept every packet sent on that fixed channel by my hardware.
I also stand to say that nobody in my region uses gateways and lorawan (a traditional agriculture area), and I just came to know why OLG02 gateways are bad for the community thanks to this thread. But I am sure that Im not messing with somebodies packets (according to the CEO) and also seen the history of the gateway through the days, nothin except my packets are received.
This said, my gateway shouldnt be busy to the point it catches 1 uplink in a long period and the others are lost.

  • I ignored that problem and focused on getting a join accept with those rarely caught uplinks, so I went to see when the “no JoinAccept” is sent to me on the arduino and when does the downlink show on my gateways logread, I found out that a downlink pops on my gateway waaaaaaaaay before the noJoinAccept is sent on my arduino serial monitor, after some research that led to me to the conclusion that it’s a Timing problem.
    -So I went to the LMIC library README and went to the Timing part and read it, I read it once and didnt do deeper research to comprehend how it exactly works. But lets say I understood what’s written and nthin deeper than that, so I went on desperately trying the different solutions (that’s why I got the enable arbitrary to disable the clockerr being capped at maxError) like the setClockError, enabling interrupts instead of polling events from the pins, disabling the different features that are not used for class A devices. All for the hope of getting the timing right, and getting that JoinAccept.

Now I ran out of options :frowning:, and Im seeking help from wise people. I also want to say that im just an intern at a company, so im supposed to make things work with the given material. If I also were to suggest to buy new material (seen that gateways that are not LoraWAN compliant are hated ^^), my internship would come to an end (not stopped) but I just wouldn’t have nothing to do and nothing to say on my internship report (no positive results).

I would appreciate any help and recommandations.


You will see that LoRaWAN is predicated on atleast 8 channels (with potentially 6 SF’s)

Your ‘GW’ or DCPF:-

Is by definitition only 2 channel - either used as single channel or dual channel config as you acknowledge

Dragino themselves call it out as a LoRa GW not a LoRaWAN GW

On the nodes:

This is a LoRaWAN stack - not a LoRa proprietary implementation and the node expects to RX/TX across the gammut of available Channels & SF’s

Fundamentally this will then explain much of the problems/‘upsets’ you go on to call out

Get a LoRaWAN GW - simples! Dragino do many and there are lots of low cost devices in the market


You will have no way of knowing!

Sorry but what position on e.g. the L-A does

The have - you admit you do not know/.have much experience of LoRaWAN/TTN - is the CEO an expert in the field?! (Unless the CEO of a LORaWAN focussed company I would consider that unlikely :wink: )

When deployed your GW would potentially see ‘occasional’ traffic & that would be enough to disrupt those users if not correctly configured, also LoRaWAN deployments expand over time - no nodes in range to day does not mean no nodes tomorrow or next week or next year…but your (LoRa) GW wont have changed so problems are then likely emmergent.

Solution is be LoRaWAN compliant and observing from day 1 (or use an alternate private network vs community)

I completely understand, I will make the suggestion for the CEO. And the Lora GW will change and won’t be used after my elaborations to him. It’s just that I need to move forward a bit in the mean time, the time he buys and receives a new gateway.

I know that what Im doing isn’t clean and smooth, but it’s just that I want to do something about the internship. I can’t stand still and dont really have time to wait for delivery.

I hope you understand. If I sit still I won’t learn nothing I just want to make it work and have a result even if it’s ugly, afterall none of what I do now is going to be put in official production in the near future. So it’s basically just a testing project, and I would genuinely like to see some results.

If It was me alone, and im funding my own project. I would defo buy proper material without questionning, but you know how it is when you’re just tasked.

Thanks in advance,

  1. You can’t make things work with software if the hardware is not compliant and not capable of doing what is needed.
  2. Non compliant gateways disrupt the network for other users. So they’re not hated, they simply f*ck things up for others. What would you think if someone did that to your setup?
  3. If you can’t get new material you need to implement something that is not LoRaWAN with the existing hardware. LoRaWAN is out of the question because of the hardware limitations.

So we tell you how to break TTN as a standby solution, a new comer to the community who we don’t know, and trust you will switch over to a full gateway after your CEO finds out you’ve got it working.

That’s not how professional developers behave. They provide recommendations & find a way to explain the technicals. You can ask your tutors to contact any one of @Jeff-UK, @kersing or me, @descartes to explain to them that you were coerced in to a position that was not appropriate.

As for waiting for delivery, I very much doubt that you can’t get hold of a TTIG on a 2 to 3 day delivery to a major city in a North African country that is directly connected via a very narrow part of the Mediterranean. You can then convert it to a using an external antenna. And in parallel, order any one of gateways from any of the commercial distributors that are shipping to pretty much anywhere in the world via DHL, UPS, FedEx etc on a weekly basis (apart from Iran or North Korea).

The nature of hive monitoring, not that I’m an expert, not even on how they are setup in North African countries*, is that gateways are deployed in various locations. So eventually a SCPF or DCPF will impact other users causing the authorities to be asked to investigate. If you don’t outline the situation to the CEO about these choices, an email that you CC to yourself and your tutor, there won’t be anything to show you have acted professionally.

Time to man up, not that you’ve got much choice, because help to break TTN is not forthcoming here.

  • Or maybe I am, for realz.


I thank you for all the responses.

I sent an email to the CEO, he claimed that he knows all the limitations and then went to say that 1 channel is enough to assure a OTAA communication with 1 device ignoring the 50 lines that I wrote him…

He claims that it was functionnal before. I then went to ask the technical manager on whether it worked or not, he said that it did and then somebody messed with it and it stopped working.

Now what confuses me is that when I asked him whether they did it with OTAA and if they received the JoinAccept downlink, he said that they did receive it. Meanwhile when I was roaming in the dragino wiki, I found out that to make it work, the device haaaas to be in ABP Mode " To work with single channel gateway, users need to set Dragino End Device to work in ABP mode and transmit in only one frequency .".

Assuming what they claim is valid, my theory is that there have been some releases that nerfed it.

I’m sorry for yall for sharing this delicate situation, it really is not my fault.

No, it’s not your fault and you are in a tricky situation.

The OLG02 is not able to listen on all the channels (8) and all the spreading factors (6) - in fact it can only do two channels with one spreading factor, so 2 out of 48. So there may well be users in the area that you don’t know about. So we can’t help you break a system that others may be using.

If it’s just a single device that’s needed, you can look at other (off-topic) options for point to point LoRa. Or setup a copy of TTS OS and use that as your server but even if you do that, we can’t share details on how to break TTN if we happen to know at all, so you will still have to figure out how to do make it work.

If this internship is a university placement, please feel free to show this thread to your tutor so that they understand what is happening.

I’d also add that once you have two or three devices working and the CEO wants to roll out sensors on many hives, you will then have to take up a subscription for TTI. So making your life difficult now is only going to delay the inevitable additional pain of getting things to work on a commercial sized solution.