RN2903 "invalid_data_len" on AU915 over 24 Bytes/11 Characters

I am using the @jpmeijers RN2483 Arduino Library with an Atmel MEGA328P RN2903 board and am doing some testing to see what the largest payload that I can transmit is.

After some testing I came to realise that I am unable to send to more than 24 bytes, or 11 characters in myLoRa.tx(). If I try to transmit anymore, the board keeps printing that it is transmitting, much quicker it normally does (About half a second versus 3 seconds). No transmission is present in either the TTN console for the device or the gateway. This is due to the RN2903 stating that there is an invalid_data_len.

This means that the initialisation message in the setup() does not work, which has led me to removing it from any code that I have been using. It also means that the amount of data and be transmitted is much lower than what is possible and permitted with LoRaWAN. For example, if I wanted to send a GPS coordinate, I would not have enough space.

This output from the module is documented in the RN2903 LoRa Technology Module Command Reference User’s Guide. There are two mentions of it in here, one for:

Response after entering the command

and another for:

Response after the uplink transmission

The description is the same, however my error is related to the entering of the command as I believe no transmission is occurring:

invalid_data_len if application payload length is greater than the maximum application payload length corresponding to the current data rate

In the library I am using, I have specified that I am using AU915, which is initialised the same as US915 as both frequencies use band 2 (channels 8 to 15).

I have also tried turning the ADR on in line 290 as I am using ABP, however that did not change what has been happening.

My code is as follows:

#include <rn2xx3.h>
#include <AltSoftSerial.h>

AltSoftSerial mySerial;

// create an instance of the rn2xx3 library,
// giving the software serial as port to use
rn2xx3 myLora(mySerial);

// the setup routine runs once when you press reset:
void setup()
{

  // open serial communications and wait for port to open:
  Serial.begin(57600); //serial port to computer
  mySerial.begin(9600); //serial port to radio
  
  Serial.println("It's start'n up mate!");

  initialize_radio();

  myLora.sendRawCommand(F("sys set pindig GPIO0 1"));
  led_on();

  // setting the frequency plan to AU915
  myLora.setFrequencyPlan(TTN_US);

  led_off();
  delay(2000);
}

void initialize_radio()
{
  //reset rn2483
  pinMode(12, OUTPUT);
  digitalWrite(12, LOW);
  delay(500);
  digitalWrite(12, HIGH);

  delay(100); //wait for the RN2xx3's startup message
  mySerial.flush();

  // autobaud the rn2483 module to 9600. The default would otherwise be 57600.
  myLora.autobaud();

  // check communication with radio
  String hweui = myLora.hweui();
  while(hweui.length() != 16)
  {
    Serial.println("Communication with RN2xx3 unsuccessful. Start that baby right up again.");
    Serial.println(hweui);
    delay(10000);
    hweui = myLora.hweui();
  }

  // Setting the frequency plan to AU915
  myLora.setFrequencyPlan(TTN_US);

  // print out the HWEUI so that we can register it via ttnctl
  Serial.println("When using OTAA, register this DevEUI: ");
  Serial.println(myLora.hweui());
  Serial.println("RN2xx3 firmware version:");
  Serial.println(myLora.sysver());

  // configure your keys and join the network
  Serial.println("Trying to join TTN");
  bool join_result = false;

  /*
   * ABP: initABP(String addr, String AppSKey, String NwkSKey);
   * Paste the example code from the TTN console here:
   */
  const char *devAddr = "KEY";
  const char *nwkSKey = "KEY";
  const char *appSKey = "KEY";

   join_result = myLora.initABP(devAddr, appSKey, nwkSKey);

  /*
   * OTAA: initOTAA(String AppEUI, String AppKey);
   * If you are using OTAA, paste the example code from the TTN console here:
   */
  //const char *appEui = "KEY";
  //const char *appKey = "KEY";
  //
  //join_result = myLora.initOTAA(appEui, appKey);

  while(!join_result)
  {
    Serial.println("Unable to join. Are your keys correct and are you in the middle of the outback?");
    delay(30000); //delay a minute before retry
    join_result = myLora.init();
  }
  Serial.println("Successfully joined TTN. You beauty!");

  // Setting the frequency plan to TTN_AU. Not needed for OTAA.
  myLora.setFrequencyPlan(TTN_US);
}

