LoRaWAN¶
Libraries¶
Install the required libraries from the Arduino library manager. Sketch -> Include library -> Manage libraries… Install “Sodaq_RN2483” and “Sodaq_wdt”
More information about installing libraries can be found on the getting started page.
LoRa Serial Passthrough¶
For many network you will need the hardware eui to register your device on their network. Replace [x] with your own keys.
Command | Action |
---|---|
sys reset | Will reset the module and shows the version on the module |
sys get ver | Firmware version of the RN2XX3 module |
sys get hweui | Get the hardware eui |
mac set devaddr [x] | Set the device address |
mac set nwkskey [x] | Set the network session key |
mac set appskey [x] | Set the application session key |
mac join abp | Join the network with personalized keys |
mac tx uncnf 1 01 | Send the hexadecimal message “01” unconfirmed on port 1 |
Full command set:
RN2483 command reference
RN2903 command reference
/*
* Compatible with:
* SODAQ MBILI
* SODAQ Autonomo
* SODAQ ONE
* SODAQ ONE BETA
* SODAQ EXPLORER
*/
#include "Arduino.h"
#if defined(ARDUINO_AVR_SODAQ_MBILI)
#define debugSerial Serial
#define loraSerial Serial1
#elif defined(ARDUINO_SODAQ_AUTONOMO) || defined(ARDUINO_SODAQ_ONE) || defined(ARDUINO_SODAQ_ONE_BETA)
#define debugSerial SerialUSB
#define loraSerial Serial1
#elif defined(ARDUINO_SODAQ_EXPLORER)
#define debugSerial SerialUSB
#define loraSerial Serial2
#else
// please select a sodaq board
#endif
void setup() {
// Enable LoRa module
#if defined(ARDUINO_SODAQ_AUTONOMO)
pinMode(BEE_VCC, OUTPUT);
digitalWrite(BEE_VCC, HIGH); //set input power BEE high
#elif defined(ARDUINO_AVR_SODAQ_MBILI)
pinMode(20, OUTPUT);
digitalWrite(20, HIGH); //set input power BEE high
#endif
// Hard reset the RN module
#if defined(LORA_RESET)
pinMode(LORA_RESET, OUTPUT);
digitalWrite(LORA_RESET, LOW);
delay(100);
digitalWrite(LORA_RESET, HIGH);
delay(100);
#endif
while ((!debugSerial) && (millis() < 10000)){
// wait 10 seconds for serial monitor
}
debugSerial.begin(57600);
loraSerial.begin(57600);
debugSerial.println("Please send command");
}
void loop() {
//send and receive data with serial
if (debugSerial.available()){
//debugSerial.print("SEND: ");
while (debugSerial.available()) {
uint8_t inChar = debugSerial.read();
//debugSerial.write(inChar);
loraSerial.write(inChar);
}
}
if (loraSerial.available()){
//debugSerial.print("RECEIVE: ");
while (loraSerial.available()) {
uint8_t inChar = loraSerial.read();
debugSerial.write(inChar);
}
}
}
HWEUI¶
Get HWEUI from RN module
/**
* Works with:
* SODAQ Mbili
* SODAQ Autonomo
* SODAQ One
* SODAQ Explorer
*
*/
#define CONSOLE_STREAM SERIAL_PORT_MONITOR
#if defined(ARDUINO_SODAQ_EXPLORER)
#define LORA_STREAM Serial2
#else
#define LORA_STREAM Serial1
#endif
#define LORA_BAUD 57600
#define DEBUG_BAUD 57600
void setup() {
// put your setup code here, to run once:
// Enable LoRa module
#if defined(ARDUINO_SODAQ_AUTONOMO)
pinMode(BEE_VCC, OUTPUT);
digitalWrite(BEE_VCC, HIGH); //set input power BEE high
#endif
//wait forever for the Serial Monitor to open
while(!CONSOLE_STREAM);
//Setup streams
CONSOLE_STREAM.begin(DEBUG_BAUD);
LORA_STREAM.begin(LORA_BAUD);
#ifdef LORA_RESET
//Hardreset the RN module
pinMode(LORA_RESET, OUTPUT);
digitalWrite(LORA_RESET, HIGH);
delay(100);
digitalWrite(LORA_RESET, LOW);
delay(100);
digitalWrite(LORA_RESET, HIGH);
delay(1000);
// empty the buffer
LORA_STREAM.end();
#endif
LORA_STREAM.begin(57600);
// get the Hardware DevEUI
CONSOLE_STREAM.println("Get the hardware serial, sending \"sys get hweui\\r\\n\", expecting \"xxxxxxxxxxxxxxxx\", received: \"");
delay(100);
LORA_STREAM.println("sys get hweui");
delay(100);
char buff[17];
memset(buff, 0, sizeof(buff));
LORA_STREAM.readBytesUntil(0x0D, buff, sizeof(buff));
CONSOLE_STREAM.print(buff);
CONSOLE_STREAM.println();
}
void loop() {
// put your main code here, to run repeatedly:
}
LoRaWAN simple send example¶
#include <Sodaq_RN2483.h>
#define debugSerial SerialUSB
#define loraSerial Serial2
// USE YOUR OWN KEYS!
const uint8_t devAddr[4] =
{
0x00, 0x00, 0x00, 0x00
};
// USE YOUR OWN KEYS!
const uint8_t appSKey[16] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// USE YOUR OWN KEYS!
const uint8_t nwkSKey[16] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// Some complete random hex
uint8_t testPayload[] =
{
0x53, 0x4F, 0x44, 0x41, 0x51
};
void setup()
{
while ((!debugSerial) && (millis() < 10000));
debugSerial.begin(57600);
loraSerial.begin(LoRaBee.getDefaultBaudRate());
LoRaBee.setDiag(debugSerial); // optional
if (LoRaBee.initABP(loraSerial, devAddr, appSKey, nwkSKey, false))
{
debugSerial.println("Connection to the network was successful.");
}
else
{
debugSerial.println("Connection to the network failed!");
}
// Uncomment this line to for the RN2903 with the Actility Network
// For OTAA update the DEFAULT_FSB in the library
// LoRaBee.setFsbChannels(1);
}
void loop()
{
debugSerial.println("Sleeping for 5 seconds before starting sending out test packets.");
for (uint8_t i = 5; i > 0; i--)
{
debugSerial.println(i);
delay(1000);
}
// send 10 packets, with at least a 5 seconds delay after each transmission (more seconds if the device is busy)
uint8_t i = 10;
while (i > 0)
{
switch (LoRaBee.send(1, testPayload, 5))
{
case NoError:
debugSerial.println("Successful transmission.");
i--;
break;
case NoResponse:
debugSerial.println("There was no response from the device.");
break;
case Timeout:
debugSerial.println("Connection timed-out. Check your serial connection to the device! Sleeping for 20sec.");
delay(20000);
break;
case PayloadSizeError:
debugSerial.println("The size of the payload is greater than allowed. Transmission failed!");
break;
case InternalError:
debugSerial.println("Oh No! This shouldn't happen. Something is really wrong! Try restarting the device!\r\nThe program will now halt.");
while (1) {};
break;
case Busy:
debugSerial.println("The device is busy. Sleeping for 10 extra seconds.");
delay(10000);
break;
case NetworkFatalError:
debugSerial.println("There is a non-recoverable error with the network connection. You should re-connect.\r\nThe program will now halt.");
while (1) {};
break;
case NotConnected:
debugSerial.println("The device is not connected to the network. Please connect to the network before attempting to send data.\r\nThe program will now halt.");
while (1) {};
break;
case NoAcknowledgment:
debugSerial.println("There was no acknowledgment sent back!");
break;
default:
break;
}
delay(60000);
}
}
Send Temperature with LoRaWAN¶
#include <Sodaq_RN2483.h>
#define debugSerial SerialUSB
#define loraSerial Serial2
#define NIBBLE_TO_HEX_CHAR(i) ((i <= 9) ? ('0' + i) : ('A' - 10 + i))
#define HIGH_NIBBLE(i) ((i >> 4) & 0x0F)
#define LOW_NIBBLE(i) (i & 0x0F)
//Use OTAA, set to false to use ABP
bool OTAA = true;
// ABP
// USE YOUR OWN KEYS!
const uint8_t devAddr[4] =
{
0x00, 0x00, 0x00, 0x00
};
// USE YOUR OWN KEYS!
const uint8_t appSKey[16] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// USE YOUR OWN KEYS!
const uint8_t nwkSKey[16] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// OTAA
// With using the GetHWEUI() function the HWEUI will be used
static uint8_t DevEUI[8]
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
const uint8_t AppEUI[8] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
const uint8_t AppKey[16] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
void setup()
{
delay(1000);
while ((!debugSerial) && (millis() < 10000)){
// Wait 10 seconds for debugSerial to open
}
debugSerial.println("Start");
// Start streams
debugSerial.begin(57600);
loraSerial.begin(LoRaBee.getDefaultBaudRate());
LoRaBee.setDiag(debugSerial); // to use debug remove //DEBUG inside library
LoRaBee.init(loraSerial, LORA_RESET);
//Use the Hardware EUI
getHWEUI();
// Print the Hardware EUI
debugSerial.print("LoRa HWEUI: ");
for (uint8_t i = 0; i < sizeof(DevEUI); i++) {
debugSerial.print((char)NIBBLE_TO_HEX_CHAR(HIGH_NIBBLE(DevEUI[i])));
debugSerial.print((char)NIBBLE_TO_HEX_CHAR(LOW_NIBBLE(DevEUI[i])));
}
debugSerial.println();
setupLoRa();
}
void setupLoRa(){
if(!OTAA){
// ABP
setupLoRaABP();
} else {
//OTAA
setupLoRaOTAA();
}
// Uncomment this line to for the RN2903 with the Actility Network
// For OTAA update the DEFAULT_FSB in the library
// LoRaBee.setFsbChannels(1);
LoRaBee.setSpreadingFactor(9);
}
void setupLoRaABP(){
if (LoRaBee.initABP(loraSerial, devAddr, appSKey, nwkSKey, true))
{
debugSerial.println("Communication to LoRaBEE successful.");
}
else
{
debugSerial.println("Communication to LoRaBEE failed!");
}
}
void setupLoRaOTAA(){
if (LoRaBee.initOTA(loraSerial, DevEUI, AppEUI, AppKey, true))
{
debugSerial.println("Network connection successful.");
}
else
{
debugSerial.println("Network connection failed!");
}
}
void loop()
{
String reading = getTemperature();
debugSerial.println(reading);
switch (LoRaBee.send(1, (uint8_t*)reading.c_str(), reading.length()))
{
case NoError:
debugSerial.println("Successful transmission.");
break;
case NoResponse:
debugSerial.println("There was no response from the device.");
break;
case Timeout:
debugSerial.println("Connection timed-out. Check your serial connection to the device! Sleeping for 20sec.");
delay(20000);
break;
case PayloadSizeError:
debugSerial.println("The size of the payload is greater than allowed. Transmission failed!");
break;
case InternalError:
debugSerial.println("Oh No! This shouldn't happen. Something is really wrong! The program will reset the RN module.");
setupLoRa();
break;
case Busy:
debugSerial.println("The device is busy. Sleeping for 10 extra seconds.");
delay(10000);
break;
case NetworkFatalError:
debugSerial.println("There is a non-recoverable error with the network connection. The program will reset the RN module.");
setupLoRa();
break;
case NotConnected:
debugSerial.println("The device is not connected to the network. The program will reset the RN module.");
setupLoRa();
break;
case NoAcknowledgment:
debugSerial.println("There was no acknowledgment sent back!");
break;
default:
break;
}
// Delay between readings
// 60 000 = 1 minute
delay(10000);
}
String getTemperature()
{
//10mV per C, 0C is 500mV
float mVolts = (float)analogRead(TEMP_SENSOR) * 3300.0 / 1023.0;
float temp = (mVolts - 500.0) / 10.0;
return String(temp);
}
/**
* Gets and stores the LoRa module's HWEUI/
*/
static void getHWEUI()
{
uint8_t len = LoRaBee.getHWEUI(DevEUI, sizeof(DevEUI));
}
Reset the RN module in software¶
It is possible to give the RN module a hardware reset in software.
#define CONSOLE_STREAM SerialUSB
#define LORA_STREAM Serial2
#define LORA_BAUD 57600
#define DEBUG_BAUD 57600
void setup() {
// put your setup code here, to run once:
//Setup streams
CONSOLE_STREAM.begin(DEBUG_BAUD);
LORA_STREAM.begin(LORA_BAUD);
}
void loop() {
// put your main code here, to run repeatedly:
LORA_STREAM.end();
LORA_STREAM.begin(57600);
// RESET LORA_MODULE
pinMode(LORA_RESET, OUTPUT);
digitalWrite(LORA_RESET, LOW);
delay(100);
digitalWrite(LORA_RESET, HIGH);
delay(1000);
CONSOLE_STREAM.println("Testing LoRa module, sending \"sys get ver\\r\\n\", expecting \"RN2xxx\", received: \"");
delay(100);
LORA_STREAM.println("sys reset");
delay(100);
LORA_STREAM.println("sys get ver");
delay(100);
char buff[7];
memset(buff, 0, sizeof(buff));
LORA_STREAM.readBytesUntil(0x20, buff, sizeof(buff));
CONSOLE_STREAM.print(buff);
CONSOLE_STREAM.print("\"...");
CONSOLE_STREAM.println();
delay(800);
}