Header comments & ABP
This commit is contained in:
parent
ff5ade2aa1
commit
c0ebd5a92e
6 changed files with 88 additions and 499 deletions
|
@ -1,178 +1,68 @@
|
|||
/*
|
||||
RadioLib LoRaWAN End Device ABP Example
|
||||
RadioLib LoRaWAN ABP Example
|
||||
|
||||
This example sets up a LoRaWAN node using ABP (activation
|
||||
by personalization). Before you start, you will have to
|
||||
ABP = Activation by Personalisation, an alternative
|
||||
to OTAA (Over the Air Activation). OTAA is preferable.
|
||||
|
||||
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 start uploading data directly,
|
||||
without having to join the network.
|
||||
The device will join the network and start uploading data.
|
||||
|
||||
LoRaWAN v1.1 requires the use of EEPROM (persistent storage).
|
||||
Running this examples REQUIRES you to check "Resets frame counters"
|
||||
on your LoRaWAN dashboard. Refer to the network's documentation
|
||||
on how to do this.
|
||||
|
||||
NOTE: LoRaWAN v1.1 requires storing parameters persistently!
|
||||
RadioLib does this by using EEPROM (persistent storage),
|
||||
by default starting at address 0 and using 448 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/
|
||||
|
||||
For LoRaWAN details, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/LoRaWAN
|
||||
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// SX1262 has the following pin order:
|
||||
// Module(NSS/CS, DIO1, RESET, BUSY)
|
||||
// SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
// SX1278 has the following pin order:
|
||||
// Module(NSS/CS, DIO0, RESET, DIO1)
|
||||
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);
|
||||
|
||||
// for fixed bands with subband selection
|
||||
// such as US915 and AU915, you must specify
|
||||
// the subband that matches the Frequency Plan
|
||||
// that you selected on your LoRaWAN console
|
||||
/*
|
||||
LoRaWANNode node(&radio, &US915, 2);
|
||||
*/
|
||||
#include "configABP.h"
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
delay(5000); // Give time to switch to the serial monitor
|
||||
Serial.println(F("\nSetup ... "));
|
||||
|
||||
// initialize radio (SX1262 / SX1278 / ... ) with default settings
|
||||
Serial.print(F("[Radio] Initializing ... "));
|
||||
Serial.println(F("Initalise the radio"));
|
||||
int state = radio.begin();
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
|
||||
// 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 };
|
||||
|
||||
// network key 2 is the ASCII string "topSecretKey5678"
|
||||
uint8_t fNwkSIntKey[] = { 0x61, 0x44, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65,
|
||||
0x6E, 0x74, 0x4B, 0x65, 0x35, 0x36, 0x37, 0x38 };
|
||||
|
||||
// network key 3 is the ASCII string "aDifferentKeyDEF"
|
||||
uint8_t sNwkSIntKey[] = { 0x61, 0x44, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65,
|
||||
0x6E, 0x74, 0x4B, 0x65, 0x79, 0x44, 0x45, 0x46 };
|
||||
|
||||
// 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
|
||||
|
||||
|
||||
// if using EU868 on ABP in TTN, you need to set the SF for RX2 window manually
|
||||
/*
|
||||
node.rx2.drMax = 3;
|
||||
*/
|
||||
|
||||
// on EEPROM-enabled boards, after the device has been activated,
|
||||
// the session can be restored without rejoining after device power cycle
|
||||
// this is intrinsically done when calling `beginABP()` with the same keys
|
||||
// in that case, the function will not need to transmit a JoinRequest
|
||||
|
||||
// to start a LoRaWAN v1.0 session,
|
||||
// the user can remove the fNwkSIntKey and sNwkSIntKey
|
||||
/*
|
||||
state = node.beginABP(devAddr, nwkSKey, appSKey);
|
||||
*/
|
||||
|
||||
// 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, nwkSKey, appSKey, fNwkSIntKey, sNwkSIntKey);
|
||||
if(state >= RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
debug(state != RADIOLIB_ERR_NONE, F("Initalise radio failed"), state, true);
|
||||
|
||||
Serial.println(F("Initalise LoRaWAN Network credentials"));
|
||||
state = node.beginABP(devAddr, NwkSEncKey, AppSKey, NwkSKey, SNwkSIntKey, true);
|
||||
debug(state < RADIOLIB_ERR_NONE, F("Session setup failed"), state, true);
|
||||
|
||||
Serial.println(F("Ready!\n"));
|
||||
}
|
||||
|
||||
// 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!" + String(count++);
|
||||
String strDown;
|
||||
int state = node.sendReceive(strUp, 10, strDown);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("received a downlink!"));
|
||||
Serial.println(F("Sending uplink"));
|
||||
|
||||
// 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>"));
|
||||
}
|
||||
// Read some inputs
|
||||
uint8_t Digital1 = digitalRead(2);
|
||||
uint16_t Analog1 = analogRead(A0);
|
||||
|
||||
// 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"));
|
||||
// Build payload byte array
|
||||
uint8_t uplinkPayload[3];
|
||||
uplinkPayload[0] = Digital1;
|
||||
uplinkPayload[1] = highByte(Analog1); // See notes for high/lowByte functions
|
||||
uplinkPayload[2] = lowByte(Analog1);
|
||||
|
||||
} else if(state == RADIOLIB_ERR_RX_TIMEOUT) {
|
||||
Serial.println(F("no downlink!"));
|
||||
// Perform an uplink
|
||||
int state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload));
|
||||
debug((state != RADIOLIB_ERR_RX_TIMEOUT) && (state != RADIOLIB_ERR_NONE), F("Error in sendReceive"), state, false);
|
||||
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// on EEPROM enabled boards, you should save the current session
|
||||
// by calling "saveSession" which allows retrieving the session after reboot or deepsleep
|
||||
node.saveSession();
|
||||
|
||||
// wait before sending another packet
|
||||
uint32_t minimumDelay = 60000; // try to send once every minute
|
||||
uint32_t interval = node.timeUntilUplink(); // calculate minimum duty cycle delay (per law!)
|
||||
uint32_t delayMs = max(interval, minimumDelay); // cannot send faster than duty cycle allows
|
||||
|
||||
delay(delayMs);
|
||||
// Wait until next uplink - observing legal & TTN FUP constraints
|
||||
delay(uplinkIntervalSeconds * 1000UL);
|
||||
}
|
||||
|
|
|
@ -6,26 +6,29 @@
|
|||
// 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
|
||||
// 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 0x------
|
||||
#endif
|
||||
|
||||
// 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 0x---------------
|
||||
#ifndef RADIOLIB_LORAWAN_NWKS_KEY // Replace with your NwkS Key
|
||||
#define RADIOLIB_LORAWAN_NWKS_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
|
||||
#endif
|
||||
#ifndef RADIOLIB_LORAWAN_APP_KEY // Replace with your App Key
|
||||
#define RADIOLIB_LORAWAN_APP_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
|
||||
#ifndef RADIOLIB_LORAWAN_SNWKSINT_KEY // Replace with your SNwkSInt Key
|
||||
#define RADIOLIB_LORAWAN_SNWKSINT_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
|
||||
#endif
|
||||
#ifndef RADIOLIB_LORAWAN_NWK_KEY // Put your Nwk Key here
|
||||
#define RADIOLIB_LORAWAN_NWK_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
|
||||
#ifndef RADIOLIB_LORAWAN_NWKSENC_KEY // Replace with your NwkSEnc Key
|
||||
#define RADIOLIB_LORAWAN_NWKSENC_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
|
||||
#endif
|
||||
#ifndef RADIOLIB_LORAWAN_APPS_KEY // Replace with your AppS Key
|
||||
#define RADIOLIB_LORAWAN_APPS_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
|
||||
#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
|
||||
|
@ -97,11 +100,13 @@ const uint8_t subBand = 0; // For US915, change this to 2, otherwise leave on 0
|
|||
#endif
|
||||
|
||||
|
||||
// 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 };
|
||||
// Copy over the keys in to the something that will not compile if incorrectly formatted
|
||||
uint32_t devAddr = RADIOLIB_LORAWAN_DEV_ADDR;
|
||||
uint8_t NwkSKey[] = { RADIOLIB_LORAWAN_NWKS_KEY };
|
||||
uint8_t SNwkSIntKey[] = { RADIOLIB_LORAWAN_SNWKSINT_KEY }; // Previously sNwkSIntKey
|
||||
uint8_t NwkSEncKey[] = { RADIOLIB_LORAWAN_NWKSENC_KEY }; // Previously fNwkSIntKey
|
||||
uint8_t AppSKey[] = { RADIOLIB_LORAWAN_APPS_KEY };
|
||||
|
||||
|
||||
// Create the LoRaWAN node
|
||||
LoRaWANNode node(&radio, &Region, subBand);
|
||||
|
|
|
@ -1,196 +0,0 @@
|
|||
|
||||
/*
|
||||
|
||||
This demonstrates how to save the join information in to permanent memory
|
||||
so that if the power fails, batteries run out or are changed, the rejoin
|
||||
is more efficient & happens sooner due to the way that LoRaWAN secures
|
||||
the join process - see the wiki for more details.
|
||||
|
||||
This is typically useful for devices that need more power than a battery
|
||||
driven sensor - something like a air quality monitor or GPS based device that
|
||||
is likely to use up it's power source resulting in loss of the session.
|
||||
|
||||
The relevant code is flagged with a ##### comment
|
||||
|
||||
Saving the entire session is possible but not demonstrated here - it has
|
||||
implications for flash wearing and complications with which parts of the
|
||||
session may have changed after an uplink. So it is assumed that the device
|
||||
is going in to deep-sleep, as below, between normal uplinks.
|
||||
|
||||
*/
|
||||
|
||||
#if !defined(ESP32)
|
||||
#pragma error ("This is not the example your device is looking for - ESP32 only")
|
||||
#endif
|
||||
|
||||
// ##### Load the ESP32 preferences facilites
|
||||
#include <Preferences.h>
|
||||
Preferences store;
|
||||
|
||||
// LoRaWAN config, credentials & pinmap
|
||||
#include "config.h"
|
||||
|
||||
#include <RadioLib.h>
|
||||
|
||||
// Utilities & vars to support ESP32 deep-sleep. The RTC_DATA_ATTR attribute
|
||||
// puts these in to the RTC memory which is preserved during deep-sleep
|
||||
RTC_DATA_ATTR uint16_t bootCount = 1;
|
||||
RTC_DATA_ATTR uint16_t bootCountSinceUnsuccessfulJoin = 0;
|
||||
RTC_DATA_ATTR uint8_t LWsession[RADIOLIB_LORAWAN_SESSION_BUF_SIZE];
|
||||
|
||||
// Abbreviated version from the Arduino-ESP32 package, see
|
||||
// https://espressif-docs.readthedocs-hosted.com/projects/arduino-esp32/en/latest/api/deepsleep.html
|
||||
// for the complete set of options
|
||||
void print_wakeup_reason() {
|
||||
esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause();
|
||||
if (wakeup_reason == ESP_SLEEP_WAKEUP_TIMER) {
|
||||
Serial.println(F("Wake from sleep"));
|
||||
} else {
|
||||
Serial.print(F("Wake not caused by deep sleep: "));
|
||||
Serial.println(wakeup_reason);
|
||||
}
|
||||
|
||||
Serial.print(F("Boot count: "));
|
||||
Serial.println(bootCount++);
|
||||
}
|
||||
|
||||
// Put device in to lowest power deep-sleep mode
|
||||
void gotoSleep(uint32_t seconds) {
|
||||
esp_sleep_enable_timer_wakeup(seconds * 1000UL * 1000UL); // Function uses uS
|
||||
Serial.println(F("Sleeping\n"));
|
||||
Serial.flush();
|
||||
|
||||
esp_deep_sleep_start();
|
||||
|
||||
// If this appears in the serial debug, we didn't go to sleep!
|
||||
// So take defensive action so we don't continually uplink
|
||||
Serial.println(F("\n\n### Sleep failed, delay of 5 minutes & then restart ###\n"));
|
||||
delay(5UL * 60UL * 1000UL);
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Setup & execute all device functions ...
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // Wait for serial to be initalised
|
||||
delay(2000); // Give time to switch to the serial monitor
|
||||
Serial.println(F("\nSetup"));
|
||||
print_wakeup_reason();
|
||||
|
||||
int16_t state = 0; // return value for calls to RadioLib
|
||||
|
||||
// Setup the radio based on the pinmap (connections) in config.h
|
||||
Serial.println(F("Initalise the radio"));
|
||||
state = radio.begin();
|
||||
debug(state != RADIOLIB_ERR_NONE, F("Initalise radio failed"), state, true);
|
||||
|
||||
Serial.println(F("Recalling LoRaWAN nonces & session"));
|
||||
// ##### Setup the flash storage
|
||||
store.begin("radiolib");
|
||||
// ##### If we have previously saved nonces, restore them
|
||||
if (store.isKey("nonces")) {
|
||||
uint8_t buffer[RADIOLIB_LORAWAN_NONCES_BUF_SIZE];// Create somewhere to store nonces
|
||||
store.getBytes("nonces", buffer, RADIOLIB_LORAWAN_NONCES_BUF_SIZE);// Get them to the store
|
||||
state = node.setBufferNonces(buffer); // Send them to LoRaWAN
|
||||
debug(state != RADIOLIB_ERR_NONE, F("Restoring nonces buffer failed"), state, false);
|
||||
}
|
||||
|
||||
// Recall session from RTC deep-sleep preserved variable
|
||||
state = node.setBufferSession(LWsession); // Send them to LoRaWAN stack
|
||||
// If we have booted at least once we should have a session to restore, so report any failure
|
||||
// Otherwise no point saying there's been a failure when it was bound to fail with an empty
|
||||
// LWsession var. At this point, bootCount has already been incremented, hence the > 2
|
||||
debug((state != RADIOLIB_ERR_NONE) && (bootCount > 2), F("Restoring session buffer failed"), state, false);
|
||||
|
||||
// Process the restored session or failing that, create a new one &
|
||||
// return flag to indicate a fresh join is required
|
||||
Serial.println(F("Setup LoRaWAN session"));
|
||||
state = node.beginOTAA(joinEUI, devEUI, nwkKey, appKey, false);
|
||||
// See comment above, no need to report a failure that is bound to occur on first boot
|
||||
debug((state != RADIOLIB_ERR_NONE) && (bootCount > 2), F("Restore session failed"), state, false);
|
||||
|
||||
// Loop until successful join
|
||||
while (state != RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("Join ('login') to the LoRaWAN Network"));
|
||||
state = node.beginOTAA(joinEUI, devEUI, nwkKey, appKey, true);
|
||||
|
||||
if (state < RADIOLIB_ERR_NONE) {
|
||||
Serial.print(F("Join failed: "));
|
||||
Serial.println(state);
|
||||
|
||||
// How long to wait before join attenpts. This is an interim solution pending
|
||||
// implementation of TS001 LoRaWAN Specification section #7 - this doc applies to v1.0.4 & v1.1
|
||||
// It sleeps for longer & longer durations to give time for any gateway issues to resolve
|
||||
// or whatever is interfering with the device <-> gateway airwaves.
|
||||
uint32_t sleepForSeconds = min((bootCountSinceUnsuccessfulJoin++ + 1UL) * 60UL, 3UL * 60UL);
|
||||
Serial.print(F("Boots since unsuccessful join: "));
|
||||
Serial.println(bootCountSinceUnsuccessfulJoin);
|
||||
Serial.print(F("Retrying join in "));
|
||||
Serial.print(sleepForSeconds);
|
||||
Serial.println(F(" seconds"));
|
||||
|
||||
gotoSleep(sleepForSeconds);
|
||||
|
||||
} else { // Join was successful
|
||||
Serial.println(F("Joined"));
|
||||
|
||||
// ##### Save the join counters (nonces) to permanent store
|
||||
Serial.println(F("Saving nonces to flash"));
|
||||
uint8_t buffer[RADIOLIB_LORAWAN_NONCES_BUF_SIZE]; // Create somewhere to store nonces
|
||||
uint8_t *persist = node.getBufferNonces(); // Get pointer to nonces
|
||||
memcpy(buffer, persist, RADIOLIB_LORAWAN_NONCES_BUF_SIZE); // Copy in to buffer
|
||||
store.putBytes("nonces", buffer, RADIOLIB_LORAWAN_NONCES_BUF_SIZE); // Send them to the store
|
||||
|
||||
// We'll save the session after the uplink
|
||||
|
||||
// Reset the failed join count
|
||||
bootCountSinceUnsuccessfulJoin = 0;
|
||||
|
||||
delay(1000); // Hold off off hitting the airwaves again too soon - an issue in the US
|
||||
|
||||
} // if beginOTAA state
|
||||
} // while join
|
||||
|
||||
// ##### Close the store
|
||||
store.end();
|
||||
|
||||
|
||||
// ----- And now for the main event -----
|
||||
Serial.println(F("Sending uplink"));
|
||||
|
||||
// Read some inputs
|
||||
uint8_t Digital2 = digitalRead(2);
|
||||
uint16_t Analog1 = analogRead(A1);
|
||||
|
||||
// Build payload byte array
|
||||
uint8_t uplinkPayload[3];
|
||||
uplinkPayload[0] = Digital2;
|
||||
uplinkPayload[1] = highByte(Analog1); // See notes for high/lowByte functions
|
||||
uplinkPayload[2] = lowByte(Analog1);
|
||||
|
||||
// Perform an uplink
|
||||
state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload));
|
||||
debug((state != RADIOLIB_ERR_RX_TIMEOUT) && (state != RADIOLIB_ERR_NONE), F("Error in sendReceive"), state, false);
|
||||
|
||||
Serial.print(F("FcntUp: "));
|
||||
Serial.println(node.getFcntUp());
|
||||
|
||||
// Now save session to RTC memory
|
||||
uint8_t *persist = node.getBufferSession();
|
||||
memcpy(LWsession, persist, RADIOLIB_LORAWAN_SESSION_BUF_SIZE);
|
||||
|
||||
// Wait until next uplink - observing legal & TTN FUP constraints
|
||||
gotoSleep(uplinkIntervalSeconds);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// The ESP32 wakes from deep-sleep and starts from the very beginning
|
||||
// which is a very good place to start, as any singing nun knows.
|
||||
// It then goes back to sleep, so loop() is never called and which is
|
||||
// why it is empty.
|
||||
|
||||
void loop() {}
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
|
||||
#include <RadioLib.h>
|
||||
|
||||
// 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 0x---------------
|
||||
#endif
|
||||
#ifndef RADIOLIB_LORAWAN_APP_KEY // Replace with your App Key
|
||||
#define RADIOLIB_LORAWAN_APP_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
|
||||
#endif
|
||||
#ifndef RADIOLIB_LORAWAN_NWK_KEY // Put your Nwk Key here
|
||||
#define RADIOLIB_LORAWAN_NWK_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
|
||||
#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
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// Below is to support the sketch - only make changes if the notes say so ...
|
||||
|
||||
// Auto select MCU <-> radio connections
|
||||
// If you get an error message when compiling, it may be that the
|
||||
// pinmap could not be determined - see the notes for more info
|
||||
|
||||
// Adafruit
|
||||
#if defined(ARDUINO_SAMD_FEATHER_M0)
|
||||
#pragma message ("Adafruit Feather M0 with RFM95")
|
||||
#pragma message ("Link required on board")
|
||||
SX1276 radio = new Module(8, 3, 4, 6);
|
||||
|
||||
|
||||
// LilyGo
|
||||
#elif defined(ARDUINO_TTGO_LORA32_V1)
|
||||
#pragma message ("TTGO LoRa32 v1 - no Display")
|
||||
SX1276 radio = new Module(18, 26, 14, 33);
|
||||
|
||||
#elif defined(ARDUINO_TTGO_LORA32_V2)
|
||||
#pragma error ("ARDUINO_TTGO_LORA32_V2 awaiting pin map")
|
||||
|
||||
#elif defined(ARDUINO_TTGO_LoRa32_v21new) // T3_V1.6.1
|
||||
#pragma message ("Using TTGO LoRa32 v2.1 marked T3_V1.6.1 + Display")
|
||||
SX1276 radio = new Module(18, 26, 14, 33);
|
||||
|
||||
#elif defined(ARDUINO_TBEAM_USE_RADIO_SX1262)
|
||||
#pragma error ("ARDUINO_TBEAM_USE_RADIO_SX1262 awaiting pin map")
|
||||
|
||||
#elif defined(ARDUINO_TBEAM_USE_RADIO_SX1276)
|
||||
#pragma message ("Using TTGO LoRa32 v2.1 marked T3_V1.6.1 + Display")
|
||||
SX1276 radio = new Module(18, 26, 23, 33);
|
||||
|
||||
|
||||
// Heltec
|
||||
#elif defined(ARDUINO_HELTEC_WIFI_LORA_32)
|
||||
#pragma error ("ARDUINO_HELTEC_WIFI_LORA_32 awaiting pin map")
|
||||
|
||||
#elif defined(ARDUINO_heltec_wifi_kit_32_V2)
|
||||
#pragma message ("ARDUINO_heltec_wifi_kit_32_V2 awaiting pin map")
|
||||
SX1276 radio = new Module(18, 26, 14, 35);
|
||||
|
||||
#elif defined(ARDUINO_heltec_wifi_kit_32_V3)
|
||||
#pragma message ("Using Heltec WiFi LoRa32 v3 - Display + USB-C")
|
||||
SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
#elif defined(ARDUINO_CUBECELL_BOARD)
|
||||
#pragma message ("Using TTGO LoRa32 v2.1 marked T3_V1.6.1 + Display")
|
||||
SX1262 radio = new Module(RADIOLIB_BUILTIN_MODULE);
|
||||
|
||||
#elif defined(ARDUINO_CUBECELL_BOARD_V2)
|
||||
#pragma error ("ARDUINO_CUBECELL_BOARD_V2 awaiting pin map")
|
||||
|
||||
|
||||
#else
|
||||
#pragma message ("Unknown board - no automagic pinmap available")
|
||||
|
||||
// SX1262 pin order: Module(NSS/CS, DIO1, RESET, BUSY);
|
||||
// SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
// SX1278 pin order: Module(NSS/CS, DIO0, RESET, DIO1);
|
||||
// SX1278 radio = new Module(10, 2, 9, 3);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// 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 };
|
||||
|
||||
// Create the LoRaWAN node
|
||||
LoRaWANNode node(&radio, &Region, subBand);
|
||||
|
||||
|
||||
// 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(state);
|
||||
Serial.println(")");
|
||||
while (Freeze);
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to display a byte array
|
||||
void arrayDump(uint8_t *buffer, uint16_t len) {
|
||||
for (uint16_t c; c < len; c++) {
|
||||
Serial.printf("%02X", buffer[c]);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -11,8 +11,6 @@
|
|||
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.
|
||||
|
@ -26,7 +24,6 @@
|
|||
For LoRaWAN details, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/LoRaWAN
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
@ -38,7 +35,7 @@
|
|||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // Wait for serial to be initalised
|
||||
delay(2000); // Give time to switch to the serial monitor
|
||||
delay(5000); // Give time to switch to the serial monitor
|
||||
Serial.println(F("\nSetup"));
|
||||
|
||||
int16_t state = 0; // return value for calls to RadioLib
|
||||
|
|
|
@ -1,10 +1,33 @@
|
|||
#include <Arduino.h>
|
||||
/*
|
||||
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 "config.h"
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
delay(5000); // Give time to switch to the serial monitor
|
||||
Serial.println(F("\nSetup ... "));
|
||||
|
||||
Serial.println(F("Initalise the radio"));
|
||||
|
|
Loading…
Add table
Reference in a new issue