How to send more than 7 bytes from Wisblock RAK4631?

I am testing with the example LoRaWAN_OTAA_ABP sketch version 0.1 and US915 frequency band.

I have discovered that if I attempt to send more than 7 bytes, the lmh_send() function throws an error.

NOTE that if I send exactly 8 bytes, the first send is successful, but subsequent attempts to send fail.
If I send more than 8 bytes, the first and all subsequent sends fail immediately.

Is this 7-byte limit a product of the LoRaWAN maximum payload size of 11 bytes for US915 at D0?

If this is the case, why isn’t this mentioned somewhere within the sketch? Instead, the m_lora_app_data.buffer variable is declared to be 64 bytes in size with no mention that it must be only 7 bytes or fail will occur.

Also, is this a fixed limitation? I.e. will the limit always be 7 bytes, or will this change based on some unknown property, header, or length of another value that is being sent?

Hi @thegpx ,

Yes, it is based on Duty Cycle and Dwell Time restrictions LoRaWAN.
I am not sure why you are getting failures in 8 bytes size but I think that is a different issue.
At DR0, you should be able to send successfuly up to 11 bytes.

@thegpx
Can you change the example code to

lmh_error_status error = lmh_send(&m_lora_app_data, g_CurrentConfirm);
switch (error)
{
case LMH_SUCCESS:
	Serial.println("Packet enqueued");
	count++;
	break;
case LMH_BUSY:
	Serial.println("LoRa transceiver is busy");
	count_fail++;
	break;
case LMH_ERROR:
	Serial.println("Packet error, too big to send with current DR");
	count_fail++;
	break;
}

This gives more information why the send failed.

Thank you @beegee and @carlrowan for your replies.

I have modified the code per your request and here are the results:

7 bytes: send OK (repeated sending is successful)
8 bytes to 11 bytes: first send OK, subsequent sends fail with error code “-1”
12+ bytes: error code “-1” on every attempt

To confirm, at no time does it report “Busy”. Always Error “-1”.

Thanks and I hope this clarifies the issue.

I have exactly the SAME ISSUE. On the FIRST send, I can send NO MORE than ELEVEN(11) bytes. After that, I can send SEVEN(7) bytes maximum. NOT EIGHT*

Is the maximum size supposed to be 11-bytes all the time? OR, is it sensible that this applies only to the FIRST transmission?

BTW, this problem persists, for ALL data-rates.

My question boils down to this: How can I get back to my 11-byte payload capacity?

That is very weird. Somehow this feels like a buffer is not being emptied properly, or a pointer not being reset to zero somewhere… Hopefully @beegee will have more insight. In my own application I had to limit the data to 7 bytes or less. I send a separate message for each data point (i.e. temperature, pressure, wind speed, etc) I want to transmit, and use byte [0] to indicate which data point is being sent, vs sending multiple data points per message.

Considering that this application issue was three years ago, it’s interesting that the seven-byte limit still persists to this day.

It is even stranger that the FIRST message, after OTAA join, permits an eleven byte payload, and ALL subsequent traffic is limited to seven.

(I eagerly await comment from @beegee )

It seems to depend on the LoRaWAN server.

Little test application for US915:

  • Set DR to DR0
  • Disable ADR
  • Join network
  • send 6 packets with payload size 7
  • from 7th packet on send with payload size 11

LoRaWAN server can send commands to the end device. Answering such a command extends the payload by 4 bytes. This means
7 bytes payload + 4 bytes == 11 bytes ==> ok to send
11 bytes payload + 4 bytes == 15 bytes ==> not ok to send, throws Packet error, too big to send with current DR

I run a test on US915 against a Chirpstack server and against TTN and what I found is

  • the TTN sends a ADR request with every uplink, the device answers it (which extends the payload by 4 bytes). TTN LNS does not stop to do this. Strange is that I disabled ADR in the TTN console, but it still sends that command.
  • Chirpstack sends one command Device Status, the device answers it (which extends the payload by 4 bytes). Then Chirpstack stops sending commands and the payload can be extended to 11 bytes.

Logs from my gateway:

(1) Chirpstack LNS

(2) TTN LNS

The only solution I found was to enable ADR. Then TTN LNS stops after the ADR REQ command to send commands.

(3) Logs from my gateway with ADR enabled on the device and connected to TTN LNS:

@beegee Thanks for these insights.

BTW - I just now validated that after sending 8 messages of payload 7-bytes, I am thereafter free to send 11-bytes per payload.

I am IN SHOCK.

