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.
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[16];
memset(buff, 0, sizeof(buff));
LORA_STREAM.readBytesUntil(0x20, 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);
}