Lora-net / SWL2001

LoRa Basics Modem LoRaWAN stack
BSD 3-Clause Clear License
87 stars 50 forks source link

Trouble joining a LoRaWAN network #52

Closed EddieCarrera closed 2 months ago

EddieCarrera commented 2 months ago

I have built a prototype PCBA board with an STM32L433 MCU interfacing with the LR1120, with the goal of evaluating the L1120. I leveraged the SemTech provided PCB design for the LR1120 layout (https://www.semtech.com/products/wireless-rf/lora-edge/lr1120dvk1tcks#documentation) .

After learning to update the LR1120 firmware to 0x201 (with this repo https://github.com/Lora-net/SWTL001) and porting the SWL2001 driver code to work with the STM32L433, I used the “porting tests” example firmware from SWL2001 to verify that the LR1120 radio is working correctly with the STM32L433 – it passed all tests.

From there I made some changes to the LoRaWAN network configuration “example_options.h” to get the LR1120 to connect to our network. I’m also calling the following: ASSERT_SMTC_MODEM_RC( smtc_modem_set_network_type(stack_id, false) ) to ensure the radio is configured for a private LoRaWAN network (my network is private). However, my gateway only receives a join request packet from the LR1120 intermittently (1 out of 10 tries). It’s also observed that the LR1120 never receives any downlinked “join request accepted” packet even though it’s confirmed that the gateway has sent the packet on its end.

I have a few things I want to try to debug this network connection issue:

1) Lower the max transmit power of the LR1120 to a max of 14dBm. I thought I made the appropriate changes in the code, but the LR1120 continues to send a “join request” packet at the max 22dBm (See screenshot below). I would like to lower the max to 14dBm as a debugging step because I’ve found that a LoRa radio front-end that isn’t perfectly tuned has issues transmitting at max power – which might be the case.

2) I also wanted to disable ADR on the LR1120 stack – which I couldn’t find in the code.

t

I’m still in the process of trying to troubleshoot the root cause of this – as I’m unsure if it’s a firmware configuration issue, or hardware issue. As a troubleshooting step, I am no longer interfacing with the STM32L433 on the custom PCB. Instead, currently am interfacing the LR1120 (on the custom board) with the NUCLEO-L476RG (via jumper wires soldered to the SPI lines), which is what the default out-of-the-box setup for the SWTL001 LR1120 radio library example. However, the exact same behavior persists between the NUCLEO-L476RG and STM32L433 MCU. So this would indicate some sort or hardware/software issue on the LR1120 side rather than the STM32 side.

Any further troubleshoot steps and advice would be appreciated! I have experience with STM32's stackforce LoRaWAN radio stack, so although I'm no expert, I have exposure to the config setup to make an edge device communicate via LoRaWAN.

lbm-team commented 2 months ago

Hi EddieCarrera, Thanks for using LBM.

Does your gateway support 64 uplink channels? When the modem is configured with US915 region, it uses 64 channels (BW125) + 8 channels (BW500). If your gateway only supports 8 uplink channels, you will lose a lot of joinRequest, but when the join is received, the network should downlink the correct configuration based on the gateway configuration.

1) To setup HP vs LP you have to implement your own ral_lr11xx_bsp.c as proposed in lbm_examples/radio_hal/ral_lr11xx_bsp.c

2) To disable ADR you have to use the API smtc_modem_adr_set_profile()

EddieCarrera commented 2 months ago

Thanks for the response!

