LoRa Rx window timing debugging

  • Objective

    Reliably join a LoRaWAN network though OTAA & send/receive data.


    The following setup, except the end device, works for a few hundred other devices which have been working for months. None of the already working end devices are Pycom products.

    End device

    FiPy with the following version:

    (sysname='FiPy', nodename='FiPy', release='1.20.2.r6', version='v1.11-c5a0a97 on 2021-10-28', machine='FiPy with ESP32', lorawan='1.0.2', sigfox='1.0.1', pybytes='1.7.1')


    MikroTik LoRa gateway configured as a packet forwarder.

    The gateway LoRa channels are the following:

    Number Frequency (MHz) Bandwidth
    0 868.1 125 kHz
    1 868.3 125kHz
    2 868.5 125kHz
    3 867.1 125kHz
    4 867.3 125kHz
    5 867.5 125kHz
    6 867.7 125kHz
    7 867.9 125kHz
    8 868.3 250kHz
    9 868.8 125kHz

    LoRa Server

    Debian machine with the whole ChirpStack server stack:

    • ChirpStack Gateway Bridge
    • ChirpStack Network Server
    • ChirpStack Application Server

    Note: ChirpStack is configured with the default configuration files used in this guide.

    End device code

    import time
    import pycom
    import binascii
    import socket
    from network import LoRa
    if __name__ == "__main__":
        lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868, device_class=LoRa.CLASS_A, public=1, adr=0, tx_retries=0)
        for i in range(0, 16):
        lora.add_channel(index=0, frequency=868100000, dr_min=0, dr_max=5)
        lora.add_channel(index=1, frequency=868300000, dr_min=0, dr_max=5)
        lora.add_channel(index=2, frequency=868500000, dr_min=0, dr_max=5)
        lora.add_channel(index=3, frequency=867100000, dr_min=0, dr_max=5)
        lora.add_channel(index=4, frequency=867300000, dr_min=0, dr_max=5)
        lora.add_channel(index=5, frequency=867500000, dr_min=0, dr_max=5)
        lora.add_channel(index=6, frequency=867700000, dr_min=0, dr_max=5)
        lora.add_channel(index=7, frequency=867900000, dr_min=0, dr_max=5)
        lora.add_channel(index=8, frequency=868300000, dr_min=0, dr_max=5)
        lora.add_channel(index=9, frequency=868800000, dr_min=0, dr_max=5)
        dev_eui = binascii.unhexlify('0000000000000000')
        app_eui = binascii.unhexlify('0000000000000000')
        app_key = binascii.unhexlify('00000000000000000000000000000000')
        lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0, dr=0)
        def rxcb(arg):
            print("RX callback received: {}".format(arg))
        lora.callback(LoRa.RX_PACKET_EVENT, rxcb)
        while not lora.has_joined():
        # create a LoRa socket
        sock = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
        # set the LoRaWAN data rate
        sock.setsockopt(socket.SOL_LORA, socket.SO_DR, 5)
        # make the socket blocking
        # (waits for the data to be sent and for the 2 receive windows to expire)
        # send some data
        sock.send(bytes([0x01, 0x02, 0x03]))
        # make the socket non-blocking
        # (because if there's no data received it will block forever...)
        # get any data received (if any...)
        data = sock.recv(64)


    Observed behaviour

    Some JoinRequest messages appear to get "lost" as they do not appear in the gateway traffic log. To my understanding the FiPy sends a new JoinRequest message every ~10 seconds.

    It a significant amount of JoinAccept messages to successfully join the network and, once joined, very rarely receives a scheduled downlink message. All JoinRequest messages received by the gateway are successfully sent to & authenticated by the LoRa server, the JoinAccept response however, does not reach the end device.


    Some forum threads have mentioned that similar issues may be related to an incompatibility with the gateway's channels. Therefore, the FiPy's code has been modified to remove the default channel configuration and replace it with the gateway's. This has resulted in a significant improvement with the JoinRequest messages being lost.


    Since downlinks only appear to work every few hundred attempts there might be a problem with the Rx window timing.
    I would expect this to be thouroughly tested in the LoRa firmware as the issue would be present on all Pycom devices.

    Is there any way to debug this issue?

    Any other hypothesis/solutions are welcome.
    Thank you

Pycom on Twitter