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?
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.
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;
}
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”.
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.
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.
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.
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 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);
}
}
}