-
Notifications
You must be signed in to change notification settings - Fork 409
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
391 additions
and
0 deletions.
There are no files selected for viewing
145 changes: 145 additions & 0 deletions
145
examples/LoRaWAN/LoRaWAN_End_Device_Persistent/LoRaWAN_End_Device_Persistent.ino
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
/* | ||
RadioLib LoRaWAN End Device Persistent Example | ||
This example assumes you have tried one of the OTAA or ABP | ||
examples and are familiar with the required keys and procedures. | ||
This example restores and saves a session such that you can use | ||
deepsleep or survive power cycles. Before you start, you will | ||
have to register your device at https://www.thethingsnetwork.org/ | ||
and join the network using either OTAA or ABP. | ||
Please refer to one of the other LoRaWAN examples for more | ||
information regarding joining a network. | ||
NOTE: LoRaWAN requires storing some parameters persistently! | ||
RadioLib does this by using EEPROM, by default | ||
starting at address 0 and using 384 bytes. | ||
If you already use EEPROM in your application, | ||
you will have to either avoid this range, or change it | ||
by setting a different start address by changing the value of | ||
RADIOLIB_HAL_PERSISTENT_STORAGE_BASE macro, either | ||
during build or in src/BuildOpt.h. | ||
For default module settings, see the wiki page | ||
https://github.com/jgromes/RadioLib/wiki/Default-configuration | ||
For full API reference, see the GitHub Pages | ||
https://jgromes.github.io/RadioLib/ | ||
*/ | ||
|
||
// include the library | ||
#include <RadioLib.h> | ||
|
||
// SX1278 has the following connections: | ||
// NSS pin: 10 | ||
// DIO0 pin: 2 | ||
// RESET pin: 9 | ||
// DIO1 pin: 3 | ||
SX1278 radio = new Module(10, 2, 9, 3); | ||
|
||
// create the node instance on the EU-868 band | ||
// using the radio module and the encryption key | ||
// make sure you are using the correct band | ||
// based on your geographical location! | ||
LoRaWANNode node(&radio, &EU868); | ||
|
||
void setup() { | ||
Serial.begin(9600); | ||
|
||
// initialize SX1278 with default settings | ||
Serial.print(F("[SX1278] Initializing ... ")); | ||
int state = radio.begin(); | ||
if(state == RADIOLIB_ERR_NONE) { | ||
Serial.println(F("success!")); | ||
} else { | ||
Serial.print(F("failed, code ")); | ||
Serial.println(state); | ||
while(true); | ||
} | ||
|
||
// first we need to initialize the device storage | ||
// this will reset all persistently stored parameters | ||
// NOTE: This should only be done once prior to first joining a network! | ||
// After wiping persistent storage, you will also have to reset | ||
// the end device in TTN and perform the join procedure again! | ||
// Here, a delay is added to make sure that during re-flashing | ||
// the .wipe() is not triggered and the session is lost | ||
//delay(5000); | ||
//node.wipe(); | ||
|
||
// now we can start the activation | ||
// Serial.print(F("[LoRaWAN] Attempting over-the-air activation ... ")); | ||
// uint64_t joinEUI = 0x12AD1011B0C0FFEE; | ||
// uint64_t devEUI = 0x70B3D57ED005E120; | ||
// uint8_t nwkKey[] = { 0x74, 0x6F, 0x70, 0x53, 0x65, 0x63, 0x72, 0x65, | ||
// 0x74, 0x4B, 0x65, 0x79, 0x31, 0x32, 0x33, 0x34 }; | ||
// uint8_t appKey[] = { 0x61, 0x44, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, | ||
// 0x6E, 0x74, 0x4B, 0x65, 0x79, 0x41, 0x42, 0x43 }; | ||
// state = node.beginOTAA(joinEUI, devEUI, nwkKey, appKey); | ||
|
||
// after the device has been activated, | ||
// the session can be restored without rejoining after device power cycle | ||
// on EEPROM-enabled boards by calling "restore" | ||
Serial.print(F("[LoRaWAN] Resuming previous session ... ")); | ||
state = node.restore(); | ||
if(state == RADIOLIB_ERR_NONE) { | ||
Serial.println(F("success!")); | ||
} else { | ||
Serial.print(F("failed, code ")); | ||
Serial.println(state); | ||
while(true); | ||
} | ||
|
||
} | ||
|
||
// counter to keep track of transmitted packets | ||
int count = 0; | ||
|
||
void loop() { | ||
// send uplink to port 10 | ||
Serial.print(F("[LoRaWAN] Sending uplink packet ... ")); | ||
String strUp = "Hello World! #" + String(count++); | ||
String strDown; | ||
int state = node.sendReceive(strUp, 10, strDown); | ||
if(state == RADIOLIB_ERR_NONE) { | ||
Serial.println(F("received a downlink!")); | ||
|
||
// print data of the packet (if there are any) | ||
Serial.print(F("[LoRaWAN] Data:\t\t")); | ||
if(strDown.length() > 0) { | ||
Serial.println(strDown); | ||
} else { | ||
Serial.println(F("<MAC commands only>")); | ||
} | ||
|
||
// print RSSI (Received Signal Strength Indicator) | ||
Serial.print(F("[LoRaWAN] RSSI:\t\t")); | ||
Serial.print(radio.getRSSI()); | ||
Serial.println(F(" dBm")); | ||
|
||
// print SNR (Signal-to-Noise Ratio) | ||
Serial.print(F("[LoRaWAN] SNR:\t\t")); | ||
Serial.print(radio.getSNR()); | ||
Serial.println(F(" dB")); | ||
|
||
// print frequency error | ||
Serial.print(F("[LoRaWAN] Frequency error:\t")); | ||
Serial.print(radio.getFrequencyError()); | ||
Serial.println(F(" Hz")); | ||
|
||
} else if(state == RADIOLIB_ERR_RX_TIMEOUT) { | ||
Serial.println(F("no downlink!")); | ||
|
||
} else { | ||
Serial.print(F("failed, code ")); | ||
Serial.println(state); | ||
} | ||
|
||
// on EEPROM enabled boards, you can save the current session | ||
// by calling "saveSession" which allows retrieving the session after reboot or deepsleep | ||
node.saveSession(); | ||
|
||
// wait before sending another packet | ||
// alternatively, call a deepsleep function here | ||
// make sure to send the radio to sleep as well using radio.sleep() | ||
delay(30000); | ||
} |
246 changes: 246 additions & 0 deletions
246
examples/LoRaWAN/LoRaWAN_End_Device_Reference/LoRaWAN_End_Device_Reference.ino
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,246 @@ | ||
/* | ||
RadioLib LoRaWAN End Device Reference Example | ||
This example joins a LoRaWAN network and will send | ||
uplink packets. Before you start, you will have to | ||
register your device at https://www.thethingsnetwork.org/ | ||
After your device is registered, you can run this example. | ||
The device will join the network and start uploading data. | ||
Also, most of the possible and available functions are | ||
shown here for reference. | ||
LoRaWAN v1.1 requires the use of EEPROM (persistent storage). | ||
Please refer to the 'persistent' example once you are familiar | ||
with LoRaWAN. | ||
Running this examples REQUIRES you to check "Resets DevNonces" | ||
on your LoRaWAN dashboard. Refer to the network's | ||
documentation on how to do this. | ||
For default module settings, see the wiki page | ||
https://github.com/jgromes/RadioLib/wiki/Default-configuration | ||
For full API reference, see the GitHub Pages | ||
https://jgromes.github.io/RadioLib/ | ||
*/ | ||
|
||
// include the library | ||
#include <RadioLib.h> | ||
|
||
// SX1278 has the following connections: | ||
// NSS pin: 10 | ||
// DIO0 pin: 2 | ||
// RESET pin: 9 | ||
// DIO1 pin: 3 | ||
SX1278 radio = new Module(10, 2, 9, 3); | ||
|
||
// create the node instance on the EU-868 band | ||
// using the radio module and the encryption key | ||
// make sure you are using the correct band | ||
// based on your geographical location! | ||
LoRaWANNode node(&radio, &EU868); | ||
|
||
void setup() { | ||
Serial.begin(9600); | ||
|
||
// initialize SX1278 with default settings | ||
Serial.print(F("[SX1278] Initializing ... ")); | ||
int state = radio.begin(); | ||
if(state == RADIOLIB_ERR_NONE) { | ||
Serial.println(F("success!")); | ||
} else { | ||
Serial.print(F("failed, code ")); | ||
Serial.println(state); | ||
while(true); | ||
} | ||
|
||
// application identifier - pre-LoRaWAN 1.1.0, this was called appEUI | ||
// when adding new end device in TTN, you will have to enter this number | ||
// you can pick any number you want, but it has to be unique | ||
uint64_t joinEUI = 0x12AD1011B0C0FFEE; | ||
|
||
// device identifier - this number can be anything | ||
// when adding new end device in TTN, you can generate this number, | ||
// or you can set any value you want, provided it is also unique | ||
uint64_t devEUI = 0x70B3D57ED005E120; | ||
|
||
// select some encryption keys which will be used to secure the communication | ||
// there are two of them - network key and application key | ||
// because LoRaWAN uses AES-128, the key MUST be 16 bytes (or characters) long | ||
|
||
// network key is the ASCII string "topSecretKey1234" | ||
uint8_t nwkKey[] = { 0x74, 0x6F, 0x70, 0x53, 0x65, 0x63, 0x72, 0x65, | ||
0x74, 0x4B, 0x65, 0x79, 0x31, 0x32, 0x33, 0x34 }; | ||
|
||
// application key is the ASCII string "aDifferentKeyABC" | ||
uint8_t appKey[] = { 0x61, 0x44, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, | ||
0x6E, 0x74, 0x4B, 0x65, 0x79, 0x41, 0x42, 0x43 }; | ||
|
||
// prior to LoRaWAN 1.1.0, only a single "nwkKey" is used | ||
// when connecting to LoRaWAN 1.0 network, "appKey" will be disregarded | ||
// and can be set to NULL | ||
|
||
// some frequency bands only use a subset of the available channels | ||
// you can select the specific band or set the first channel and last channel | ||
// for example, either of the following corresponds to US915 FSB2 in TTN | ||
/* | ||
node.selectSubband(2); | ||
node.selectSubband(8, 15); | ||
*/ | ||
|
||
// now we can start the activation | ||
// this can take up to 10 seconds, and requires a LoRaWAN gateway in range | ||
// a specific starting-datarate can be selected in dynamic bands (e.g. EU868): | ||
/* | ||
uint8_t joinDr = 4; | ||
state = node.beginOTAA(joinEUI, devEUI, nwkKey, appKey, joinDr); | ||
*/ | ||
Serial.print(F("[LoRaWAN] Attempting over-the-air activation ... ")); | ||
state = node.beginOTAA(joinEUI, devEUI, nwkKey, appKey); | ||
|
||
if(state == RADIOLIB_ERR_NONE) { | ||
Serial.println(F("success!")); | ||
} else { | ||
Serial.print(F("failed, code ")); | ||
Serial.println(state); | ||
while(true); | ||
} | ||
|
||
// after the device has been activated, | ||
// the session can be restored without rejoining after device power cycle | ||
// on EEPROM-enabled boards by calling "restore" | ||
/* | ||
Serial.print(F("[LoRaWAN] Resuming previous session ... ")); | ||
state = node.restore(); | ||
if(state == RADIOLIB_ERR_NONE) { | ||
Serial.println(F("success!")); | ||
} else { | ||
Serial.print(F("failed, code ")); | ||
Serial.println(state); | ||
while(true); | ||
} | ||
*/ | ||
|
||
// disable the ADR algorithm | ||
node.setADR(false); | ||
|
||
// set a fixed datarate | ||
node.setDatarate(5); | ||
|
||
// enable CSMA | ||
// this tries to minimize packet loss by searching for a free channel | ||
// before actually sending an uplink | ||
node.setCSMA(6, 2, true); | ||
} | ||
|
||
void loop() { | ||
int state = RADIOLIB_ERR_NONE; | ||
|
||
// set battery fill level - the LoRaWAN network server | ||
// may periodically request this information | ||
// 0 = external power source | ||
// 1 = lowest (empty battery) | ||
// 254 = highest (full battery) | ||
// 255 = unable to measure | ||
uint8_t battLevel = 146; | ||
node.setDeviceStatus(battLevel); | ||
|
||
// retrieve the last uplink frame counter | ||
uint32_t fcntUp = node.getFcntUp(); | ||
|
||
Serial.print(F("[LoRaWAN] Sending uplink packet ... ")); | ||
String strUp = "Hello World! #" + String(fcntUp); | ||
|
||
// send a confirmed uplink to port 10 every 64th frame | ||
if(fcntUp % 64 == 0) { | ||
state = node.uplink(strUp, 10, true); | ||
} else { | ||
state = node.uplink(strUp, 10); | ||
} | ||
if(state == RADIOLIB_ERR_NONE) { | ||
Serial.println(F("success!")); | ||
} else { | ||
Serial.print(F("failed, code ")); | ||
Serial.println(state); | ||
} | ||
|
||
// after uplink, you can call downlink(), | ||
// to receive any possible reply from the server | ||
// this function must be called within a few seconds | ||
// after uplink to receive the downlink! | ||
Serial.print(F("[LoRaWAN] Waiting for downlink ... ")); | ||
String strDown; | ||
|
||
// you can also retrieve additional information about | ||
// uplink or downlink by passing a reference to | ||
// LoRaWANEvent_t structure | ||
LoRaWANEvent_t event; | ||
state = node.downlink(strDown, &event); | ||
if(state == RADIOLIB_ERR_NONE) { | ||
Serial.println(F("success!")); | ||
|
||
// print data of the packet (if there are any) | ||
Serial.print(F("[LoRaWAN] Data:\t\t")); | ||
if(strDown.length() > 0) { | ||
Serial.println(strDown); | ||
} else { | ||
Serial.println(F("<MAC commands only>")); | ||
} | ||
|
||
// print RSSI (Received Signal Strength Indicator) | ||
Serial.print(F("[LoRaWAN] RSSI:\t\t")); | ||
Serial.print(radio.getRSSI()); | ||
Serial.println(F(" dBm")); | ||
|
||
// print SNR (Signal-to-Noise Ratio) | ||
Serial.print(F("[LoRaWAN] SNR:\t\t")); | ||
Serial.print(radio.getSNR()); | ||
Serial.println(F(" dB")); | ||
|
||
// print frequency error | ||
Serial.print(F("[LoRaWAN] Frequency error:\t")); | ||
Serial.print(radio.getFrequencyError()); | ||
Serial.println(F(" Hz")); | ||
|
||
// print extra information about the event | ||
Serial.println(F("[LoRaWAN] Event information:")); | ||
Serial.print(F("[LoRaWAN] Direction:\t")); | ||
if(event.dir == RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK) { | ||
Serial.println(F("uplink")); | ||
} else { | ||
Serial.println(F("downlink")); | ||
} | ||
Serial.print(F("[LoRaWAN] Confirmed:\t")); | ||
Serial.println(event.confirmed); | ||
Serial.print(F("[LoRaWAN] Confirming:\t")); | ||
Serial.println(event.confirming); | ||
Serial.print(F("[LoRaWAN] Frequency:\t")); | ||
Serial.print(event.freq, 3); | ||
Serial.println(F(" MHz")); | ||
Serial.print(F("[LoRaWAN] Output power:\t")); | ||
Serial.print(event.power); | ||
Serial.println(F(" dBm")); | ||
Serial.print(F("[LoRaWAN] Frame count:\t")); | ||
Serial.println(event.fcnt); | ||
Serial.print(F("[LoRaWAN] Port:\t\t")); | ||
Serial.println(event.port); | ||
|
||
Serial.print(radio.getFrequencyError()); | ||
|
||
} else if(state == RADIOLIB_ERR_RX_TIMEOUT) { | ||
Serial.println(F("timeout!")); | ||
|
||
} else { | ||
Serial.print(F("failed, code ")); | ||
Serial.println(state); | ||
} | ||
|
||
// on EEPROM enabled boards, you can save the current session | ||
// by calling "saveSession" which allows retrieving the session after reboot or deepsleep | ||
/* | ||
node.saveSession(); | ||
*/ | ||
|
||
// wait before sending another packet | ||
delay(30000); | ||
} |