Lmh_send fail rak4631

what could cause the messages to fail

I start the application i get 2 good messages then after that all i get is lmh_send fail messages over and over my loop

any ideas?

@buton
Region?
Payload size?
ADR enabled or disabled?
What code? One of our example codes or your own code?

@beegee

I did a Mix of copy paste, Region US915, DR0, ADR ON

Here is some sample 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> //http://librarymanager/All#SX126x
#include <SPI.h>
#include <TinyGPS.h>        //http://librarymanager/All#TinyGPS
#include <Wire.h>
#include <U8g2lib.h>		   // Click to install library: http://librarymanager/All#u8g2


//--- Oled Display
//U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0);
U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0);

//GPS stuff
TinyGPS gps;
unsigned long fix_age;
String tmp_data = "";
int direction_S_N = 0;  //0--S, 1--N
int direction_E_W = 0;  //0--E, 1--W
bool start_gps = false;
bool lora_joined=false;

int  Led1_Blink=0;
int Led2_Blink=0;
int timing1=0;
int timing2=0;



// 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_US915;    /* Region:EU868*/
lmh_confirm g_CurrentConfirm = LMH_UNCONFIRMED_MSG; 				  /* confirm/unconfirm packet definition*/
uint8_t gAppPort = LORAWAN_APP_PORT;							        /* data port*/

//---Lora Config STUFF

/**@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_OFF};

// 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);


//void direction_parse(String tmp)
/**@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 !!!!
//OTAA keys !!!! KEYS ARE MSB !!!!
uint8_t nodeDeviceEUI[8] =x
uint8_t nodeAppEUI[8] = x
uint8_t nodeAppKey[16] =x

// ABP keys
uint32_t nodeDevAddr = x
uint8_t nodeNwsKey[16] = x
uint8_t nodeAppsKey[16] = x

// 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.


static uint32_t count = 0;
static uint32_t count_fail = 0;

char data[32] = {0};

void direction_parse(String tmp)
{
    if (tmp.indexOf(",E,") != -1)
    {
        direction_E_W = 0;
    }
    else
    {
        direction_E_W = 1;
    }
    
    if (tmp.indexOf(",S,") != -1)
    {
        direction_S_N = 0;
    }
    else
    {
        direction_S_N = 1;
    }
}


void setup() {

    //put your setup code here, to run once:
    pinMode(LED_BUILTIN, OUTPUT);
    pinMode(LED_BUILTIN2, OUTPUT);
    digitalWrite(LED_BUILTIN, HIGH);

    //-- Init Display
    u8g2.begin();
  
    // Initialize Serial for debug output
    time_t timeout = millis();
    Serial.begin(115200);
    while (!Serial)
    {
      if ((millis() - timeout) < 5000)
      {
        delay(100);
      }
      else
      {
        break;
      }
    }

    u8g2.clearBuffer();					// clear the internal memory
    u8g2.setFont(u8g2_font_6x13_tf); // choose a suitable font
    delay(300);
    //--Display Init
    memset(data, 0, sizeof(data));
    sprintf(data, "Init");
    u8g2.drawStr(0, 15, data);


    // 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;
 

    // 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;
    }

  // Start Join procedure
  lmh_join();

  //gps init

  pinMode(WB_IO2, OUTPUT);
  digitalWrite(WB_IO2, 0);
  delay(1000);
  digitalWrite(WB_IO2, 1);
  delay(1000);
  
  Serial1.begin(9600);
  while (!Serial1);
    Serial.println("gps uart init ok!");
  timing1=millis();
  timing2=millis();

}

void loop() {
  
    //--Upadte Display
    u8g2.sendBuffer(); // transfer internal memory to the display

    //-- LED Blinking changes
    if( (millis()-timing1)>Led1_Blink)
      {
        
        digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
        timing1=millis();
      }

       if( (millis()-timing2)>Led2_Blink)
      {
        
        digitalWrite(LED_BUILTIN2, !digitalRead(LED_BUILTIN2));
        timing2=millis();
      }

    //-- Start GPS flag for troubleshooting
    start_gps=true;//-- leaving it true for now

  //-- Enter GPS once  we joined a lora network
  if(start_gps&&lora_joined)
  {
    Serial.println("entering GPs...");

    bool newData = false;

    // For one second we parse GPS data and report some key values
    memset(data, 0, sizeof(data));
    sprintf(data, "*");
    u8g2.drawStr(30, 30, data);
    u8g2.sendBuffer(); // transfer internal memory to the display


    for (unsigned long start = millis(); millis() - start < 1000;)
    { 
      while (Serial1.available())
      {
        Led2_Blink=200;
        char c = Serial1.read();
        //Serial.write(c); // uncomment this line if you want to see the GPS data flowing
        tmp_data += c;
        if (gps.encode(c))// Did a new valid sentence come in?
          {
          newData = true;
          }
          else
          {
          
          }
      }
    }
    //--- Erase *
    u8g2.setColorIndex(0);
    u8g2.drawBox(30, 15, 60,30);
    u8g2.setColorIndex(1);

    //-- Set to  - to make it kind of blink
    memset(data, 0, sizeof(data));
    sprintf(data, "-");
    u8g2.drawStr(30, 30, data);
    u8g2.sendBuffer(); // transfer internal memory to the display
    delay(500);



    direction_parse(tmp_data);
    tmp_data = "";
    float flat, flon;
    int32_t ilat, ilon;
    //-- If new data is valid we decode
    if (newData)
    {
      Serial.println("Got GPS Fix");

      //-- Indicator on display that we go t a fix
      memset(data, 0, sizeof(data));
      sprintf(data, "F-Y");
      u8g2.drawStr(0, 30, data);
      u8g2.sendBuffer(); // transfer internal memory to the display

      unsigned long age;  
      gps.f_get_position(&flat, &flon, &age);
      flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat;
      ilat = flat * 100000;
      flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon;
      ilon = flon * 100000;
      
      //-- Display GPS Data on Display
      memset(data, 0, sizeof(data));
      sprintf(data,"%0.2f %0.2f",flat,flon);
      u8g2.drawStr(50,30, data);
      u8g2.sendBuffer(); // transfer internal memory to the display

      //-- Set lora buffer
      memset(m_lora_app_data.buffer, 0, LORAWAN_APP_DATA_BUFF_SIZE);

      m_lora_app_data.port = gAppPort;
      m_lora_app_data.buffer[0] = 0x09;
      //lat data
      m_lora_app_data.buffer[1] = (ilat & 0xFF000000) >> 24;
      m_lora_app_data.buffer[2] = (ilat & 0x00FF0000) >> 16;
      m_lora_app_data.buffer[3] = (ilat & 0x0000FF00) >> 8;
      m_lora_app_data.buffer[4] =  ilat & 0x000000FF;
      if(direction_S_N == 0)
      {
        m_lora_app_data.buffer[5] = 'S';    
      }
      else
      {
        m_lora_app_data.buffer[5] = 'N';    
      }
      //lon data
      m_lora_app_data.buffer[6] = (ilon & 0xFF000000) >> 24;
      m_lora_app_data.buffer[7] = (ilon & 0x00FF0000) >> 16;
      m_lora_app_data.buffer[8] = (ilon & 0x0000FF00) >> 8;
      m_lora_app_data.buffer[9] =  ilon & 0x000000FF;
      if(direction_E_W == 0)
      {
        m_lora_app_data.buffer[10] = 'E';
      }
      else
      {
        m_lora_app_data.buffer[10] = 'W';
      }
      m_lora_app_data.buffsize = 11;

      send_lora_frame();
      digitalWrite(LED_BUILTIN2,HIGH);
      delay(20000);
    }
    
  
  


  }



}


/**@brief LoRa function for handling HasJoined event.
 */