That's a very good point about the channels. That can be a contributing factor to intermittent join requests being seen by the gateway. I forgot to mention the LoRaWAN network I'm running only utilizes sub-band 1 (channels 1-8). Other LoRaWAN stacks (such at Stackforce's) has an option to enable hybrid mode which limits channel masks on end-nodes, and limits the application to a single sub-band (sub-band 1 in this case). An example of such an implementation is below:

void RegionUS915InitDefaults( InitDefaultsParams_t* params )
{
#if defined( REGION_US915 )
    Band_t bands[US915_MAX_NB_BANDS] =
    {
       US915_BAND0
    };

    switch( params->Type )
    {
        case INIT_TYPE_DEFAULTS:
        {
            if( ( params->NvmGroup1 == NULL ) || ( params->NvmGroup2 == NULL ) )
            {
                return;
            }

            RegionNvmGroup1 = (RegionNvmDataGroup1_t*) params->NvmGroup1;
            RegionNvmGroup2 = (RegionNvmDataGroup2_t*) params->NvmGroup2;

            // Initialize 8 bit channel groups index
            RegionNvmGroup1->JoinChannelGroupsCurrentIndex = 0;

            // Initialize the join trials counter
            RegionNvmGroup1->JoinTrialsCounter = 0;

            // Default bands
            memcpy1( ( uint8_t* )RegionNvmGroup1->Bands, ( uint8_t* )bands, sizeof( Band_t ) * US915_MAX_NB_BANDS );

            // Default channels
            for( uint8_t i = 0; i < US915_MAX_NB_CHANNELS - 8; i++ )
            {
                // 125 kHz channels
                RegionNvmGroup2->Channels[i].Frequency = 902300000 + i * 200000;
                RegionNvmGroup2->Channels[i].DrRange.Value = ( DR_3 << 4 ) | DR_0;
                RegionNvmGroup2->Channels[i].Band = 0;
            }
            for( uint8_t i = US915_MAX_NB_CHANNELS - 8; i < US915_MAX_NB_CHANNELS; i++ )
            {
                // 500 kHz channels
                RegionNvmGroup2->Channels[i].Frequency = 903000000 + ( i - ( US915_MAX_NB_CHANNELS - 8 ) ) * 1600000;
                RegionNvmGroup2->Channels[i].DrRange.Value = ( DR_4 << 4 ) | DR_4;
                RegionNvmGroup2->Channels[i].Band = 0;
            }

            // Default ChannelsMask
            /* ST_WORKAROUND_BEGIN: Hybrid mode */
#if ( HYBRID_ENABLED == 1 )
            RegionNvmGroup2->ChannelsDefaultMask[0] = 0x00FF;
            RegionNvmGroup2->ChannelsDefaultMask[1] = 0x0000;
            RegionNvmGroup2->ChannelsDefaultMask[2] = 0x0000;
            RegionNvmGroup2->ChannelsDefaultMask[3] = 0x0000;
            RegionNvmGroup2->ChannelsDefaultMask[4] = 0x0001;
            RegionNvmGroup2->ChannelsDefaultMask[5] = 0x0000;
#else
            RegionNvmGroup2->ChannelsDefaultMask[0] = 0xFFFF;
            RegionNvmGroup2->ChannelsDefaultMask[1] = 0xFFFF;
            RegionNvmGroup2->ChannelsDefaultMask[2] = 0xFFFF;
            RegionNvmGroup2->ChannelsDefaultMask[3] = 0xFFFF;
            RegionNvmGroup2->ChannelsDefaultMask[4] = 0x00FF;
            RegionNvmGroup2->ChannelsDefaultMask[5] = 0x0000;
#endif /* HYBRID_ENABLED == 1 */
            /* ST_WORKAROUND_END */

            // Copy channels default mask
            RegionCommonChanMaskCopy( RegionNvmGroup2->ChannelsMask, RegionNvmGroup2->ChannelsDefaultMask, CHANNELS_MASK_SIZE );

            // Copy into channels mask remaining
            RegionCommonChanMaskCopy( RegionNvmGroup1->ChannelsMaskRemaining, RegionNvmGroup2->ChannelsMask, CHANNELS_MASK_SIZE );
            break;
        }
        case INIT_TYPE_RESET_TO_DEFAULT_CHANNELS:
        {
            // Intentional fallthrough
        }
        case INIT_TYPE_ACTIVATE_DEFAULT_CHANNELS:
        {
            // Copy channels default mask
            RegionCommonChanMaskCopy( RegionNvmGroup2->ChannelsMask, RegionNvmGroup2->ChannelsDefaultMask, CHANNELS_MASK_SIZE );

            for( uint8_t i = 0; i < CHANNELS_MASK_SIZE; i++ )
            { // Copy-And the channels mask
                RegionNvmGroup1->ChannelsMaskRemaining[i] &= RegionNvmGroup2->ChannelsMask[i];
            }
            break;
        }
        default:
        {
            break;
        }
    }
#endif /* REGION_US915 */
}

Is there a similar method of limiting the channels in lbm-lib? If not, what would you recommend the best approach to do this?

1) I'm using the default ral_lr11xx_bsp.c as-is for the nucleo-l476rg. I already tried limiting the power to 14dBm by changing

