From 6cd8214fe82f8ab68d502fbc76b851eef7db3f45 Mon Sep 17 00:00:00 2001 From: lewisxhe Date: Sat, 1 Jun 2024 13:53:00 +0800 Subject: [PATCH] Update RadioLib example --- .github/workflows/arduino_ci.yml | 3 +- .github/workflows/platformio.yml | 2 + .../LoRaWAN/LoRaWAN_ABP/LoRaWAN_ABP.ino | 216 ++++++++++++++++++ .../LoRaWAN_End_Device/LoRaWAN_End_Device.ino | 194 ---------------- .../LoRaWAN_End_Device_ABP.ino | 186 --------------- .../LoRaWAN_Starter/LoRaWAN_Starter.ino | 209 +++++++++++++++++ platformio.ini | 4 +- 7 files changed, 431 insertions(+), 383 deletions(-) create mode 100644 examples/radio/SX1262/LoRaWAN/LoRaWAN_ABP/LoRaWAN_ABP.ino delete mode 100644 examples/radio/SX1262/LoRaWAN/LoRaWAN_End_Device/LoRaWAN_End_Device.ino delete mode 100644 examples/radio/SX1262/LoRaWAN/LoRaWAN_End_Device_ABP/LoRaWAN_End_Device_ABP.ino create mode 100644 examples/radio/SX1262/LoRaWAN/LoRaWAN_Starter/LoRaWAN_Starter.ino diff --git a/.github/workflows/arduino_ci.yml b/.github/workflows/arduino_ci.yml index cb4e6362..c9f31e40 100644 --- a/.github/workflows/arduino_ci.yml +++ b/.github/workflows/arduino_ci.yml @@ -100,7 +100,8 @@ jobs: - examples/peripheral/RTC_TimeSynchronization/RTC_TimeSynchronization.ino - examples/peripheral/Vibrate_Basic/Vibrate_Basic.ino - examples/radio/SX1262/LoRaWAN/LoRaWAN_End_Device/LoRaWAN_End_Device.ino - - examples/radio/SX1262/LoRaWAN/LoRaWAN_End_Device_ABP/LoRaWAN_End_Device_ABP.ino + - examples/radio/SX1262/LoRaWAN/LoRaWAN_ABP/LoRaWAN_ABP.ino + - examples/radio/SX1262/LoRaWAN/LoRaWAN_Starter/LoRaWAN_Starter.ino - examples/radio/SX1262/SX126x_Channel_Activity_Detection/SX126x_Channel_Activity_Detection.ino - examples/radio/SX1262/SX126x_Channel_Activity_Detection_Interrupt/SX126x_Channel_Activity_Detection_Interrupt.ino - examples/radio/SX1262/SX126x_FSK_Modem/SX126x_FSK_Modem.ino diff --git a/.github/workflows/platformio.yml b/.github/workflows/platformio.yml index d78852f6..5ca7824e 100644 --- a/.github/workflows/platformio.yml +++ b/.github/workflows/platformio.yml @@ -100,6 +100,8 @@ jobs: - examples/peripheral/RTC_TimeLib - examples/peripheral/RTC_TimeSynchronization - examples/peripheral/Vibrate_Basic + - examples/radio/SX1262/LoRaWAN/LoRaWAN_ABP + - examples/radio/SX1262/LoRaWAN/LoRaWAN_Starter - examples/radio/SX1262/SX126x_Channel_Activity_Detection - examples/radio/SX1262/SX126x_Channel_Activity_Detection_Interrupt - examples/radio/SX1262/SX126x_FSK_Modem diff --git a/examples/radio/SX1262/LoRaWAN/LoRaWAN_ABP/LoRaWAN_ABP.ino b/examples/radio/SX1262/LoRaWAN/LoRaWAN_ABP/LoRaWAN_ABP.ino new file mode 100644 index 00000000..943ac524 --- /dev/null +++ b/examples/radio/SX1262/LoRaWAN/LoRaWAN_ABP/LoRaWAN_ABP.ino @@ -0,0 +1,216 @@ +/* + RadioLib LoRaWAN End Device ABP Example + + This example sets up a LoRaWAN node using ABP (activation + by personalization). 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 start uploading data directly, + without having to join the network. + + NOTE: LoRaWAN requires storing some parameters persistently! + RadioLib does this by using EEPROM, by default + starting at address 0 and using 32 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 +#include + + +// how often to send an uplink - consider legal & FUP constraints - see notes +const uint32_t uplinkIntervalSeconds = 5UL * 60UL; // minutes x seconds + + +// device address - either a development address or one assigned +// to the LoRaWAN Service Provider - TTN will generate one for you +#ifndef RADIOLIB_LORAWAN_DEV_ADDR // Replace with your DevAddr +#define RADIOLIB_LORAWAN_DEV_ADDR 0x12345678 +#endif + +#ifndef RADIOLIB_LORAWAN_FNWKSINT_KEY // Replace with your FNwkSInt Key +#define RADIOLIB_LORAWAN_FNWKSINT_KEY 0x74, 0x6F, 0x70, 0x53, 0x65, 0x63, 0x72, 0x65,0x74, 0x4B, 0x65, 0x79, 0x31, 0x32, 0x33, 0x34 +#endif +#ifndef RADIOLIB_LORAWAN_SNWKSINT_KEY // Replace with your SNwkSInt Key +#define RADIOLIB_LORAWAN_SNWKSINT_KEY 0x74, 0x6F, 0x70, 0x53, 0x65, 0x63, 0x72, 0x65,0x74, 0x4B, 0x65, 0x79, 0x31, 0x32, 0x33, 0x34 +#endif +#ifndef RADIOLIB_LORAWAN_NWKSENC_KEY // Replace with your NwkSEnc Key +#define RADIOLIB_LORAWAN_NWKSENC_KEY 0x74, 0x6F, 0x70, 0x53, 0x65, 0x63, 0x72, 0x65,0x74, 0x4B, 0x65, 0x79, 0x31, 0x32, 0x33, 0x34 +#endif +#ifndef RADIOLIB_LORAWAN_APPS_KEY // Replace with your AppS Key +#define RADIOLIB_LORAWAN_APPS_KEY 0x74, 0x6F, 0x70, 0x53, 0x65, 0x63, 0x72, 0x65,0x74, 0x4B, 0x65, 0x79, 0x31, 0x32, 0x33, 0x34 +#endif + +// for the curious, the #ifndef blocks allow for automated testing &/or you can +// put your EUI & keys in to your platformio.ini - see wiki for more tips + +// regional choices: EU868, US915, AU915, AS923, IN865, KR920, CN780, CN500 +const LoRaWANBand_t Region = EU868; +const uint8_t subBand = 0; // For US915, change this to 2, otherwise leave on 0 + + +SX1262 radio = newModule(); + + +// copy over the keys in to the something that will not compile if incorrectly formatted +uint32_t devAddr = RADIOLIB_LORAWAN_DEV_ADDR; +uint8_t fNwkSIntKey[] = { RADIOLIB_LORAWAN_FNWKSINT_KEY }; +uint8_t sNwkSIntKey[] = { RADIOLIB_LORAWAN_SNWKSINT_KEY }; +uint8_t nwkSEncKey[] = { RADIOLIB_LORAWAN_NWKSENC_KEY }; +uint8_t appSKey[] = { RADIOLIB_LORAWAN_APPS_KEY }; + +// create the LoRaWAN node +LoRaWANNode node(&radio, &Region, subBand); + + +String stateDecode(const int16_t result); +void debug(bool isFail, const __FlashStringHelper *message, int state, bool Freeze); + +void setup() +{ + Serial.begin(11520); + + watch.begin(); + + // initialize SX1262 with default settings + Serial.print(F("[SX1262] 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); + } + + // start the device by directly providing the encryption keys and device address + Serial.print(F("[LoRaWAN] Attempting over-the-air activation ... ")); + node.beginABP(devAddr, fNwkSIntKey, sNwkSIntKey, nwkSEncKey, appSKey); + + + node.activateABP(); + debug(state != RADIOLIB_ERR_NONE, F("Activate ABP failed"), state, true); + + Serial.println(F("Ready!\n")); +} + +// counter to keep track of transmitted packets +int count = 0; + +void loop() +{ + Serial.println(F("Sending uplink")); + + // This is the place to gather the sensor inputs + // Instead of reading any real sensor, we just generate some random numbers as example + uint8_t value1 = radio.random(100); + uint16_t value2 = radio.random(2000); + + // Build payload byte array + uint8_t uplinkPayload[3]; + uplinkPayload[0] = value1; + uplinkPayload[1] = highByte(value2); // See notes for high/lowByte functions + uplinkPayload[2] = lowByte(value2); + + // Perform an uplink + int state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload)); + debug((state != RADIOLIB_LORAWAN_NO_DOWNLINK) && (state != RADIOLIB_ERR_NONE), F("Error in sendReceive"), state, false); + + // Wait until next uplink - observing legal & TTN FUP constraints + delay(uplinkIntervalSeconds * 1000UL); +} + + + +// helper function to display any issues +void debug(bool isFail, const __FlashStringHelper *message, int state, bool Freeze) +{ + if (isFail) { + Serial.print(message); + Serial.print(" - "); + Serial.print(stateDecode(state)); + Serial.print(" ("); + Serial.print(state); + Serial.println(")"); + while (Freeze); + } +} + + +// result code to text ... +String stateDecode(const int16_t result) +{ + switch (result) { + case RADIOLIB_ERR_NONE: + return "ERR_NONE"; + case RADIOLIB_ERR_CHIP_NOT_FOUND: + return "ERR_CHIP_NOT_FOUND"; + case RADIOLIB_ERR_PACKET_TOO_LONG: + return "ERR_PACKET_TOO_LONG"; + case RADIOLIB_ERR_RX_TIMEOUT: + return "ERR_RX_TIMEOUT"; + case RADIOLIB_ERR_CRC_MISMATCH: + return "ERR_CRC_MISMATCH"; + case RADIOLIB_ERR_INVALID_BANDWIDTH: + return "ERR_INVALID_BANDWIDTH"; + case RADIOLIB_ERR_INVALID_SPREADING_FACTOR: + return "ERR_INVALID_SPREADING_FACTOR"; + case RADIOLIB_ERR_INVALID_CODING_RATE: + return "ERR_INVALID_CODING_RATE"; + case RADIOLIB_ERR_INVALID_FREQUENCY: + return "ERR_INVALID_FREQUENCY"; + case RADIOLIB_ERR_INVALID_OUTPUT_POWER: + return "ERR_INVALID_OUTPUT_POWER"; + case RADIOLIB_ERR_NETWORK_NOT_JOINED: + return "RADIOLIB_ERR_NETWORK_NOT_JOINED"; + + case RADIOLIB_ERR_DOWNLINK_MALFORMED: + return "RADIOLIB_ERR_DOWNLINK_MALFORMED"; + case RADIOLIB_ERR_INVALID_REVISION: + return "RADIOLIB_ERR_INVALID_REVISION"; + case RADIOLIB_ERR_INVALID_PORT: + return "RADIOLIB_ERR_INVALID_PORT"; + case RADIOLIB_ERR_NO_RX_WINDOW: + return "RADIOLIB_ERR_NO_RX_WINDOW"; + case RADIOLIB_ERR_INVALID_CID: + return "RADIOLIB_ERR_INVALID_CID"; + case RADIOLIB_ERR_UPLINK_UNAVAILABLE: + return "RADIOLIB_ERR_UPLINK_UNAVAILABLE"; + case RADIOLIB_ERR_COMMAND_QUEUE_FULL: + return "RADIOLIB_ERR_COMMAND_QUEUE_FULL"; + case RADIOLIB_ERR_COMMAND_QUEUE_ITEM_NOT_FOUND: + return "RADIOLIB_ERR_COMMAND_QUEUE_ITEM_NOT_FOUND"; + case RADIOLIB_ERR_JOIN_NONCE_INVALID: + return "RADIOLIB_ERR_JOIN_NONCE_INVALID"; + case RADIOLIB_ERR_N_FCNT_DOWN_INVALID: + return "RADIOLIB_ERR_N_FCNT_DOWN_INVALID"; + case RADIOLIB_ERR_A_FCNT_DOWN_INVALID: + return "RADIOLIB_ERR_A_FCNT_DOWN_INVALID"; + case RADIOLIB_ERR_DWELL_TIME_EXCEEDED: + return "RADIOLIB_ERR_DWELL_TIME_EXCEEDED"; + case RADIOLIB_ERR_CHECKSUM_MISMATCH: + return "RADIOLIB_ERR_CHECKSUM_MISMATCH"; + case RADIOLIB_LORAWAN_NO_DOWNLINK: + return "RADIOLIB_LORAWAN_NO_DOWNLINK"; + case RADIOLIB_LORAWAN_SESSION_RESTORED: + return "RADIOLIB_LORAWAN_SESSION_RESTORED"; + case RADIOLIB_LORAWAN_NEW_SESSION: + return "RADIOLIB_LORAWAN_NEW_SESSION"; + case RADIOLIB_LORAWAN_NONCES_DISCARDED: + return "RADIOLIB_LORAWAN_NONCES_DISCARDED"; + case RADIOLIB_LORAWAN_SESSION_DISCARDED: + return "RADIOLIB_LORAWAN_SESSION_DISCARDED"; + } + return "See TypeDef.h"; +} \ No newline at end of file diff --git a/examples/radio/SX1262/LoRaWAN/LoRaWAN_End_Device/LoRaWAN_End_Device.ino b/examples/radio/SX1262/LoRaWAN/LoRaWAN_End_Device/LoRaWAN_End_Device.ino deleted file mode 100644 index b6b76b5b..00000000 --- a/examples/radio/SX1262/LoRaWAN/LoRaWAN_End_Device/LoRaWAN_End_Device.ino +++ /dev/null @@ -1,194 +0,0 @@ -/* - RadioLib LoRaWAN End Device 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. - - NOTE: LoRaWAN requires storing some parameters persistently! - RadioLib does this by using EEPROM, by default - starting at address 0 and using 32 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 -#include - -SX1262 radio = newModule(); - -// 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 = NULL; - -void setup() -{ - Serial.begin(11520); - - - watch.begin(); - - // initialize SX1262 with default settings - Serial.print(F("[SX1262] 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); - } - - // set carrier frequency to 868.0 MHz - if (radio.setFrequency(868.0) == RADIOLIB_ERR_INVALID_FREQUENCY) { - Serial.println(F("Selected frequency is invalid for this module!")); - while (true); - } - - node = new LoRaWANNode(&radio, &EU868); - - // 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! - //node->wipe(); - - // 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 set the starting channel and their number - // for example, the following corresponds to US915 FSB2 in TTN - /* - node->startChannel = 8; - node->numChannels = 8; - */ - - // now we can start the activation - // this can take up to 20 seconds, and requires a LoRaWAN gateway in range - 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, - // network can be rejoined after device power cycle - // by calling "begin" - /* - Serial.print(F("[LoRaWAN] Resuming previous session ... ")); - state = node->begin(); - 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++); - int 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; - state = node->downlink(strDown); - 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("")); - } - - // 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("timeout!")); - - } else { - Serial.print(F("failed, code ")); - Serial.println(state); - } - - // wait before sending another packet - delay(10000); -} diff --git a/examples/radio/SX1262/LoRaWAN/LoRaWAN_End_Device_ABP/LoRaWAN_End_Device_ABP.ino b/examples/radio/SX1262/LoRaWAN/LoRaWAN_End_Device_ABP/LoRaWAN_End_Device_ABP.ino deleted file mode 100644 index 7920c061..00000000 --- a/examples/radio/SX1262/LoRaWAN/LoRaWAN_End_Device_ABP/LoRaWAN_End_Device_ABP.ino +++ /dev/null @@ -1,186 +0,0 @@ -/* - RadioLib LoRaWAN End Device ABP Example - - This example sets up a LoRaWAN node using ABP (activation - by personalization). 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 start uploading data directly, - without having to join the network. - - NOTE: LoRaWAN requires storing some parameters persistently! - RadioLib does this by using EEPROM, by default - starting at address 0 and using 32 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 -#include - -SX1262 radio = newModule(); - -// 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 = NULL; - -void setup() -{ - Serial.begin(11520); - - watch.begin(); - - // initialize SX1262 with default settings - Serial.print(F("[SX1262] 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); - } - - // set carrier frequency to 868.0 MHz - if (radio.setFrequency(868.0) == RADIOLIB_ERR_INVALID_FREQUENCY) { - Serial.println(F("Selected frequency is invalid for this module!")); - 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! - //node->wipe(); - - // device address - 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 unique - uint32_t devAddr = 0x12345678; - - // 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 nwkSKey[] = { 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 appSKey[] = { 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 set the starting channel and their number - // for example, the following corresponds to US915 FSB2 in TTN - /* - node->startChannel = 8; - node->numChannels = 8; - */ - - // start the device by directly providing the encryption keys and device address - Serial.print(F("[LoRaWAN] Attempting over-the-air activation ... ")); - state = node->beginABP(devAddr, (uint8_t *)nwkSKey, (uint8_t *)appSKey); - 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, - // network can be rejoined after device power cycle - // by calling "begin" - /* - Serial.print(F("[LoRaWAN] Resuming previous session ... ")); - state = node->begin(); - 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++); - int 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; - state = node->downlink(strDown); - 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("")); - } - - // 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("timeout!")); - - } else { - Serial.print(F("failed, code ")); - Serial.println(state); - } - - // wait before sending another packet - delay(10000); -} diff --git a/examples/radio/SX1262/LoRaWAN/LoRaWAN_Starter/LoRaWAN_Starter.ino b/examples/radio/SX1262/LoRaWAN/LoRaWAN_Starter/LoRaWAN_Starter.ino new file mode 100644 index 00000000..c7215b7e --- /dev/null +++ b/examples/radio/SX1262/LoRaWAN/LoRaWAN_Starter/LoRaWAN_Starter.ino @@ -0,0 +1,209 @@ +/* + RadioLib LoRaWAN Starter 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. + + 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/ + + For LoRaWAN details, see the wiki page + https://github.com/jgromes/RadioLib/wiki/LoRaWAN + +*/ +// include the library +#include +#include + +// how often to send an uplink - consider legal & FUP constraints - see notes +const uint32_t uplinkIntervalSeconds = 5UL * 60UL; // minutes x seconds + +// joinEUI - previous versions of LoRaWAN called this AppEUI +// for development purposes you can use all zeros - see wiki for details +#define RADIOLIB_LORAWAN_JOIN_EUI 0x0000000000000000 + +// the Device EUI & two keys can be generated on the TTN console +#ifndef RADIOLIB_LORAWAN_DEV_EUI // Replace with your Device EUI +#define RADIOLIB_LORAWAN_DEV_EUI 0x12345678 +#endif +#ifndef RADIOLIB_LORAWAN_APP_KEY // Replace with your App Key +#define RADIOLIB_LORAWAN_APP_KEY 0x74, 0x6F, 0x70, 0x53, 0x65, 0x63, 0x72, 0x65,0x74, 0x4B, 0x65, 0x79, 0x31, 0x32, 0x33, 0x34 +#endif +#ifndef RADIOLIB_LORAWAN_NWK_KEY // Put your Nwk Key here +#define RADIOLIB_LORAWAN_NWK_KEY 0x74, 0x6F, 0x70, 0x53, 0x65, 0x63, 0x72, 0x65,0x74, 0x4B, 0x65, 0x79, 0x31, 0x32, 0x33, 0x34 +#endif + +// for the curious, the #ifndef blocks allow for automated testing &/or you can +// put your EUI & keys in to your platformio.ini - see wiki for more tips + +// regional choices: EU868, US915, AU915, AS923, IN865, KR920, CN780, CN500 +const LoRaWANBand_t Region = EU868; +const uint8_t subBand = 0; // For US915, change this to 2, otherwise leave on 0 + + +// copy over the EUI's & keys in to the something that will not compile if incorrectly formatted +uint64_t joinEUI = RADIOLIB_LORAWAN_JOIN_EUI; +uint64_t devEUI = RADIOLIB_LORAWAN_DEV_EUI; +uint8_t appKey[] = { RADIOLIB_LORAWAN_APP_KEY }; +uint8_t nwkKey[] = { RADIOLIB_LORAWAN_NWK_KEY }; + + +SX1262 radio = newModule(); + +// create the LoRaWAN node +LoRaWANNode node(&radio, &Region, subBand); + + +String stateDecode(const int16_t result); +void debug(bool isFail, const __FlashStringHelper *message, int state, bool Freeze); + + +void setup() +{ + Serial.begin(115200); + while (!Serial); + delay(5000); // Give time to switch to the serial monitor + Serial.println(F("\nSetup ... ")); + + Serial.println(F("Initialise the radio")); + int16_t state = radio.begin(); + debug(state != RADIOLIB_ERR_NONE, F("Initialise radio failed"), state, true); + + // Setup the OTAA session information + node.beginOTAA(joinEUI, devEUI, nwkKey, appKey); + + Serial.println(F("Join ('login') the LoRaWAN Network")); + state = node.activateOTAA(); + debug(state != RADIOLIB_LORAWAN_NEW_SESSION, F("Join failed"), state, true); + + Serial.println(F("Ready!\n")); +} + +void loop() +{ + Serial.println(F("Sending uplink")); + + // This is the place to gather the sensor inputs + // Instead of reading any real sensor, we just generate some random numbers as example + uint8_t value1 = radio.random(100); + uint16_t value2 = radio.random(2000); + + // Build payload byte array + uint8_t uplinkPayload[3]; + uplinkPayload[0] = value1; + uplinkPayload[1] = highByte(value2); // See notes for high/lowByte functions + uplinkPayload[2] = lowByte(value2); + + // Perform an uplink + int16_t state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload)); + debug((state != RADIOLIB_LORAWAN_NO_DOWNLINK) && (state != RADIOLIB_ERR_NONE), F("Error in sendReceive"), state, false); + + Serial.print(F("Uplink complete, next in ")); + Serial.print(uplinkIntervalSeconds); + Serial.println(F(" seconds")); + + // Wait until next uplink - observing legal & TTN FUP constraints + delay(uplinkIntervalSeconds * 1000UL); // delay needs milli-seconds +} + + + +// result code to text ... +String stateDecode(const int16_t result) { + switch (result) { + case RADIOLIB_ERR_NONE: + return "ERR_NONE"; + case RADIOLIB_ERR_CHIP_NOT_FOUND: + return "ERR_CHIP_NOT_FOUND"; + case RADIOLIB_ERR_PACKET_TOO_LONG: + return "ERR_PACKET_TOO_LONG"; + case RADIOLIB_ERR_RX_TIMEOUT: + return "ERR_RX_TIMEOUT"; + case RADIOLIB_ERR_CRC_MISMATCH: + return "ERR_CRC_MISMATCH"; + case RADIOLIB_ERR_INVALID_BANDWIDTH: + return "ERR_INVALID_BANDWIDTH"; + case RADIOLIB_ERR_INVALID_SPREADING_FACTOR: + return "ERR_INVALID_SPREADING_FACTOR"; + case RADIOLIB_ERR_INVALID_CODING_RATE: + return "ERR_INVALID_CODING_RATE"; + case RADIOLIB_ERR_INVALID_FREQUENCY: + return "ERR_INVALID_FREQUENCY"; + case RADIOLIB_ERR_INVALID_OUTPUT_POWER: + return "ERR_INVALID_OUTPUT_POWER"; + case RADIOLIB_ERR_NETWORK_NOT_JOINED: + return "RADIOLIB_ERR_NETWORK_NOT_JOINED"; + + case RADIOLIB_ERR_DOWNLINK_MALFORMED: + return "RADIOLIB_ERR_DOWNLINK_MALFORMED"; + case RADIOLIB_ERR_INVALID_REVISION: + return "RADIOLIB_ERR_INVALID_REVISION"; + case RADIOLIB_ERR_INVALID_PORT: + return "RADIOLIB_ERR_INVALID_PORT"; + case RADIOLIB_ERR_NO_RX_WINDOW: + return "RADIOLIB_ERR_NO_RX_WINDOW"; + case RADIOLIB_ERR_INVALID_CID: + return "RADIOLIB_ERR_INVALID_CID"; + case RADIOLIB_ERR_UPLINK_UNAVAILABLE: + return "RADIOLIB_ERR_UPLINK_UNAVAILABLE"; + case RADIOLIB_ERR_COMMAND_QUEUE_FULL: + return "RADIOLIB_ERR_COMMAND_QUEUE_FULL"; + case RADIOLIB_ERR_COMMAND_QUEUE_ITEM_NOT_FOUND: + return "RADIOLIB_ERR_COMMAND_QUEUE_ITEM_NOT_FOUND"; + case RADIOLIB_ERR_JOIN_NONCE_INVALID: + return "RADIOLIB_ERR_JOIN_NONCE_INVALID"; + case RADIOLIB_ERR_N_FCNT_DOWN_INVALID: + return "RADIOLIB_ERR_N_FCNT_DOWN_INVALID"; + case RADIOLIB_ERR_A_FCNT_DOWN_INVALID: + return "RADIOLIB_ERR_A_FCNT_DOWN_INVALID"; + case RADIOLIB_ERR_DWELL_TIME_EXCEEDED: + return "RADIOLIB_ERR_DWELL_TIME_EXCEEDED"; + case RADIOLIB_ERR_CHECKSUM_MISMATCH: + return "RADIOLIB_ERR_CHECKSUM_MISMATCH"; + case RADIOLIB_LORAWAN_NO_DOWNLINK: + return "RADIOLIB_LORAWAN_NO_DOWNLINK"; + case RADIOLIB_LORAWAN_SESSION_RESTORED: + return "RADIOLIB_LORAWAN_SESSION_RESTORED"; + case RADIOLIB_LORAWAN_NEW_SESSION: + return "RADIOLIB_LORAWAN_NEW_SESSION"; + case RADIOLIB_LORAWAN_NONCES_DISCARDED: + return "RADIOLIB_LORAWAN_NONCES_DISCARDED"; + case RADIOLIB_LORAWAN_SESSION_DISCARDED: + return "RADIOLIB_LORAWAN_SESSION_DISCARDED"; + } + return "See TypeDef.h"; +} + +// helper function to display any issues +void debug(bool isFail, const __FlashStringHelper* message, int state, bool Freeze) { + if (isFail) { + Serial.print(message); + Serial.print(" - "); + Serial.print(stateDecode(state)); + Serial.print(" ("); + Serial.print(state); + Serial.println(")"); + while (Freeze); + } +} + + +// helper function to display a byte array +void arrayDump(uint8_t *buffer, uint16_t len) { + for(uint16_t c = 0; c < len; c++) { + char b = buffer[c]; + if(b < 0x10) { Serial.print('0'); } + Serial.print(b, HEX); + } + Serial.println(); +} \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 157c2734..6d2df23d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -122,8 +122,8 @@ ; src_dir = examples/radio/SX1262/SX126x_Spectrum_Scan_Frequency ; src_dir = examples/radio/SX1262/SX126x_Transmit ; src_dir = examples/radio/SX1262/SX126x_Transmit_Interrupt -; src_dir = examples/radio/SX1262/LoRaWAN/LoRaWAN_End_Device_ABP -; src_dir = examples/radio/SX1262/LoRaWAN/LoRaWAN_End_Device +; src_dir = examples/radio/SX1262/LoRaWAN/LoRaWAN_ABP +; src_dir = examples/radio/SX1262/LoRaWAN/LoRaWAN_Starter ; ! SX1280 Radio examples ; src_dir = examples/radio/SX1280//SX128x_BLE_Modem