// the loop routine runs over and over again forever:
void loop()
{
    led_on();
    Serial.println("TXing");
    myLora.tx("Testing");
    led_off();
    delay(200);
}

void led_on()
{
  myLora.sendRawCommand(F("sys set pindig GPIO10 1"));
}

void led_off()
{
  myLora.sendRawCommand(F("sys set pindig GPIO10 0"));
}

I’d first set the frequency plan before sending anything.

Beware you also still have a reference to US, despite the comment stating otherwise:

  // Setting the frequency plan to AU915
  myLora.setFrequencyPlan(TTN_US);

Even though most use cases should not use text, I’d not expect a library to support 16 bits characters or some UTF-encodig, if that’s what causes that difference. How many bytes of application payload do you see in TTN Console when sending, say, 2 bytes? Maybe the library is adding its own payload?

ADR is unrelated to whether you’re using OTAA or ABP.

Actually, that might only need 6 bytes; see Best practices when sending GPS location data [HowTo].

Hi @arjanvanb,

Apologies for the confusion about the frequency plan. The setup for TTN_AU and TTN_US is identical, so it’s simply an inconsistency on my part. Both achieve the same thing.

In the TTN Console, the output shows 24 bytes, 13 of which are the header and the remaining 11 are the message I am sending.

Regarding the GPS, that was simply an example of usage, I had thought that the size of the payload was much larger, but thanks to the link, now I know this is not the case.

I have also tested this on OTAA and it has the same problem. I’ll have a look into it to see what’s happening.

I’ve been doing some testing with OTAA and come to face the same issue. In addition, this error seems to relate to the data rate and come to think of it, you were talking about this over in this post. Does anything you said over there have to do with what’s happening here?

When it says invalid_data_len, no transmission happens which means I can’t see the data rate we are talking about in the TTN console. I’ll see if I can find a way in the library to show what data rate we are on and then that might help.

I did find this post which states they can’t send more than 10 bytes, whereas I’m unable to send more than 11 bytes (24 with header). Their setup is very similar:

I have an RN2903 module (915Mhz) communicating with a network server.
Data rate : SF7BW125
Coding rate: 4/5

I am unsure about my data and coding rates, however considering I am about 10 metres from my gateway, I would think they would be similar. The only issue with this person’s post however is that there has not been a response, so it’s a dead end.

I have also found this post which talks about the limits of the RN2483 which he states is 191 bytes, however no answer is given here either.

This still doesn’t make any sense to me:

Or is this just the full LoRaWAN packet of 24 bytes, being 13 bytes for the LoRaWAN header and MIC, and 11 bytes of application payload? (Which for your tests is text.) (I understood that it made a difference if you sent “bytes” or text…)

Also, what version is the module? The release notes claim for the October 2017 release:

1.0.3 Fixed issues with LinkAdr, RxParamSetup, RX1 Receive Window, Channel Management, ESUART buffer sizes.

Maybe that buffer size was the problem, but just a wild guess.

The maximum payload size I can send with success is 11 bytes, which I called 11 character. In my testing this payload has been:
01234567890

To do this, I use the line:
myLora.tx("01234567890");

I know this is different to the transmission I have shown in the initial post (“Testing” vs “01234567890”), but this is maximum payload I can send.

When I look in the TTN console, I see the payload is 24 bytes in size at a maximum. This means that there is a 13 byte header which is attached to my payload as shown below:

30%20pm
30%20pm

The firmware I am using on my RN2903 is SA1.0.3, available from here. The reason for the SA version is because I need AU915 support.

Just an aside as I ran into it:

Apparently not:

The specification of the Australian 915-928 MHz band is practically the same as the US 902-928 MHz, except that its uplink frequencies are on higher frequencies than in the US band.

Are you sending confirmed messages too, and does it indeed work fine for unconfirmed messages?

As for the error message: if no other RN2903 user responds here, I guess you’ll need to contact Microchip. Using some passthrough sketch you should be able to issue the commands directly, to get a minimal, complete, verifiable example.

