LoRa long-range communication system, similier similar to WIFI but working over very long distances (up to 10km). Unlike regular wifi, LoRa is designed to send only very small amounts of data, and pretty slowly.
LoRaWAN defines the communication protocol and system architecture for network based on LoRa.
...
Hardware
The Arduino MKR WAN 1310 is a board that combines the functionality of the MKR Zero and LoRa / LoRaWANTM connectivity.
Seting up the MKR WAN 1300
https://docs.arduino.cc/tutorials/mkr-wan-1310/the-things-network
Visualising Data on The Things Network
Data is stored on The Things Network for up to 7 days. The data can be exported, and it’s possible to integrate with many IOT platforms for handling live data streams.
https://www.thethingsnetwork.org/docs/applications/storage/api/
Terms:
OTAA: OTAA end devices are assigned a new DevAddr
at establishing each new session. This allows them to move to different networks/clusters.
ABP: ABPend devices use a fixed DevAdd
AppEUI and JoinEUI are the same thingsThere are also modules that allow LoRa communication for almost any device, and several other Arduino based devices with inbuilt LoRa functionality.
For the experiments below we will also need:
Compatible Antena
Jumper wires
Breadboard
A sensor
Getting started with the MKR WAN 1310
For this experiment, we need two LoRa devices. We also need to have a compatible antenna connected to both devices.
We will also need to install the Arduino Lora Library.
We also have to be aware of the radio frequency plan allowed in our region. It’s 868E6 for Europe, and you can find the full list of frequency bands here.
Sender Code
The sender code sends a simple message, with a delay of 5 seconds. Make sure you change the contents of myData.
Code Block | ||
---|---|---|
| ||
#include <SPI.h>
#include <LoRa.h>
int counter = 0;
String myData = "my name";
void setup() {
Serial.begin(9600);// wait until serial has started
Serial.println("LoRa Sender");
if (!LoRa.begin(868E6)) {
Serial.println("Starting LoRa failed!");
while (1);
}
delay(1000);
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
Serial.print("Sending packet: ");
Serial.println(counter);
// send packet
LoRa.beginPacket();
LoRa.print(myData);
LoRa.endPacket();
counter++;
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(4000);
} |
Receiver Code
Code Block | ||
---|---|---|
| ||
#include <SPI.h>
#include <LoRa.h>
String contents = "";
void setup() {
Serial.begin(9600);
while (!Serial); // wait until serial has started
Serial.println("LoRa Receiver");
if (!LoRa.begin(868E6)) {
Serial.println("Starting LoRa failed!");
while (1);
}
}
void loop() {
// try to parse packet
int packetSize = LoRa.parsePacket();
if (packetSize) {
// received a packet
Serial.print("Received packet '");
// read packet
while (LoRa.available()) {
contents += (char)LoRa.read();
}
Serial.println(contents);
// print RSSI of packet
Serial.print("' with RSSI ");
Serial.println(LoRa.packetRssi());
contents = "";
}
} |
Advanced example MKR WAN 1310
In the previous example, you might have noticed a potential problem. The receiving device is getting LoRa messages from anyone sending data on that frequency. Furthermore, anyone can listen in to the data being sent. This could be resolved by encrypting the message.
We are going to solve the problem by simply sending an ID with our packet, then checking it at the receiving end and discarding any other messages.
We are using the Serial port extensively here to see the workings of our code, which is very slow for the Arduino. It would be wise to remove most of this communication before using an example from the real world.
Sender Code with an Analog Sensor.
Code Block | ||
---|---|---|
| ||
#include <SPI.h>
#include <LoRa.h>
int counter = 0;
String myUniqueId = "asdfw1";
void setup() {
Serial.begin(9600);
while (!Serial);
Serial.println("LoRa Sender");
if (!LoRa.begin(868E6)) {
Serial.println("Starting LoRa failed!");
while(1);
}
delay(1000);
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
int sensorValue = analogRead(A0);
Serial.print("Sending packet: ");
Serial.println(counter);
// send packet
LoRa.beginPacket();
LoRa.print(sensorValue);
LoRa.print(",");
LoRa.print(myUniqueId);
LoRa.endPacket();
counter++;
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(4000);
} |
Receiver Code
Code Block | ||
---|---|---|
| ||
#include <SPI.h>
#include <LoRa.h>
String contents = "";
String myUniqueId = "asdfw1";
void setup() {
Serial.begin(9600);
while (!Serial);
Serial.println("LoRa Receiver");
if (!LoRa.begin(868E6)) {
Serial.println("Starting LoRa failed!");
while (1);
}
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
// try to parse packet
int packetSize = LoRa.parsePacket();
if (packetSize) {
// received a packet
Serial.print("Received packet '");
// read packet
while (LoRa.available()) {
contents += (char)LoRa.read();
}
Serial.println(contents);
// print RSSI of packet (Received Signal Strength Indicator)
Serial.print("' with RSSI ");
Serial.println(LoRa.packetRssi());
int commaIndex = contents.indexOf(',');
String data = contents.substring(0, commaIndex);
String ID = contents.substring(commaIndex + 1);
if (data && ID) {
Serial.println("Recieved Matching format");
if (ID.equals(myUniqueId)) {
Serial.println("ID matches!");
digitalWrite(LED_BUILTIN, HIGH);
Serial.print("data: ");
Serial.println(data);
} else {
Serial.print(myUniqueId);
Serial.print(" does not match ");
Serial.println(ID);
digitalWrite(LED_BUILTIN, LOW);
}
}
contents = "";
}
} |
If you want to send more than one piece of data at a time, you will need to parse multiple comma-separated values. This code snippet below shows how this can be done using the substring() and indexOf() methods of the String object.
Code Block | ||
---|---|---|
| ||
// This can get confusing as you send more data. It can be helpful to write out your expected string and note where the indexes are.
// data1,data2,uniqueId
// ↑ ↑
// IndexA IndexB
int IndexA = contents.indexOf(','); //finds location of first item
String data1 = contents.substring(0, IndexA);
int IndexB = contents.indexOf(',', IndexA + 1 ); //finds location of 2nd item
String data2 = contents.substring(IndexA + 1, IndexB);
String ID = contents.substring(IndexB + 1);
if (ID.equals(myUniqueId)) {
Serial.println("ID matches!");
digitalWrite(LED_BUILTIN, HIGH);
Serial.print("data1: ");
Serial.println(data1);
Serial.print("data2: ");
Serial.println(data2);
Serial.println();
} |