Solution: The Murata LoRa module on the MKR WAN 1310 defaults to the following settings when using US915 band settings:
-
Randomly selects all 64 channels in the US915 band. This is bad. Most Gateways only receive on a sub band of 8 channels.
Instead of using US915, switch it to US915_HYBRID. This forces the Murata module to use the lower 8 channels only which is sub band 1. Ensure Gateway is set to sub band 1. Most 8 channel LoRa gateways allow you to select any one of the available 8 channel sub bands.
-
Automatic Data Rate is set to ON. This is also bad for most Gateways. In this mode, the Spreading factor and Bandwidth are seemingly randomly set which results in 2 symptoms: 1 - It takes multiple join requests to actually join the network; 2 - A high percentage of messages are missed after joining.
For our Multitech Conduit Gateway with MTAC-LORA-H-915 Lora card installed, it requires the end node to turn off ADR (AT command AT+ADR=0) and to set the data rate to 4/5 (AT+DR=3). This setting also forces the bandwidth of each uplink channel to 125kHz and sets the spreading factor to 10 (SF10) which is what the MTAC LoRa card requires.
The code below is a modified version of MKRWAN library example FirstConfiguration.ino to illustrate the changes.
/*
First Configuration
This sketch demonstrates the usage of MKR WAN 1300/1310 LoRa module.
This example code is in the public domain.
*/
#include <MKRWAN.h>
LoRaModem modem;
// Uncomment if using the Murata chip as a module
// LoRaModem modem(Serial1);
String appEui;
String appKey;
String devAddr;
String nwkSKey;
String appSKey;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
while (!Serial);
Serial.println("Welcome to MKRWAN1300/1310 first configuration sketch");
Serial.println("Register to your favourite LoRa network and we are ready to go!");
// change this to your regional band (eg. US915, AS923, ...)
if (!modem.begin(US915_HYBRID)) {
Serial.println("Failed to start module");
while (1) {}
};
modem.setADR(0); //Turn off automatic Data Rate mode
modem.dataRate(3); //set data rate to be 4/5, Spreading Factor 10 10 and channel bandwidth to 125kHz
Serial.print("Your module version is: ");
Serial.println(modem.version());
Serial.print("Your device EUI is: ");
Serial.println(modem.deviceEUI());
int mode = 0;
while (mode != 1 && mode != 2) {
Serial.println("Are you connecting via OTAA (1) or ABP (2)?");
while (!Serial.available());
mode = Serial.readStringUntil('\n').toInt();
}
int connected;
if (mode == 1) {
Serial.println("Enter your APP EUI");
while (!Serial.available());
appEui = Serial.readStringUntil('\n');
Serial.println("Enter your APP KEY");
while (!Serial.available());
appKey = Serial.readStringUntil('\n');
appKey.trim();
appEui.trim();
connected = modem.joinOTAA(appEui, appKey);
} else if (mode == 2) {
Serial.println("Enter your Device Address");
while (!Serial.available());
devAddr = Serial.readStringUntil('\n');
Serial.println("Enter your NWS KEY");
while (!Serial.available());
nwkSKey = Serial.readStringUntil('\n');
Serial.println("Enter your APP SKEY");
while (!Serial.available());
appSKey = Serial.readStringUntil('\n');
devAddr.trim();
nwkSKey.trim();
appSKey.trim();
connected = modem.joinABP(devAddr, nwkSKey, appSKey);
}
if (!connected) {
Serial.println("Something went wrong; are you indoor? Move near a window and retry");
while (1) {}
}
delay(5000);
int err;
modem.setPort(3);
modem.beginPacket();
modem.print("HeLoRA world!");
err = modem.endPacket(true);
if (err > 0) {
Serial.println("Message sent correctly!");
} else {
Serial.println("Error sending message :(");
}
}
void loop() {
while (modem.available()) {
Serial.write(modem.read());
}
modem.poll();
}
Note, for some reason in the MKRWAN library the endPacket(bool confirmed) function is forced to false, no matter what you want it to be. So if you want to confirm a message packet was received by the Gateway (only do this once in a while, not for every message!) Make the following change to MKRWAN.h library.
//int endPacket(bool confirmed = false) { //1/14/21 - TLZ - this is original library, do not know why they forced to false?
int endPacket(bool confirmed) { //Allows you to ask for a confirmation of message receipt by Gateway when true
uint8_t buffer[LORA_RX_BUFFER];
memset(buffer, 0, LORA_RX_BUFFER);
int size = tx.get(buffer, tx.size());
return modemSend(buffer, size, confirmed);
}
Good Practices to follow for LoRa Networks:
- If you have a lot of sensors and if there is a possibility that all of them will be reset or turned on at the same time, you should put a random time delay of from 0 to several minutes at the beginning of your code before the join request.
- For every X number of messages, the end node should ask for a message received confirmation from the Gateway as would be done in the function modem.endPacket(true) [As modified above]; by checking this periodically, you know the sensor is still connected to the LoRa Network. The value of X depend on the time you have set for message transmission frequency and how critical the data is to you. Some may choose to do this for every message, but beware, some Gateways will block incoming data while it is sending an acknowledgement.
An option to the above is to simply periodically perform another join request.
Murata Module Notes: Murata uses the Semtech SX1276. This is controlled by an ST Micro STM32L01. ST wrote the software for this device, it is based on their LoRa software expansion for STM32Cube. The supported AT command set is defined in ST Micros App Note AN4967. If you obtain the code from ST Micro the relevant files are shown in their App AT-Slave, at.h. (I cannot post due to licensing) Note that the version of the ST firmware that you can update using MKRWAN example MKRWANFWUpdate_standalone will load v 1.2.0 onto the ST micro chip in the Murata module. The latest version as of this post is 1.3.1, As of yet I do not know if anyone has created an update to that yet for Arduino. The MKRWAN_v2 library will allow you to upgrade to 1.3.0 but note that we had too many issues with MKRWAN_v2 and reverted back to the original MKRWAN library.