1 Like

Ah, I think it’s indeed a matter of old firmware in the RN2903, but not due to a bug but due to adhering to the specifications. The very first LoRaWAN™ Regional Parameters v1.0 indeed defines 11 bytes for DR0 (SF12 BW125):

But the later LoRaWAN™ Regional Parameters v1.0.2rB reads:

The release notes of version 1.0.5 available from https://www.microchip.com/wwwproducts/en/RN2903 (dating beack to November 2018, but only released a few days ago?) states:

Release for LoRaWAN specification 1.0.2
RN2903 1.0.5 Nov 06 2018 10:45:27

Just to add a bit more detail

The US915 Band is 902-928 with the 64 uplink channels starting at 902 MHz through to 915 MHz, the downlink channels start at 915 through to 928. In the Au915 the uplink and downlink channels overlap and are in the same band.

Therefore the downlink channels are the same in the US915 and Au915, however the frequency of the uplink channels are different.

Hey @TonySmith and @arjanvanb,

I should have clarified what I meant when I said:

Within the @jpmeijers RN2483 Arduino Library, I have customised it to have a frequency called TTN_AU. This is currently not in in the the library (which I hope changes soon), and simply is just TTN_US.

The code for this specification is:

    case TTN_US:
      // Same setup as the Australian frequency plan
    case TTN_AU:
    {
    /*
     * Most of the TTN_AU frequency plan was copied from:
     * https://github.com/TheThingsNetwork/arduino-device-lib
     */
      if(_moduleType == RN2903)
      {
        for(int channel=0; channel<72; channel++)
        {
          // Build command string. First init, then add int.
          String command = F("mac set ch status ");
          command += channel;

          if(channel>=8 && channel<16)
          {
            sendRawCommand(command+F(" on"));
          }
          else
          {
            sendRawCommand(command+F(" off"));
          }
        }
        returnValue = true;
      }
      else
      {
        returnValue = false;
      }
      break;
    }

As you said Tony:

You are correct. When I was discussing this in Slack with @hraftery , I questioned the different frequencies between US915 and AU915 and yet TTN_US being used. Here explained it like this:

The firmware on the RN2903 controls the frequency plan, which is why the AU or SA version is needed. The function myLora.setFrequencyPlan() only enables the appropriate channels. As both AU915 and US915 both use band 2 (channels 8 to 15), both frequency plans are supported.

Thank you both for the clarification. I do understand how you misunderstood what I meant because I did not elaborate.

Thank you for the explanation. I do have a few questions about this, because I believe there are a few things which I can seem to figure out:

  • I understand that the maximum sized payload from that chart is 242 bytes and is a limit specified by the LoRa Alliance. I found another article online which states the maximum is 243 bytes, so I guess it’s close enough. Why is the payload maximum size limited to this? I would have though it was something like 255 bytes, but I guess this leaves space for the the 13 byte header?
  • I see that the maximum payload sizes have changed between v1.0 and v1.0.2rB. Why is this the case?
  • Is the reason for the difference between SF12 having 11 or now 51 bytes versus SF7 having 242 bytes due to airtime? As the SF increase, so does the airtime, which means less data can be sent in the same amount of time. Going by this , does it mean that a payload in v1.0.2rB at SF12 with 51 bytes take as long to transmit as a message at SF7 at 222 bytes? From my experience, I didn’t think SF12 was four times as slow as SF7, I thought it was greater. In addition, my justification doesn’t seem to stand considering the significant change from 11 to 51 bytes between the newer parameters
  • Why can’t I transmit the maximum payload size at any SF? I thought duty cycle and fair use policy (which the RN2903 doesn’t consider) was based on a 24 hour period, not on individual transmissions.

The biggest problem I have is this however is that even if I update the firmware, I am still restricted to 51 bytes. This is still not the largest payload I should be able to send. With my current testing, which is about 10 metres from the gateway, I am never operating at SF12 and most often at SF7, as shown by the screenshot above. Why am I limited to maximum payloads of SF12 if I’m not transmitting at that rate and why does the RN2903 assume I am if I am not connected at SF12?

I do understand that TTN does not advise the use of large payloads, but it is still acceptable.