RAK4630 LoRa halts on LoRa TX when more than 12 bytes in packet

I am using the RAK4630 with Bluetooth Low Energy and LoRa in conjunction with a RAK1910 GPS module. I am trying to pack the m_lora_app_data.buffer with my data (should be only 32 bytes) like so:

    // point to first byte of float "lat"
    puc = (unsigned char *)(&lat);
    // sequentially access all 4 bytes of "lat" and pack into buffer
    m_lora_app_data.buffer[appDataSize++] = puc[0];
    m_lora_app_data.buffer[appDataSize++] = puc[1];
    m_lora_app_data.buffer[appDataSize++] = puc[2];
    m_lora_app_data.buffer[appDataSize++] = puc[3];

    // do the same with the rest of the variables
    puc = (unsigned char *)(&lon);
    m_lora_app_data.buffer[appDataSize++] = puc[0];
    m_lora_app_data.buffer[appDataSize++] = puc[1];
    m_lora_app_data.buffer[appDataSize++] = puc[2];
    m_lora_app_data.buffer[appDataSize++] = puc[3];
.
.
.
// continues for 32 total bytes

For some reason, I cannot pack more than 12 bytes into each packet, or else the program halts at the “LoRa sending” phase. I am basing my LoRa off of the program LoRaWAN_OTAA_ABP.ino, and requires a hardware reset. These are my LoRa config options:

#define SCHED_MAX_EVENT_DATA_SIZE APP_TIMER_SCHED_EVENT_DATA_SIZE /**< Maximum size of scheduler events. Trying to print either name here throws an error, saying neither is defined. Leaving it as this is fine, leading me to believe it is never used in the program.*/
#define SCHED_QUEUE_SIZE 60                                       /**< Maximum number of events in the scheduler queue. Changing this doesn't do anything.*/
#define LORAWAN_DATERATE DR_3                                     /*LoRa datarate -- in the US915 standard, DR_3 gives us a max payload of 242 bytes*/
#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. */
#define LORAWAN_APP_PORT 2                              /*added this to define a port*/
DeviceClass_t g_CurrentClass = CLASS_A;                           /* class definition*/
LoRaMacRegion_t g_CurrentRegion = LORAMAC_REGION_US915;           /* Region*/
lmh_confirm g_CurrentConfirm = LMH_UNCONFIRMED_MSG;               /* confirm/unconfirm packet definition*/
uint8_t gAppPort = LORAWAN_APP_PORT;                              /* data port, defined as port 2. Leaving it default has no effect.*/
.
.
.
// Private defination
#define LORAWAN_APP_DATA_BUFF_SIZE 64    /**< buffer size of the data to be transmitted. I've tried incrementally higher values for this with no effect (up to 2048).*/
#define LORAWAN_APP_INTERVAL 10000       /**< 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.

Why is this behavior happening? What config option am I missing that would stop the program from halting unexpectedly when trying to transmit more than 12 bytes?

Is it a memory leak? sometimes, the app will also halt after some number of packet transmissions. How is my method faulty? Is it due to my usage of the buffer? I’ve used this method to stuff a float byte-wise into a packet before with no issues, but since I am using the m_lora_app_data.buffer maybe its different.

Hi Charles,

Your method to transform a float into a byte array is unusual (to me).
What we usually do is

  • Multiply the float e.g. by 100000
  • Convert it into a long integer
  • Copy it into the byte array
  • On the receiver side, divide the value by 100000 to get back the float value.

Here is an example from our GPS tracker code

Thanks for the reply – I still experience issues even when simply extending the example code LoRaWAN_OTAA.ino (chars only) by writing like this:

m_lora_app_data.buffer[i++] = 'a';
m_lora_app_data.buffer[i++] = 'b';
m_lora_app_data.buffer[i++] = 'c';
m_lora_app_data.buffer[i++] = 'd';
... 
//works for up to 6 bytes (same as "Hello!") but program stops if you add any more

I also tried your byte-packing method, which will definitely be easier to decode than mine! However, it still froze after trying to send more than 12 bytes, even on higher datarates. I am fairly sure we can eliminate the variable regarding my byte-packing method, since your suggestion (which I will now use, thanks) exhibits the same behavior.

One thing I JUST now noticed – it sends just fine without the Serial Monitor open. With the Serial Monitor open, it halts the program. Here’s how I was serial logging those values, in case that is the problem:

        for(int i=0; i<m_lora_app_data.buffsize; i++) {
            Serial.printf("%02x ", m_lora_app_data.buffer[i]);
        }


Heres a screenshot of my real-time packets – I am able to see the 16 bytes come through, but the second I open the serial monitor, it runs until it gets to the packet sending stage, and halts!

The serial monitor should not have any influence on the program flow.

Can you show me the log output of the RAK4631.
And can you share your complete code, you can send it as direct message to me here in the forum.

I was able to solve the issue by simply removing my serial print of the LoRa packet. I am fairly certain it is the for loop, as removing it solves the issue. DR_1 now works for my packet.

That said, I will still send you my code.

Thanks!

Oh, I have to change that example code :cry:

It calls send_lora_frame() from the timer interrupt routine. Deadly mistake. Sorry for that bad example.

Within the timer interrupt routine there should be no lengthy code or Serial output.
Remove the send_lora_frame call from the timer interrupt and instead set a flag.
Handle the flag within the loop() and you can use the Serial output.

...
bool send_now = false;
...
void loop()
{
   if (send_now)
   {
      Serial.println("Sending frame now...");
      send_now = false;
      send_lora_frame();
   }
}
...
void tx_lora_periodic_handler(void)
{
    TimerSetValue(&appTimer, LORAWAN_APP_INTERVAL);
    TimerStart(&appTimer);
    send_now = true;
}
...
2 Likes

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