Intermittent/unreliable data transmission on TTNA/LORAWAN



  • Hi all,

    I recently joined the Pycom family after purchasing a Pygate and Lopy4 (running on a Pysense 2). I have followed the getting started guides to set up the Pygate and Lopy4 for Australia (AU915) and put together a basic sketch to test the auth and data transfer on the LORAWAN network (using ABP and a slightly modified version of the example sketch). I will intermittently get a payload appear and the connected status will indicate a recent connection in the in the TTN console but that is very rare and intermittent (like 5 or 6 times a day).

    I have an arduino running a basic ABP sketch and on the Pygate I can see it connecting and delivering its payload 100% of the time which to me indicates the Pygate is working fine. I believe the issue lies with the Lopy/sketch. Does anybody have any experience troubleshooting this type of issue? I have tried OTAA but had the same issues?

    MY TEST SKETCH

    import socket
    import time
    from network import LoRa
    import binascii
    import struct
    import machine
    import pycom
    from pysense import Pysense
    
    py = Pysense()
    
    # Initialize LoRa in LORAWAN mode.
    # Please pick the region that matches where you are using the device:
    # Asia = LoRa.AS923
    # Australia = LoRa.AU915
    # Europe = LoRa.EU868
    # United States = LoRa.US915
    lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.AU915)
    
    dev_addr = struct.unpack(">l", binascii.unhexlify('MYADDRESS'))[0]
    nwk_swkey = binascii.unhexlify('MYADDRESS')
    app_swkey = binascii.unhexlify('MYADDRESS')
    
    # Joining TTN via ABP
    print("Joining TTN via ABP")
    lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey))
    
    # Configure TTN socket
    s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
    s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5)
    s.setblocking(False)
    
    # Send test payload
    print("Sending data ...")
    s.send(bytes([1, 2, 3]))
    
    #Allow time for data transmission
    time.sleep(60)
    
    #Put the board in to deep sleep for X amount of time
    print("Pysense initiating sleep")
    py.setup_sleep(600)
    py.go_to_sleep()
    

    ARDUINO TRAFFIC ON THE PYGATE
    PygateTraffic.png



  • @Gijs Perfect!! Thanks for your help.



  • Yes, its listed here: https://docs.pycom.io/tutorials/networks/lora/nvram/
    Maybe the name is a bit confusing, but it saves the data to non volatile storage and then you can safely deepsleep



  • @jcaron This is awesome info!! This approach seems to work as well, I have 100% data transmission.

    I have been trying to work out what I needed to do before putting the device into deep sleep. Are you able to point me in the direction of some doco or an example on how to save and restore the LoRa state?

    Gateway_Traffic.png



  • @Gijs Thanks for this, I tested the example and it works 100%!!

    When settings this up I look in the following places for the doco:
    https://docs.pycom.io/tutorials/networks/lora/lorawan-abp/
    https://www.thethingsnetwork.org/docs/devices/lopy/usage.html

    Am I correct in thinking I can change the dr_max and socket data rate to 5 as it is supported in AU? https://avbentem.github.io/airtime-calculator/ttn/au915/8

    Thanks again for your help, I really appreciate it.



  • @Gijs @Matt-Walter To be precise, AU915 has 72 uplinks channels: 64 channels with BW125 (numbered 0-63) and 8 with BW500 (numbered 64-71).

    Gateways usually listen on 9 of them (8 BW125 and 1 BW500). Which ones they listen on depends on the network and gateway configuration.

    The TTN frequency plan for AU915 uses channels 8 to 15 (frequencies 916.8 MHz to 918.2 MHz BW 125) and channel 65 (917.5 MHz BW 500).

    Many operations (like RX1 channel selection) are based on the channel uplink channel number modulo 8, so using channel numbers 0-7 instead of 8-15 doesn't matter for those, but I would expect some MAC commands (those which update the list of channels to use and the like) to fail miserably if there is a mismatch.

    It's probably easier to keep the existing "correct" channels (8-15, 65) which should already pre-configured with the right settings (BW, DR...) and just remove the ones not in use (0-7, 16-64, 66-71). Something like:

    for i in range(0,8):
        lora.remove_channel(i)
    for i in range(16,65):
        lora.remove_channel(i)
    for i in range(66,72):
        lora.remove_channel(i)
    

    (I didn't test it as I'm not in a region with such issues).

    Of course the Pygate must indeed be appropriately configured for the same frequencies (as described by @Gijs)

    @Matt-Walter Also, if you use deep sleep, you need to save (before going to sleep) and restore (when waking up) the LoRa state, as that will at last have the correct frame counters, but also any information sent by the network about channels to use or not use, frequencies, DRs, RX offsets, and whatnot.



  • The AU915 range covers 64 channels, while the gateway only listens to 8, I have attached an example that sets the correct channels on the lopy

    from network import LoRa
    import socket
    import ubinascii
    import struct
    import time
    # Initialise LoRa in LORAWAN mode.
    # Please pick the region that matches where you are using the device:
    # Asia = LoRa.AS923
    # Australia = LoRa.AU915
    # Europe = LoRa.EU868
    # United States = LoRa.US915
    lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.AU915)
    print("joining")
    # create an ABP authentication params
    dev_addr = struct.unpack(">l", ubinascii.unhexlify(''))[0]
    nwk_swkey = ubinascii.unhexlify('')
    app_swkey = ubinascii.unhexlify('')
    #Do not transmit on the channels outside the Pygate scope
    for i in range(0,64):
        lora.remove_channel(i)
        
    lora.add_channel(0, frequency=916800000, dr_min=0, dr_max=3)
    lora.add_channel(1, frequency=917000000, dr_min=0, dr_max=3)
    lora.add_channel(2, frequency=917200000, dr_min=0, dr_max=3)
    lora.add_channel(3, frequency=917400000, dr_min=0, dr_max=3)
    lora.add_channel(4, frequency=917600000, dr_min=0, dr_max=3)
    lora.add_channel(5, frequency=917800000, dr_min=0, dr_max=3)
    lora.add_channel(6, frequency=918000000, dr_min=0, dr_max=3)
    lora.add_channel(7, frequency=918200000, dr_min=0, dr_max=3)
    # join a network using ABP (Activation By Personalization)
    lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey))
    # create a LoRa socket
    s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
    # set the LoRaWAN data rate
    s.setsockopt(socket.SOL_LORA, socket.SO_DR, 3)
    # make the socket blocking
    # (waits for the data to be sent and for the 2 receive windows to expire)
    s.setblocking(True)
    # send some data
    s.send(bytes([0x01, 0x02, 0x03]))
    # make the socket non-blocking
    # (because if there's no data received it will block forever...)
    s.setblocking(False)
    # get any data received (if any...)
    data = s.recv(64)
    print(data)
    

    (I have not tested this exact adaptation, but it should work for you)

    I want to add this to the documentation, where would you expect / have looked for this information?



  • @robert-hh Here is the config from the Pygate

    {
    	"SX1301_conf": {
    		"lorawan_public": true,
    		"clksrc": 1,
    		"clksrc_desc": "radio_1 provides clock to concentrator for most devices except MultiTech. For MultiTech set to 0.",
    		"antenna_gain": 0,
    		"antenna_gain_desc": "antenna gain, in dBi",
    		"radio_0": {
    			"enable": true,
    			"type": "SX1257",
    			"freq": 917200000,
    			"rssi_offset": -166.0,
    			"tx_enable": true,
    			"tx_freq_min": 915000000,
    			"tx_freq_max": 928000000
    		},
    		"radio_1": {
    			"enable": true,
    			"type": "SX1257",
    			"freq": 917900000,
    			"rssi_offset": -166.0,
    			"tx_enable": false
    		},
    		"chan_multiSF_0": {
    			"desc": "Lora MAC, 125kHz, all SF, 916.8 MHz",
    			"enable": true,
    			"radio": 0,
    			"if": -400000
    		},
    		"chan_multiSF_1": {
    			"desc": "Lora MAC, 125kHz, all SF, 917.0 MHz",
    			"enable": true,
    			"radio": 0,
    			"if": -200000
    		},
    		"chan_multiSF_2": {
    			"desc": "Lora MAC, 125kHz, all SF, 917.2 MHz",
    			"enable": true,
    			"radio": 0,
    			"if": 0
    		},
    		"chan_multiSF_3": {
    			"desc": "Lora MAC, 125kHz, all SF, 917.4 MHz",
    			"enable": true,
    			"radio": 0,
    			"if": 200000
    		},
    		"chan_multiSF_4": {
    			"desc": "Lora MAC, 125kHz, all SF, 917.6 MHz",
    			"enable": true,
    			"radio": 1,
    			"if": -300000
    		},
    		"chan_multiSF_5": {
    			"desc": "Lora MAC, 125kHz, all SF, 917.8 MHz",
    			"enable": true,
    			"radio": 1,
    			"if": -100000
    		},
    		"chan_multiSF_6": {
    			"desc": "Lora MAC, 125kHz, all SF, 918.0 MHz",
    			"enable": true,
    			"radio": 1,
    			"if": 100000
    		},
    		"chan_multiSF_7": {
    			"desc": "Lora MAC, 125kHz, all SF, 918.2 MHz",
    			"enable": true,
    			"radio": 1,
    			"if": 300000
    		},
    		"chan_Lora_std": {
    			"desc": "Lora MAC, 500kHz, SF8, 917.5 MHz",
    			"enable": true,
    			"radio": 0,
    			"if": 300000,
    			"bandwidth": 500000,
    			"spread_factor": 8
    		},
    		"chan_FSK": {
    			"desc": "disabled",
    			"enable": false
    		},
    		"tx_lut_0": {
    			"desc": "TX gain table, index 0",
    			"pa_gain": 0,
    			"mix_gain": 8,
    			"rf_power": -6,
    			"dig_gain": 0
    		},
    		"tx_lut_1": {
    			"desc": "TX gain table, index 1",
    			"pa_gain": 0,
    			"mix_gain": 10,
    			"rf_power": -3,
    			"dig_gain": 0
    		},
    		"tx_lut_2": {
    			"desc": "TX gain table, index 2",
    			"pa_gain": 0,
    			"mix_gain": 12,
    			"rf_power": 0,
    			"dig_gain": 0
    		},
    		"tx_lut_3": {
    			"desc": "TX gain table, index 3",
    			"pa_gain": 1,
    			"mix_gain": 8,
    			"rf_power": 3,
    			"dig_gain": 0
    		},
    		"tx_lut_4": {
    			"desc": "TX gain table, index 4",
    			"pa_gain": 1,
    			"mix_gain": 10,
    			"rf_power": 6,
    			"dig_gain": 0
    		},
    		"tx_lut_5": {
    			"desc": "TX gain table, index 5",
    			"pa_gain": 1,
    			"mix_gain": 12,
    			"rf_power": 10,
    			"dig_gain": 0
    		},
    		"tx_lut_6": {
    			"desc": "TX gain table, index 6",
    			"pa_gain": 1,
    			"mix_gain": 13,
    			"rf_power": 11,
    			"dig_gain": 0
    		},
    		"tx_lut_7": {
    			"desc": "TX gain table, index 7",
    			"pa_gain": 2,
    			"mix_gain": 9,
    			"rf_power": 12,
    			"dig_gain": 0
    		},
    		"tx_lut_8": {
    			"desc": "TX gain table, index 8",
    			"pa_gain": 1,
    			"mix_gain": 15,
    			"rf_power": 13,
    			"dig_gain": 0
    		},
    		"tx_lut_9": {
    			"desc": "TX gain table, index 9",
    			"pa_gain": 2,
    			"mix_gain": 10,
    			"rf_power": 14,
    			"dig_gain": 0
    		},
    		"tx_lut_10": {
    			"desc": "TX gain table, index 10",
    			"pa_gain": 2,
    			"mix_gain": 11,
    			"rf_power": 16,
    			"dig_gain": 0
    		},
    		"tx_lut_11": {
    			"desc": "TX gain table, index 11",
    			"pa_gain": 3,
    			"mix_gain": 9,
    			"rf_power": 20,
    			"dig_gain": 0
    		},
    		"tx_lut_12": {
    			"desc": "TX gain table, index 12",
    			"pa_gain": 3,
    			"mix_gain": 10,
    			"rf_power": 23,
    			"dig_gain": 0
    		},
    		"tx_lut_13": {
    			"desc": "TX gain table, index 13",
    			"pa_gain": 3,
    			"mix_gain": 11,
    			"rf_power": 25,
    			"dig_gain": 0
    		},
    		"tx_lut_14": {
    			"desc": "TX gain table, index 14",
    			"pa_gain": 3,
    			"mix_gain": 12,
    			"rf_power": 26,
    			"dig_gain": 0
    		},
    		"tx_lut_15": {
    			"desc": "TX gain table, index 15",
    			"pa_gain": 3,
    			"mix_gain": 14,
    			"rf_power": 27,
    			"dig_gain": 0
    		}
    	},
    	"gateway_conf": {
    		"server_address": "router.au.thethings.network",
    		"serv_port_up": 1700,
    		"serv_port_down": 1700,
    		"servers": [ {
    			"server_address": "router.au.thethings.network",
    			"serv_port_up": 1700,
    			"serv_port_down": 1700,
    			"serv_enabled": true
            } ],
            "gateway_ID": "45b98b097087aedf",
            "keepalive_interval": 10,
            "stat_interval": 30,
            "push_timeout_ms": 100,
            "forward_crc_valid": true,
            "forward_crc_error": false,
    		"forward_crc_disabled": false,
    		"fake_gps": true,
    		"ref_latitude": -26.602380,
    		"ref_longitude": 153.027713,
    		"ref_altitude": 0
    	}
    
    }
    


  • @robert-hh I am 99% sure they do. The Lopy is set to region=LoRa.AU915 which matches the Pygate channel plan.



  • @Matt-Walter Do the channel sets of LoPy and Pygate match? Otherwise the LoPy may send on freqeuncies at which the PyGate does not listen.


Log in to reply
 

Pycom on Twitter