Issue :
Hi, I’m struggling with connection using OTAA example code on Rak4631 module on a longfi network from Helium on region AU915 (Brazil) but no matter what I do it keeps returning OTAA Join Failed after the set number of tryies.
Setup :
AU915 sub band 2 (already tried sub band 5, 4 and 8 as hotspots nearby where transmitting their beacon on those bands accordingly to the helium explorer webapp) without success.
Docs :
Using code from: longfi-platformio/main.cpp at master · helium/longfi-platformio · GitHub
Details :
Here is what aways happens
14:35:55.844 > <BRD> SyncWord = 2414
14:35:55.844 > <BRD> LoRa Task started
14:35:55.844 > =====================================
14:35:55.844 > Welcome to RAK4630 LoRaWan!!!
14:35:55.844 > Type: OTAA
14:35:55.844 > Region: AU915
14:35:55.844 > =====================================
14:35:55.845 > <LMH> OTAA
14:35:55.845 > DevEui=60-81-F9-E1-A5-E8-C8-1B
14:35:55.845 > DevAdd=00000000
14:35:55.845 > AppEui=60-81-F9-5E-95-44-90-82
14:35:55.845 > AppKey=XX-XX-XX (here I have defined based on Helium Console keys as MSB)
14:35:55.918 > <LMH> Selected subband 2
14:35:56.918 > <LMH> Selected subband 2
14:35:57.918 > Starting Join
14:35:57.940 > Return from join
14:35:58.311 > <LM> OnRadioTxDone
14:35:58.313 > <LM> OnRadioTxDone => RX Windows #1 4991 #2 6002
14:35:58.313 > <LM> OnRadioTxDone => TX was Join Request
14:36:03.311 > <RADIO> RX window timeout = 3000
14:36:07.274 > <RADIO> RadioIrqProcess => IRQ_RX_TX_TIMEOUT
14:36:07.274 > <LM> OnRadioRxTimeout
14:36:07.436 > <LM> Join network failed 1 time(s)
14:36:07.436 >
14:36:35.435 > <LM> OnRadioTxDone
14:36:35.436 > <LM> OnRadioTxDone => RX Windows #1 4991 #2 6002
14:36:35.437 > <LM> OnRadioTxDone => TX was Join Request
14:36:40.435 > <RADIO> RX window timeout = 3000
14:36:44.395 > <RADIO> RadioIrqProcess => IRQ_RX_TX_TIMEOUT
14:36:44.395 > <LM> OnRadioRxTimeout
14:36:44.560 > <LM> Join network failed 2 time(s)
14:36:44.560 >
14:37:12.558 > <LM> OnRadioTxDone
14:37:12.559 > <LM> OnRadioTxDone => RX Windows #1 4991 #2 6002
14:37:12.560 > <LM> OnRadioTxDone => TX was Join Request
14:37:17.558 > <RADIO> RX window timeout = 3000
14:37:21.519 > <RADIO> RadioIrqProcess => IRQ_RX_TX_TIMEOUT
14:37:21.519 > <LM> OnRadioRxTimeout
14:37:21.683 > <LM> Join network failed 3 time(s)
14:37:21.683 >
14:37:21.683 > <LM> LoRaMacState = idle
14:37:21.683 > OTAA join failed!
14:37:21.683 > Check your EUI's and Keys's!
14:37:21.683 > Check if a Gateway is in range!
Code :
/**
* file LoRaWAN_OTAA_ABP.ino
* author rakwireless.com
* brief LoRaWan node example with OTAA/ABP registration
* version 0.1
* date 2020-08-21
*
* copyright Copyright (c) 2020
*
* note RAK4631 GPIO mapping to nRF52840 GPIO ports
RAK4631 <-> nRF52840
WB_IO1 <-> P0.17 (GPIO 17)
WB_IO2 <-> P1.02 (GPIO 34)
WB_IO3 <-> P0.21 (GPIO 21)
WB_IO4 <-> P0.04 (GPIO 4)
WB_IO5 <-> P0.09 (GPIO 9)
WB_IO6 <-> P0.10 (GPIO 10)
WB_SW1 <-> P0.01 (GPIO 1)
WB_A0 <-> P0.04/AIN2 (AnalogIn A2)
WB_A1 <-> P0.31/AIN7 (AnalogIn A7)
*/
#include <Arduino.h>
#include <LoRaWan-RAK4630.h>
#include <SPI.h>
// RAK4630 supply two LED
#ifndef LED_BUILTIN
#define LED_BUILTIN 35
#endif
#ifndef LED_BUILTIN2
#define LED_BUILTIN2 36
#endif
bool doOTAA = true; // OTAA is used by default.
#define SCHED_MAX_EVENT_DATA_SIZE APP_TIMER_SCHED_EVENT_DATA_SIZE /**< Maximum size of scheduler events. */
#define SCHED_QUEUE_SIZE 60 /**< Maximum number of events in the scheduler queue. */
#define LORAWAN_DATERATE DR_0 /*LoRaMac datarates definition, from DR_0 to DR_5*/
#define LORAWAN_TX_POWER TX_POWER_5 /*LoRaMac tx power definition, from TX_POWER_0 to TX_POWER_15*/
#define JOINREQ_NBTRIALS 3 /**< Number of trials for the join request. */
DeviceClass_t g_CurrentClass = CLASS_A; /* class definition*/
LoRaMacRegion_t g_CurrentRegion = LORAMAC_REGION_AU915; /* Region:EU868*/
lmh_confirm g_CurrentConfirm = LMH_UNCONFIRMED_MSG; /* confirm/unconfirm packet definition*/
uint8_t gAppPort = LORAWAN_APP_PORT; /* data port*/
/**brief Structure containing LoRaWan parameters, needed for lmh_init()
*/
static lmh_param_t g_lora_param_init = {LORAWAN_ADR_ON, LORAWAN_DATERATE, LORAWAN_PUBLIC_NETWORK, JOINREQ_NBTRIALS, LORAWAN_TX_POWER, LORAWAN_DUTYCYCLE_ON};
// Foward declaration
static void lorawan_has_joined_handler(void);
static void lorawan_join_failed_handler(void);
static void lorawan_rx_handler(lmh_app_data_t *app_data);
static void lorawan_confirm_class_handler(DeviceClass_t Class);
static void send_lora_frame(void);
/**brief Structure containing LoRaWan callback functions, needed for lmh_init()
*/
static lmh_callback_t g_lora_callbacks = {BoardGetBatteryLevel, BoardGetUniqueId, BoardGetRandomSeed,
lorawan_rx_handler, lorawan_has_joined_handler, lorawan_confirm_class_handler, lorawan_join_failed_handler
};
//OTAA keys !!!! KEYS ARE MSB !!!!
uint8_t nodeDeviceEUI[8] = {0x60, 0x81, 0xF9, 0xE1, 0xA5, 0xE8, 0xC8, 0x1B};
uint8_t nodeAppEUI[8] = {0x60, 0x81, 0xF9, 0x5E, 0x95, 0x44, 0x90, 0x82};
uint8_t nodeAppKey[16] = {0x12, 0xAC, 0x1F, 0xA5, 0x42, 0xF1, 0x85, 0x3A, 0x99, 0xB7, 0xEB, 0xD5, 0xEE, 0xB4, 0x7A, 0xC8};
// ABP keys
uint32_t nodeDevAddr = 0x260116F8;
uint8_t nodeNwsKey[16] = {0x7E, 0xAC, 0xE2, 0x55, 0xB8, 0xA5, 0xE2, 0x69, 0x91, 0x51, 0x96, 0x06, 0x47, 0x56, 0x9D, 0x23};
uint8_t nodeAppsKey[16] = {0xFB, 0xAC, 0xB6, 0x47, 0xF3, 0x58, 0x45, 0xC7, 0x50, 0x7D, 0xBF, 0x16, 0x8B, 0xA8, 0xC1, 0x7C};
// Private defination
#define LORAWAN_APP_DATA_BUFF_SIZE 64 /**< buffer size of the data to be transmitted. */
#define LORAWAN_APP_INTERVAL 20000 /**< Defines for user timer, the application data transmission interval. 20s, value in [ms]. */
static uint8_t m_lora_app_data_buffer[LORAWAN_APP_DATA_BUFF_SIZE]; //< Lora user application data buffer.
static lmh_app_data_t m_lora_app_data = {m_lora_app_data_buffer, 0, 0, 0, 0}; //< Lora user application data structure.
TimerEvent_t appTimer;
static uint32_t timers_init(void);
static uint32_t count = 0;
static uint32_t count_fail = 0;
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
// Initialize Serial for debug output
time_t timeout = millis();
Serial.begin(115200);
while (!Serial)
{
if ((millis() - timeout) < 5000)
{
delay(100);
}
else
{
break;
}
}
// Initialize LoRa chip.
lora_rak4630_init();
Serial.println("=====================================");
Serial.println("Welcome to RAK4630 LoRaWan!!!");
if (doOTAA)
{
Serial.println("Type: OTAA");
}
else
{
Serial.println("Type: ABP");
}
switch (g_CurrentRegion)
{
case LORAMAC_REGION_AS923:
Serial.println("Region: AS923");
break;
case LORAMAC_REGION_AU915:
Serial.println("Region: AU915");
break;
case LORAMAC_REGION_CN470:
Serial.println("Region: CN470");
break;
case LORAMAC_REGION_CN779:
Serial.println("Region: CN779");
break;
case LORAMAC_REGION_EU433:
Serial.println("Region: EU433");
break;
case LORAMAC_REGION_IN865:
Serial.println("Region: IN865");
break;
case LORAMAC_REGION_EU868:
Serial.println("Region: EU868");
break;
case LORAMAC_REGION_KR920:
Serial.println("Region: KR920");
break;
case LORAMAC_REGION_US915:
Serial.println("Region: US915");
break;
case LORAMAC_REGION_RU864:
Serial.println("Region: RU864");
break;
case LORAMAC_REGION_AS923_2:
Serial.println("Region: AS923-2");
break;
case LORAMAC_REGION_AS923_3:
Serial.println("Region: AS923-3");
break;
case LORAMAC_REGION_AS923_4:
Serial.println("Region: AS923-4");
break;
}
Serial.println("=====================================");
//creat a user timer to send data to server period
uint32_t err_code;
err_code = timers_init();
if (err_code != 0)
{
Serial.printf("timers_init failed - %d\n", err_code);
return;
}
// Setup the EUIs and Keys
if (doOTAA)
{
lmh_setDevEui(nodeDeviceEUI);
lmh_setAppEui(nodeAppEUI);
lmh_setAppKey(nodeAppKey);
}
else
{
lmh_setNwkSKey(nodeNwsKey);
lmh_setAppSKey(nodeAppsKey);
lmh_setDevAddr(nodeDevAddr);
}
// Initialize LoRaWan
err_code = lmh_init(&g_lora_callbacks, g_lora_param_init, doOTAA, g_CurrentClass, g_CurrentRegion);
if (err_code != 0)
{
Serial.printf("lmh_init failed - %d\n", err_code);
return;
}
delay(1000);
/* Helium Network LoraWan sub channel 2 is recommended, default channels 0-7*/
if (!lmh_setSubBandChannels(2))
{
Serial.println("lmh_setSubBandChannels() failed");
}
delay(1000);
// Start Join procedure
Serial.println("Starting Join");
lmh_join();
Serial.println("Return from join");
}
void loop()
{
// Put your application tasks here, like reading of sensors,
// Controlling actuators and/or other functions.
}
/**brief LoRa function for handling HasJoined event.
*/
void lorawan_has_joined_handler(void)
{
if(doOTAA == true)
{
Serial.println("OTAA Mode, Network Joined!");
}
else
{
Serial.println("ABP Mode");
}
lmh_error_status ret = lmh_class_request(g_CurrentClass);
if (ret == LMH_SUCCESS)
{
delay(1000);
TimerSetValue(&appTimer, LORAWAN_APP_INTERVAL);
TimerStart(&appTimer);
}
}
/**brief LoRa function for handling OTAA join failed
*/
static void lorawan_join_failed_handler(void)
{
Serial.println("OTAA join failed!");
Serial.println("Check your EUI's and Keys's!");
Serial.println("Check if a Gateway is in range!");
}
/**brief Function for handling LoRaWan received data from Gateway
*
* param[in] app_data Pointer to rx data
*/
void lorawan_rx_handler(lmh_app_data_t *app_data)
{
Serial.printf("LoRa Packet received on port %d, size:%d, rssi:%d, snr:%d, data:%s\n",
app_data->port, app_data->buffsize, app_data->rssi, app_data->snr, app_data->buffer);
}
void lorawan_confirm_class_handler(DeviceClass_t Class)
{
Serial.printf("switch to class %c done\n", "ABC"[Class]);
// Informs the server that switch has occurred ASAP
m_lora_app_data.buffsize = 0;
m_lora_app_data.port = gAppPort;
lmh_send(&m_lora_app_data, g_CurrentConfirm);
}
void send_lora_frame(void)
{
if (lmh_join_status_get() != LMH_SET)
{
//Not joined, try again later
return;
}
uint32_t i = 0;
memset(m_lora_app_data.buffer, 0, LORAWAN_APP_DATA_BUFF_SIZE);
m_lora_app_data.port = gAppPort;
m_lora_app_data.buffer[i++] = 'H';
m_lora_app_data.buffer[i++] = 'e';
m_lora_app_data.buffer[i++] = 'l';
m_lora_app_data.buffer[i++] = 'l';
m_lora_app_data.buffer[i++] = 'o';
m_lora_app_data.buffer[i++] = '!';
m_lora_app_data.buffsize = i;
lmh_error_status error = lmh_send(&m_lora_app_data, g_CurrentConfirm);
if (error == LMH_SUCCESS)
{
count++;
Serial.printf("lmh_send ok count %d\n", count);
}
else
{
count_fail++;
Serial.printf("lmh_send fail count %d\n", count_fail);
}
}
/**brief Function for handling user timerout event.
*/
void tx_lora_periodic_handler(void)
{
TimerSetValue(&appTimer, LORAWAN_APP_INTERVAL);
TimerStart(&appTimer);
Serial.println("Sending frame now...");
send_lora_frame();
}
/**brief Function for the Timer initialization.
*
* details Initializes the timer module. This creates and starts application timers.
*/
uint32_t timers_init(void)
{
TimerInit(&appTimer, tx_lora_periodic_handler);
return 0;
}
Platformio configuration:
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
[platformio]
default_envs = wiscore_rak4631_v2
[env]
build_flags =
-D DEBUG=1
-D LIB_DEBUG=1
[env:wiscore_rak4631_v2]
platform = nordicnrf52
board = wiscore_rak4631
framework = arduino
lib_deps = beegee-tokyo/SX126x-Arduino@^2.0.11
Am I forgetting to configure something? I have already tried to enable duty cycle wondering if 3000ms is a RX window too short (as I saw in other topics it may cause a delay on RxTimeout of 65s but independently of LORAWAN_DUTYCYCLE_ON or LORAWAN_DUTYCYCLE_OFF the timeout is the same on region AU915. Thanks in advance for any help.