MKR1300 LoRa not reliable

I was wondering if anyone would be familiar with the problem I am experiencing. It seems as if though the modules aren't working the way they should by giving me continuous communication on demand. I have a master-node which communicates with a bunch of other slave-nodes. The slave-nodes are responsible for sending the data back to the master-node when their "name" is referenced.

The code is as follows for the Master Node:

#include <SPI.h>
#include <LoRa.h>

int counter = 0;
byte MasterNode = 0xFF;     
byte Node1 = 0xAA;
byte Node2 = 0xBB; 
byte Node3 = 0XCC;
byte Node4 = 0xDD;
byte Node5 = 0xEE;
byte Node6 = 0x01;
byte Node7 = 0x02;
 
String SenderNode;
String outgoing;              // outgoing message
 
byte msgCount = 0;            // count of outgoing messages
 
// Tracks the time since last event fired
unsigned long previousMillis = 0;
unsigned long int previoussecs = 0; 
unsigned long int currentsecs = 0; 
unsigned long currentMillis = 0;
int interval = 1 ; // updated every 1 second
int Secs = 0; 


void setup() {
  Serial.begin(9600);
  while (!Serial);

  Serial.println("LoRa Sender");

  if (!LoRa.begin(868E6)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }else{Serial.print("Starting LoRa successful");}
}

void loop() {
currentMillis = millis();
   currentsecs = currentMillis / 1000; 
    if ((unsigned long)(currentsecs - previoussecs) >= interval) {
     Secs = Secs + 1;
     //Serial.println(Secs);
     if ( Secs >= 31 )
    {
      Secs = 0; 
    }
            if (Secs == 1)
    {
     
    String message = "35"; 
    sendMessage(message,MasterNode, Node1);
    Serial.println("1st message sent!");
    }
 
            if (Secs == 5)
    {
     
    String message = "40"; 
    sendMessage(message,MasterNode, Node2);
    Serial.println("2nd message sent!");
    }
            if (Secs == 10)
    {
     
    String message = "45"; 
    sendMessage(message,MasterNode, Node3);
    Serial.println("3rd message sent!");
    }
            if (Secs == 15)
    {
     
    String message = "50"; 
    sendMessage(message,MasterNode, Node4);
    Serial.println("4th message sent!");
    }
            if (Secs == 20)
    {
     
    String message = "55"; 
    sendMessage(message,MasterNode, Node5);
    Serial.println("5th message sent!");
    }
            if (Secs == 25)
    {
     
    String message = "60"; 
    sendMessage(message,MasterNode, Node6);
    Serial.println("6th message sent!");
    }
            if (Secs == 30)
    {
     
    String message = "65"; 
    sendMessage(message,MasterNode, Node7);
    Serial.println("7th message sent!");
    }
    
   previoussecs = currentsecs;
    }
 
  // parse for a packet, and call onReceive with the result:
  onReceive(LoRa.parsePacket());
    
  }
 
 
void sendMessage(String outgoing, byte MasterNode, byte otherNode) {
  LoRa.beginPacket();                   // start packet
  LoRa.write(otherNode);              // add destination address
  LoRa.write(MasterNode);             // add sender address
  LoRa.write(msgCount);                 // add message ID
  LoRa.write(outgoing.length());        // add payload length
  LoRa.print(outgoing);                 // add payload
  LoRa.endPacket();                     // finish packet and send it  
  Serial.println("Packed and sent");                         
}
 
void onReceive(int packetSize) {
  if (packetSize == 0) return;          // if there's no packet, return
 
  // read packet header bytes:
  int recipient = LoRa.read();          // recipient address
  byte sender = LoRa.read();            // sender address
  if( sender == 0XAA )
  SenderNode = "Node1:";
  if( sender == 0XBB )
  SenderNode = "Node2:";
  if( sender == 0XCC )
  SenderNode = "Node3:";
  if( sender == 0XDD )
  SenderNode = "Node4:";
  if( sender == 0XEE )
  SenderNode = "Node5:";
  if( sender == 0X01 )
  SenderNode = "Node6:";
  if( sender == 0X02 )
  SenderNode = "Node7:";
  byte incomingMsgId = LoRa.read();     // incoming msg ID
  byte incomingLength = LoRa.read();    // incoming msg length
 
  String incoming = "";
 
  while (LoRa.available()) {
    incoming += (char)LoRa.read();
  }
 
  if (incomingLength != incoming.length()) {   // check length for error
    Serial.println("error: message length does not match length");
    
    return;                             // skip rest of function
  }
 
  // if the recipient isn't this device or broadcast,
  if (recipient != Node1 && recipient != MasterNode) {
    Serial.println("This message is not for me.");
    
    return;                             // skip rest of function
  }
  
}

The code for the slave node is as follows:

#include <SPI.h>              // include libraries
#include <LoRa.h>

String outgoing;              // outgoing message
byte msgCount = 0;            // count of outgoing messages
byte MasterNode = 0xFF;     
byte Node1 = 0xAA;
String node1Data;
 
 
void setup() {
  Serial.begin(9600);
  while (!Serial);

  Serial.println("LoRa Receiver");

  if (!LoRa.begin(868E6)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }else{
    Serial.print("Starting LoRa successful");
    }
}
 
void loop() {
 
 
  // parse for a packet, and call onReceive with the result:
  onReceive(LoRa.parsePacket());
}
 