#define LR11XX_MIN_PWR_LP_LF -17
#define LR11XX_MAX_PWR_LP_LF 15

#define LR11XX_MIN_PWR_HP_LF -9
#define LR11XX_MAX_PWR_HP_LF 22

#define LR11XX_MIN_PWR_PA_HF -18
#define LR11XX_MAX_PWR_PA_HF 13

to

#define LR11XX_MIN_PWR_LP_LF -17
#define LR11XX_MAX_PWR_LP_LF 14

#define LR11XX_MIN_PWR_HP_LF -9
#define LR11XX_MAX_PWR_HP_LF 14

#define LR11XX_MIN_PWR_PA_HF -18
#define LR11XX_MAX_PWR_PA_HF 13

But the TRACE output when running the periodic_uplink.c example still indicates that a join request from the sensor is being sent at 22dBm (see screenshot in original post). Is there something else I should modify within ral_lr11xx_bsp. to achieve this?

2) I've previously tried exploring smtc_modem_adr_set_profile() as you suggested, but I couldn't find documentation for '@param [in] dr_custom_distribution_data Definition of the custom datarate distribution', so I wasn't sure how exactly to set it up. Would the following from smtc_modem_core/lorawan_certification/lorawan_certification.c be enough to disable it:

(lines 602-608)

            if( rx_buffer[1] == ( uint8_t ) LORAWAN_CERTIFICATION_ADR_OFF )
            {
                uint8_t adr_custom_data[16] = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
                                                0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
                smtc_modem_adr_set_profile( lorawan_certification_obj->stack_id, SMTC_MODEM_ADR_PROFILE_CUSTOM,
                                            adr_custom_data );
            }

Would you be able to point me in the right direction for more information on how to implement 'adr_custom_data'?

I have purchased and received the LR1120DVK1TCKS eval kit. I will play around with it, and keep this thread updated.

Edit: I'm experiencing the same behavior with the out-of-the-box eval board setup. This eliminates the potential for these issues to be hardware related (for now). I'll keep modifying and playing with the stack until I can get the eval-board to connect to my network.

Edit: I'm currently modifying \lbm_lib\smtc_modem_core\lr1mac\src\smtc_real\src\region_us_915_defs.h to try and align the configuration of the end node with the LoRaWAN network. Modifying

`

define TX_POWER_EIRP_US_915 (14) // define in dbm

` was the solution in limiting Tx power. However, the same intermittent join behavior is occurring. I'm using a spectrum analyzer and can confirm that the join network packet from the LR1120 is centered around freq:905000000. This should be within sub-band 1 of LoRaWAN (my current LoRaWAN configuration), so it's a bit strange that the gateway is still only receiving this 'join request' packet intermittently.

EddieCarrera commented 2 months ago

Okay, I found the correction. As seen above, the sync word is set up for public (0x34) instead if private (0x12). It was because I did the following:

ASSERT_SMTC_MODEM_RC( smtc_modem_set_network_type(stack_id, false) );  
ASSERT_SMTC_MODEM_RC( smtc_modem_set_region( stack_id, MODEM_EXAMPLE_REGION ) );

As it turns out, smtc_modem_set_network_type() must be called after smtc_modem_set_region() for the sync word to stick. After making this fix, the eval-board now reliably connects to my LoRaWAN network. I'll use this config to ensure my custom board with the LR1120 now works.

mluis1 commented 2 months ago

@EddieCarrera Just for info the Stackforce LoRaMac-node stack as you call it does not provide an hybrid mode and never has. On the other hand the LoRaMac-node stack fork provided by ST does.

In LoRaWAN specifications there is no hybrid mode specified.

Please refer to the following Zephyr project issue comment for further details about the US915/AU915 regions Join procedure. https://github.com/zephyrproject-rtos/zephyr/issues/70889#issuecomment-2031221027

I let the @lbm-team answer the other questions.

EddieCarrera commented 2 months ago

Initial implementation seems to be working, I'll go ahead and close this now, but it would still be very useful if all my questions above are answered in case I run into related integration issues as I continue to develop with the stack.