Out of 51-bytes (at bottom layer) of payload, we only get 11 or 7 bytes of payload available. (In other words, 86% of the communication channel is devoted to the metadata overhead, just to transport 7-bytes.)

It remains a mystery that my RAK7268CV2 gateway routinely sees traffic from devices in my area, having payloads of 30-bytes, 27-bytes, 29-bytes, way larger than 7. (with DR-0)

Please comment how I might see greater capacity, or if 11-bytes is my absolute limit.

I have no explanation about a payload larger than 11 bytes with DR0 using US915.
According to the LoRaWAN definitions that is not possible.

As I am the only one using US915 in my area (and only for short time testing), I cannot confirm whether it is possible to send more bytes in DR0.
The legal band in my country is AS923-3 and the restrictions are even worse, as I can’t use DR0 and DR1 unless I disable DwellTime and use LBT. Which I tried, but never succeeded to disable it, neither on TTN nor on Chirpstack.

This ilustration can help you to do the relationship for LoRa send operation:

This is the code to send the payload that I am limiting to 51 bytes, because when I have the worst transmission condition (spreading factor 12), the maximum size it is 51 bytes

I am using CayenneLPP to standarize the payload format and this is the place in the code where I verify if the payload size is less ou equal 51 bytes:

void Empacota()
{
	if (CFG_DEBUG >= D_INFORMA) {
        Serial.println("=======================================================");
        Serial.println("============= Iniciando o empacotamento ===============");
    }

    WisCayenneLPP.reset();

    WisCayenneLPP.addUnixTime(LPP_UNIXTIME, RAK12500.UNIXEpoch);
    WisCayenneLPP.addVoltage(LPP_VOLTAGE, VBat.real_vbat);
    WisCayenneLPP.addAccelerometer(LPP_ACCELEROMETER,RAK1904.EixoX,RAK1904.EixoY,RAK1904.EixoZ);
    WisCayenneLPP.addTemperature(LPP_TEMPERATURE, RAK1906.Temperatura);
    WisCayenneLPP.addRelativeHumidity(LPP_RELATIVE_HUMIDITY, RAK1906.Humidade);
    WisCayenneLPP.addBarometricPressure(LPP_BAROMETRIC_PRESSURE, RAK1906.PressAtm);
    WisCayenneLPP.addGNSS_6(LPP_GPS6, RAK12500.Latitude, RAK12500.Longitude, RAK12500.Altitude);

    size = WisCayenneLPP.getSize();

    if (size > MAX_SIZE) {
        if (CFG_DEBUG >= D_ERRO) {
        Serial.printf("============= Payload de %u\n", size);
        Serial.printf(" não cabe no buffer de %d\n, MAX_SIZE", MAX_SIZE);
        Serial.println(" ==== ERRO - Aumente o tamnho do buffer para que o Payload resultante possa ser transmitido ===");
        }
            
    } else {
        if (CFG_DEBUG >= D_INFORMA) {
            Serial.printf("============= Payload de %u", size);
            Serial.printf(" cabe no buffer de %d\n", MAX_SIZE);
            Serial.println(" ==== SUCESSO - o payload pode ser transmitido via LoRa ===");
        }
        }
   	   
} 
void LoRaEnvia()
{
 	// Set the fPort
	PayloadEstrutura.port = LoRaAplicPorta; // Choose the fPort you want to use
	// Set the size of the payload
	PayloadEstrutura.buffsize = WisCayenneLPP.getSize();
	// Copy the payload into the structure
	memcpy(PayloadBufferTam, WisCayenneLPP.getBuffer(), WisCayenneLPP.getSize());


    lmh_error_status error = lmh_send(&PayloadEstrutura, LoRaEnvioConfirmado);
	if (error == LMH_SUCCESS) {
		g_count++;
		if (CFG_DEBUG >= D_INFORMA) {
			Serial.printf("lmh_send ok contador %d\n", g_count);
			}
		if (CFG_DEBUG >= D_LED) {
			pinMode(LED_GREEN,OUTPUT);
			for (int i = 0; i < 5; i++) // PISCA ALTERNANDO OS LEDs PARA INDICAR QUE O PROGRAMA ESTA INICIANDO
				{
				digitalWrite(LED_GREEN,!digitalRead(LED_GREEN));
				vTaskDelay(pdMS_TO_TICKS(500));
				}
			digitalWrite(LED_GREEN,LOW);
		}
	} else {
			g_count_fail++;
			if (CFG_DEBUG >= D_ERRO) {
				Serial.printf("lmh_send falhou contador %d\n", g_count_fail);
			}
		}
}

Regards,

Claudio