void sendMessage(String outgoing, byte MasterNode, byte otherNode) {
  LoRa.beginPacket();                   // start packet
  LoRa.write(MasterNode);              // add destination address, masternode serves as byte qualification
  LoRa.write(Node1);             // add sender address, where this data comes from in the byte register
  LoRa.write(msgCount);                 // add message ID
  LoRa.write(outgoing.length());        // add payload length
  LoRa.print(outgoing);                 // add payload
  LoRa.endPacket();                     // finish packet and send it
                            
}
 
void onReceive(int packetSize) {
  if (packetSize == 0) return;          // if there's no packet, return
 
  // read packet header bytes:
  int recipient = LoRa.read();          // recipient address
  byte sender = LoRa.read();            // sender address
  byte incomingMsgId = LoRa.read();     // incoming msg ID
  byte incomingLength = LoRa.read();    // incoming msg length
  String incoming = "";
  while (LoRa.available()) {
    incoming += (char)LoRa.read();
  }
 
  if (incomingLength != incoming.length()) {   // check length for error
    Serial.println("error: data missing");
    return;                             // skip rest of function
  }
 
  // if the recipient isn't this device or broadcast,
  if (recipient != Node1 && recipient != MasterNode) {
    Serial.println("This message is not for me.");
    return;                             // skip rest of function
  }
    Serial.println(incoming);//reacting to the received message which serves as a trigger/switch case
    int Val = incoming.toInt();
    if(Val == 35)//specific value to react to, remember to change the information to include the data received via i2c
    { 
    String message = node1Data; 
    sendMessage(message,MasterNode,Node1);
    delay(100);
    return;
    }
  
}

The error I generate from the code is that the data goes missing as it doesn't coincide with "incomingLength". I have possibly a 20% rate of messages which are able to be successfully received by the slave node. The remainder of the "rejected" messages cause the length error.

My hardware setup is 2xMKR13000 with Dipole Antennas attached to both of them. The distance between the devices is probably around 4 metres line of sight.

Did you do a simpler version of the code just sending a packet of a fixed length and content, between the TX and one RX, to check the logic of the comms ?

And have you checked the bytes of the actual reply packet sent by the nodes and the bytes of the actual packet received by the master ?

Yes I did a simpler version of the code before moving over to something more complex. But the version didn't allow me to communicate with various nodes in the field from one central Master-node. I have thought about just doing a timer-based approach with the inverse logic as that above. It may help sort out the issue if I just turn the timekeeping responsibilities over to the slave nodes. Just thinking...

The simpler version has proved to be a lot more trustworthy though. I will have to have a look at the specific bytes being sent, I can't imagine something else being sent aside from what is specifically programmed to be sent. It may be that the length comparison is actually curtailing the process flow.. But that is where I am unsure

Just to give you an idea of what the serial monitor is telling me with some brief testing I provide the following:

LoRa init succeeded.
This message is not for me.
This message is not for me.
Received from: 0xff
Sent to: 0xaa
Message ID: 0
Message length: 2
Message: 35
RSSI: -18
Snr: 9.00

Received from: 0xff
Sent to: 0xaa
Message ID: 0
Message length: 2
Message: ;4
RSSI: -15
Snr: 8.75

Received from: 0xff
Sent to: 0xaa
Message ID: 0
Message length: 2
Message: 35
RSSI: -19
Snr: 8.75

This message is not for me.
error: message length does not match length
error: message length does not match length
This message is not for me.

You really need to see the HEX bytes of the packet the slave node is sending and the HEX bytes of the packet the Master is receiving.

I understand but the problem is that I do not receive the information from the master node to begin with. I cannot dissect the info without it arriving. When it does arrive I have no issues and the information can be processed accordingly.

It is as if the nodes miss each other somehow...

 LoRa.setTxPower(100);
 LoRa.setSpreadingFactor(9);
 LoRa.setSignalBandwidth(125E3);
 LoRa.setSyncWord(0xA7);
 LoRa.setCodingRate4(6);

These are the settings applicable to both nodes. I have cycled through a wide variety of combinations and yet the packages are either corrupted or they go missing.

Bad mistake, arbitary syncwords do not work well, some dont work at all.

Stick to the two standard ones, 0x12 and 0x34

If your using this LoRa library;

https://github.com/sandeepmistry/arduino-LoRa/blob/master/API.md

A TX power of 100 is not listed as a valid value.

Alright so I have changed all of the settings back to their more acceptable spec:

 LoRa.setTxPower(15);
 LoRa.setSpreadingFactor(9);
 LoRa.setSignalBandwidth(125E3);
 LoRa.setSyncWord(0x12);
 LoRa.setCodingRate4(8);

I have an output on the serial monitor of the slave node as follows:

Starting LoRa successfulerror: data missing
;5
This message is not for me.
error: data missing
error: data missing
This message is not for me.
error: data missing
error: data missing
error: data missing
3
error: data missing
error: data missing
error: data missing
35
error: data missing
35

The "35" was actually the correct value. But after the last "35", all reception has ceased.

I am really starting to suspect faulty/damaged hardware as the MKR1300 boards behave the same with the basic sketches supplied with the LoRa library examples.

The devices are powered by USB cable from my computer...not sure if that may be contributing to some of the issues I am experiencing.

Cannot comment on that, I dont have a MKR1300.

I doubt the 'problem' is with the LoRa modules themselves, however. In general the LoRa modules either work or they do not.

One point to note is that the library you are using may not implement packet CRC checking as default, so its possible you are receiving corrupt packets without realising. Some corruption of RF data is to be expected and is not a fault in the modules.

If the basic library examples dont work, then you would expect your own programmes not to work either.

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