void lorawan_has_joined_handler(void)
{
  Serial.println("OTAA Mode, Network Joined!");

  //--Delete Init Message
  u8g2.setColorIndex(0);
  u8g2.drawBox(1, 1, 40,15);
  u8g2.setColorIndex(1);

  //-- Show Network Joined on display
  memset(data, 0, sizeof(data));
  sprintf(data, "N-%s","J");
  u8g2.drawStr(0, 15, data);
  Led1_Blink=1000;
  lmh_error_status ret = lmh_class_request(g_CurrentClass);


  if (ret == LMH_SUCCESS)
  {
    delay(1000);

    lora_joined=true;
  }
}
/**@brief LoRa function for handling OTAA join failed
*/
static void lorawan_join_failed_handler(void)
{ 

  //-- Failed To Join display message
  memset(data, 0, sizeof(data));
  sprintf(data, "N-%s","X");
  u8g2.drawStr(0, 15, data);
  Led1_Blink=300;
  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)
{
  
  Serial.write("entering send lora frame");
  if (lmh_join_status_get() != LMH_SET)
  {
    //Not joined, try again later
    return;
  }

  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);

  //-- Display Count
  memset(data, 0, sizeof(data));
  sprintf(data, "M: Tx %d",count);
  u8g2.drawStr(30, 15, data);
  u8g2.sendBuffer(); // transfer internal memory to the display
 
  }
  else
  {
    
    count_fail++;
    Serial.printf("lmh_send fail count %d\n", count_fail);
    //--Display fail count
    memset(data, 0, sizeof(data));
    sprintf(data, "Ftx- %d",count_fail);
    u8g2.drawStr(80, 15, data);
    u8g2.sendBuffer(); // transfer internal memory to the display
  }

}



Hi @buton

Can you try to switch ADR off by setting LORAWAN_ADR_OFF in g_lora_param_init?

static lmh_param_t g_lora_param_init = {LORAWAN_ADR_OFF, LORAWAN_DATERATE, LORAWAN_PUBLIC_NETWORK, JOINREQ_NBTRIALS, LORAWAN_TX_POWER, LORAWAN_DUTYCYCLE_OFF};

And datarate of DR0 on US915 is the smallest allowed package size (11 bytes). It should fit with your data package, but maybe you better try with DR1.

#define LORAWAN_DATERATE DR_1								  /*LoRaMac datarates definition, from DR_0 to DR_5*/

You can find package sizes per region per datarate in our Documentation Center

Do you have access to the gateway? If yes, can you get the log file from the gateway showing the data transmission?

1 Like

It did work, no more failed packages.

Thanks @beegee

1 Like

@buton , it is most likely caused by the DR set to 0. Especially, if you are too close to the gateway :+1:

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.