Update RadioLib
This commit is contained in:
parent
54315bae97
commit
811f6064d7
183 changed files with 19613 additions and 10628 deletions
166
lib/RadioLib/examples/ADSB/ADSB_Monitor/ADSB_Monitor.ino
Normal file
166
lib/RadioLib/examples/ADSB/ADSB_Monitor/ADSB_Monitor.ino
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
RadioLib ADS-B Monitor Example
|
||||
|
||||
This example shows how to receive ADS-B messages
|
||||
using LR2021 OOK modem and forward them to be displayed
|
||||
in a live dashboard.
|
||||
|
||||
To show the live dashboard in a terminal, run the Python script
|
||||
RadioLib/extras/ADSB_Monitor/ADSBMonitorServer.py,
|
||||
and then connect to from "modeslive" from the pyModeS package
|
||||
(see the script helptext for installation instructions).
|
||||
|
||||
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>
|
||||
|
||||
// LR2021 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR2021 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or detect the pinout automatically using RadioBoards
|
||||
// https://github.com/radiolib-org/RadioBoards
|
||||
/*
|
||||
#define RADIO_BOARD_AUTO
|
||||
#include <RadioBoards.h>
|
||||
Radio radio = new RadioModule();
|
||||
*/
|
||||
|
||||
// create ADS-B client instance using the module
|
||||
ADSBClient adsb(&radio);
|
||||
|
||||
// flag to indicate that a packet was received
|
||||
volatile bool receivedFlag = false;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// we got a packet, set the flag
|
||||
receivedFlag = true;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// LR2021 allows to use any DIO pin as the interrupt
|
||||
// as an example, we set DIO10 to be the IRQ
|
||||
// this has to be done prior to calling begin()!
|
||||
radio.irqDioNum = 10;
|
||||
|
||||
// initialize LR2021 OOK modem at 1090 MHz,
|
||||
// 2 Mbps bit rate and receiver bandwidth 3076 kHz
|
||||
Serial.print(F("[LR2021] Initializing ... "));
|
||||
int state = radio.beginOOK(1090, 2000, 3076);
|
||||
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true) { delay(10); }
|
||||
}
|
||||
|
||||
// initialize ADS-B client
|
||||
Serial.print(F("[ADS-B] Initializing ... "));
|
||||
state = adsb.begin();
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true) { delay(10); }
|
||||
}
|
||||
|
||||
// apply LR2021-specific settings
|
||||
Serial.print(F("[LR2021] Setting configuration ... "));
|
||||
state = radio.setRxBoostedGainMode(7);
|
||||
state += radio.setCRC(3, 0, 0x1FFF409UL, false);
|
||||
state += radio.ookDetector();
|
||||
state += radio.fixedPacketLengthMode(11);
|
||||
state += radio.setGain(13);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true) { delay(10); }
|
||||
}
|
||||
|
||||
// measure current noise floor and add some margin
|
||||
// this values is later used to set the signal detection threshold
|
||||
float threshold = radio.getRSSI(false) + 10;
|
||||
Serial.print(F("[LR2021] Detection threshold: "));
|
||||
Serial.print(threshold, 2);
|
||||
Serial.println(F(" dBm"));
|
||||
|
||||
Serial.print(F("[LR2021] Setting threshold ... "));
|
||||
state = radio.setOokDetectionThreshold(threshold);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true) { delay(10); }
|
||||
}
|
||||
|
||||
// set the function that will be called
|
||||
// when new packet is received
|
||||
radio.setPacketReceivedAction(setFlag);
|
||||
|
||||
// start listening for LoRa packets
|
||||
Serial.print(F("[LR2021] Starting to listen ... "));
|
||||
state = radio.startReceive();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true) { delay(10); }
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check if the flag is set
|
||||
if(receivedFlag) {
|
||||
// reset flag
|
||||
receivedFlag = false;
|
||||
|
||||
// read the received binary data
|
||||
// ADS-B frames have fixed length of 14 bytes,
|
||||
// 3 of which are used as CRC which is handled automatically
|
||||
uint8_t buff[11] = { 0 };
|
||||
int state = radio.readData(buff, 11);
|
||||
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
// packet was successfully received
|
||||
// print it out, further processing is done by pyModeS
|
||||
Serial.print(F("[ADS-B] "));
|
||||
for(int i = 0; i < 11; i++) {
|
||||
if(buff[i] < 0x10) { Serial.print('0'); }
|
||||
Serial.print(buff[i], HEX);
|
||||
}
|
||||
|
||||
// pyModeS expects the data to include the CRC
|
||||
// but does not seem to be actually checking it
|
||||
// since we handle CRC automatically, just append 3 null bytes
|
||||
Serial.println(F("000000"));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
223
lib/RadioLib/examples/ADSB/ADSB_Receive/ADSB_Receive.ino
Normal file
223
lib/RadioLib/examples/ADSB/ADSB_Receive/ADSB_Receive.ino
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
RadioLib ADS-B Reception Example
|
||||
|
||||
This example shows how to receive ADS-B messages
|
||||
using LR2021 OOK modem.
|
||||
|
||||
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>
|
||||
|
||||
// LR2021 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR2021 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or detect the pinout automatically using RadioBoards
|
||||
// https://github.com/radiolib-org/RadioBoards
|
||||
/*
|
||||
#define RADIO_BOARD_AUTO
|
||||
#include <RadioBoards.h>
|
||||
Radio radio = new RadioModule();
|
||||
*/
|
||||
|
||||
// create ADS-B client instance using the module
|
||||
ADSBClient adsb(&radio);
|
||||
|
||||
// flag to indicate that a packet was received
|
||||
volatile bool receivedFlag = false;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// we got a packet, set the flag
|
||||
receivedFlag = true;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// LR2021 allows to use any DIO pin as the interrupt
|
||||
// as an example, we set DIO10 to be the IRQ
|
||||
// this has to be done prior to calling begin()!
|
||||
radio.irqDioNum = 10;
|
||||
|
||||
// initialize LR2021 OOK modem at 1090 MHz,
|
||||
// 2 Mbps bit rate and receiver bandwidth 3076 kHz
|
||||
Serial.print(F("[LR2021] Initializing ... "));
|
||||
int state = radio.beginOOK(1090, 2000, 3076);
|
||||
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true) { delay(10); }
|
||||
}
|
||||
|
||||
// initialize ADS-B client
|
||||
Serial.print(F("[ADS-B] Initializing ... "));
|
||||
state = adsb.begin();
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true) { delay(10); }
|
||||
}
|
||||
|
||||
// apply LR2021-specific settings
|
||||
Serial.print(F("[LR2021] Setting configuration ... "));
|
||||
state = radio.setRxBoostedGainMode(7);
|
||||
state += radio.setCRC(3, 0, 0x1FFF409UL, false);
|
||||
state += radio.ookDetector();
|
||||
state += radio.fixedPacketLengthMode(11);
|
||||
state += radio.setGain(13);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true) { delay(10); }
|
||||
}
|
||||
|
||||
// measure current noise floor and add some margin
|
||||
// this values is later used to set the signal detection threshold
|
||||
float threshold = radio.getRSSI(false) + 10;
|
||||
Serial.print(F("[LR2021] Detection threshold: "));
|
||||
Serial.print(threshold, 2);
|
||||
Serial.println(F(" dBm"));
|
||||
|
||||
Serial.print(F("[LR2021] Setting threshold ... "));
|
||||
state = radio.setOokDetectionThreshold(threshold);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true) { delay(10); }
|
||||
}
|
||||
|
||||
// set the reference position (position of the receiver)
|
||||
// this will be used later to calculate the aircraft position
|
||||
adsb.setReferencePosition(46.24722039359617f, 12.097993784412322f);
|
||||
|
||||
// set the function that will be called
|
||||
// when new packet is received
|
||||
radio.setPacketReceivedAction(setFlag);
|
||||
|
||||
// start listening for LoRa packets
|
||||
Serial.print(F("[LR2021] Starting to listen ... "));
|
||||
state = radio.startReceive();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true) { delay(10); }
|
||||
}
|
||||
}
|
||||
|
||||
// these variables will be used later to save decoded information
|
||||
ADSBFrame frame;
|
||||
ADSBAircraftCategory category;
|
||||
char callsign[RADIOLIB_ADSB_CALLSIGN_LEN];
|
||||
char hexId[RADIOLIB_ADSB_HEX_ID_LEN];
|
||||
ADSBAircraftCategory cat;
|
||||
int alt;
|
||||
float lat, lon;
|
||||
bool altGnss;
|
||||
|
||||
void loop() {
|
||||
// check if the flag is set
|
||||
if(receivedFlag) {
|
||||
// reset flag
|
||||
receivedFlag = false;
|
||||
|
||||
// read the received binary data
|
||||
// ADS-B frames have fixed length of 14 bytes,
|
||||
// 3 of which are used as CRC which is handled automatically
|
||||
uint8_t buff[11] = { 0 };
|
||||
int state = radio.readData(buff, 11);
|
||||
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
// packet was successfully received
|
||||
Serial.println(F("[LR2021] Received packet!"));
|
||||
|
||||
state = adsb.decode(buff, &frame);
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("[ADS-B] Decoded frame!"));
|
||||
// print the decoded information
|
||||
Serial.print(F("[ADS-B] DF = "));
|
||||
Serial.println(frame.downlinkFormat);
|
||||
Serial.print(F("[ADS-B] CA = "));
|
||||
Serial.println(frame.capability);
|
||||
Serial.print(F("[ADS-B] Message type = "));
|
||||
Serial.println((int)frame.messageType);
|
||||
|
||||
// get the hexadecimal ID (ICAO address) of the transceiver
|
||||
state = adsb.parseHexId(&frame, hexId);
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.print(F("[ADS-B] Hex ID = "));
|
||||
Serial.println(hexId);
|
||||
}
|
||||
|
||||
// further information depends on the message type
|
||||
switch(frame.messageType) {
|
||||
case(ADSBMessageType::AIRCRAFT_ID):
|
||||
adsb.parseCallsign(&frame, callsign, &cat);
|
||||
Serial.print(F("[ADS-B] Callsign = "));
|
||||
Serial.println(callsign);
|
||||
Serial.print(F("[ADS-B] Category = "));
|
||||
Serial.println((int)category);
|
||||
break;
|
||||
|
||||
case(ADSBMessageType::AIRBORNE_POS_ALT_BARO):
|
||||
case(ADSBMessageType::AIRBORNE_POS_ALT_GNSS):
|
||||
adsb.parseAirbornePosition(&frame, &alt, &lat, &lon, &altGnss);
|
||||
Serial.print(F("[ADS-B] Altitude = "));
|
||||
Serial.print(alt);
|
||||
if(altGnss) { Serial.println(" meters\n"); } else { Serial.println(" feet\n"); }
|
||||
Serial.print(F("[ADS-B] Latitude = "));
|
||||
Serial.println(lat, 6);
|
||||
Serial.print(F("[ADS-B] Longitude = "));
|
||||
Serial.println(lon, 6);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
Serial.print(F("[ADS-B] Failed to decode, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
|
||||
} else if (state == RADIOLIB_ERR_CRC_MISMATCH) {
|
||||
// packet was received, but is malformed
|
||||
Serial.println(F("CRC error!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -82,10 +82,11 @@ void setup() {
|
|||
void loop() {
|
||||
Serial.print(F("[CC1101] Transmitting packet ... "));
|
||||
|
||||
// you can transmit C-string or Arduino string up to 64 characters long
|
||||
// you can transmit C-string or Arduino string up to 255 characters long
|
||||
int state = radio.transmit("Hello World!");
|
||||
|
||||
// you can also transmit byte array up to 64 bytes long
|
||||
// you can also transmit byte array up to 255 bytes long
|
||||
// With some limitations see here: https://github.com/jgromes/RadioLib/discussions/1138
|
||||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
|
||||
int state = radio.transmit(byteArr, 8);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
RadioLib CC1101 Blocking Transmit Example
|
||||
|
||||
This example transmits packets using CC1101 FSK radio module.
|
||||
Each packet contains up to 64 bytes of data, in the form of:
|
||||
Each packet contains up to 255 bytes of data with some limitations (https://github.com/jgromes/RadioLib/discussions/1138), in the form of:
|
||||
- Arduino String
|
||||
- null-terminated char array (C-string)
|
||||
- arbitrary binary data (byte array)
|
||||
|
|
@ -57,11 +57,11 @@ int count = 0;
|
|||
void loop() {
|
||||
Serial.print(F("[CC1101] Transmitting packet ... "));
|
||||
|
||||
// you can transmit C-string or Arduino string up to 64 characters long
|
||||
// you can transmit C-string or Arduino string up to 255 characters long
|
||||
String str = "Hello World! #" + String(count++);
|
||||
int state = radio.transmit(str);
|
||||
|
||||
// you can also transmit byte array up to 64 bytes long
|
||||
// you can also transmit byte array up to 255 bytes long with some limitations; https://github.com/jgromes/RadioLib/discussions/1138
|
||||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
|
||||
int state = radio.transmit(byteArr, 8);
|
||||
|
|
@ -72,7 +72,7 @@ void loop() {
|
|||
Serial.println(F("success!"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
|
||||
// the supplied packet was longer than 64 bytes
|
||||
// the supplied packet was longer than 255 bytes
|
||||
Serial.println(F("too long!"));
|
||||
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
This example transmits packets using CC1101 FSK radio module.
|
||||
Once a packet is transmitted, an interrupt is triggered.
|
||||
Each packet contains up to 64 bytes of data, in the form of:
|
||||
Each packet contains up to 255 bytes of data with some limitations (https://github.com/jgromes/RadioLib/discussions/1138), in the form of:
|
||||
- Arduino String
|
||||
- null-terminated char array (C-string)
|
||||
- arbitrary binary data (byte array)
|
||||
|
|
@ -73,10 +73,12 @@ void setup() {
|
|||
Serial.print(F("[CC1101] Sending first packet ... "));
|
||||
|
||||
// you can transmit C-string or Arduino string up to
|
||||
// 64 characters long
|
||||
// 255 characters long
|
||||
transmissionState = radio.startTransmit("Hello World!");
|
||||
|
||||
// you can also transmit byte array up to 64 bytes long
|
||||
// you can also transmit byte array up to 255 bytes long
|
||||
// When transmitting more than 64 bytes startTransmit blocks to refill the FIFO.
|
||||
// Blocking ceases once the last bytes have been placed in the FIFO
|
||||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x56,
|
||||
0x78, 0xAB, 0xCD, 0xEF};
|
||||
|
|
@ -97,10 +99,6 @@ void loop() {
|
|||
// packet was successfully sent
|
||||
Serial.println(F("transmission finished!"));
|
||||
|
||||
// NOTE: when using interrupt-driven transmit method,
|
||||
// it is not possible to automatically measure
|
||||
// transmission data rate using getDataRate()
|
||||
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(transmissionState);
|
||||
|
|
@ -119,11 +117,11 @@ void loop() {
|
|||
Serial.print(F("[CC1101] Sending another packet ... "));
|
||||
|
||||
// you can transmit C-string or Arduino string up to
|
||||
// 64 characters long
|
||||
// 255 characters long
|
||||
String str = "Hello World! #" + String(count++);
|
||||
transmissionState = radio.startTransmit(str);
|
||||
|
||||
// you can also transmit byte array up to 64 bytes long
|
||||
// you can also transmit byte array up to 255 bytes long with limitations https://github.com/jgromes/RadioLib/discussions/1138
|
||||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
|
||||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
|
|
|
|||
|
|
@ -70,13 +70,6 @@ void setup() {
|
|||
while (true) { delay(10); }
|
||||
}
|
||||
|
||||
// GFSK modem on LR11x0 can handle the sync word setting in bits, not just
|
||||
// whole bytes. The value used is left-justified.
|
||||
// This makes same result as radio.setSyncWord(syncWord, 8):
|
||||
state = radio.setSyncBits(syncWord, 64);
|
||||
// This will use 0x012 as sync word (12 bits only):
|
||||
state = radio.setSyncBits(syncWord, 12);
|
||||
|
||||
// GFSK modem allows advanced CRC configuration
|
||||
// Default is CCIT CRC16 (2 bytes, initial 0x1D0F, polynomial 0x1021, inverted)
|
||||
// Set CRC to IBM CRC (2 bytes, initial 0xFFFF, polynomial 0x8005, non-inverted)
|
||||
|
|
|
|||
|
|
@ -57,8 +57,8 @@ void setup() {
|
|||
// the following settings can also
|
||||
// be modified at run-time
|
||||
state = radio.setFrequency(433.5);
|
||||
state = radio.setLrFhssConfig(RADIOLIB_LR11X0_LR_FHSS_BW_1523_4, // bandwidth
|
||||
RADIOLIB_LR11X0_LR_FHSS_CR_1_2, // coding rate
|
||||
state = radio.setLrFhssConfig(RADIOLIB_LRXXXX_LR_FHSS_BW_1523_4, // bandwidth
|
||||
RADIOLIB_LRXXXX_LR_FHSS_CR_1_2, // coding rate
|
||||
3, // header count
|
||||
0x13A); // hopping sequence seed
|
||||
state = radio.setOutputPower(10.0);
|
||||
|
|
|
|||
|
|
@ -101,11 +101,6 @@ void loop() {
|
|||
// the packet was successfully transmitted
|
||||
Serial.println(F("success!"));
|
||||
|
||||
// print measured data rate
|
||||
Serial.print(F("[LR1110] Datarate:\t"));
|
||||
Serial.print(radio.getDataRate());
|
||||
Serial.println(F(" bps"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
|
||||
// the supplied packet was longer than 256 bytes
|
||||
Serial.println(F("too long!"));
|
||||
|
|
|
|||
|
|
@ -126,10 +126,6 @@ void loop() {
|
|||
// packet was successfully sent
|
||||
Serial.println(F("transmission finished!"));
|
||||
|
||||
// NOTE: when using interrupt-driven transmit method,
|
||||
// it is not possible to automatically measure
|
||||
// transmission data rate using getDataRate()
|
||||
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(transmissionState);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
RadioLib LR2021 Blocking Channel Activity Detection Example
|
||||
|
||||
This example uses LR2021 to scan the current LoRa
|
||||
channel and detect ongoing LoRa transmissions.
|
||||
Unlike SX127x CAD, LR2021 can detect any part
|
||||
of LoRa transmission, not just the preamble.
|
||||
|
||||
Using blocking CAD is not recommended, as it will lead
|
||||
to significant amount of timeouts, inefficient use of processor
|
||||
time and can some miss packets!
|
||||
Instead, interrupt CAD is recommended.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr2021---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR2021 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR2021 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or detect the pinout automatically using RadioBoards
|
||||
// https://github.com/radiolib-org/RadioBoards
|
||||
/*
|
||||
#define RADIO_BOARD_AUTO
|
||||
#include <RadioBoards.h>
|
||||
Radio radio = new RadioModule();
|
||||
*/
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// LR2021 allows to use any DIO pin as the interrupt
|
||||
// as an example, we set DIO10 to be the IRQ
|
||||
// this has to be done prior to calling begin()!
|
||||
radio.irqDioNum = 10;
|
||||
|
||||
// initialize LR2021 with default settings
|
||||
Serial.print(F("[LR2021] 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) { delay(10); }
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.print(F("[LR2021] Scanning channel for LoRa transmission ... "));
|
||||
|
||||
// start scanning current channel
|
||||
int state = radio.scanChannel();
|
||||
|
||||
if (state == RADIOLIB_LORA_DETECTED) {
|
||||
// LoRa preamble was detected
|
||||
Serial.println(F("detected!"));
|
||||
|
||||
} else if (state == RADIOLIB_CHANNEL_FREE) {
|
||||
// no preamble was detected, channel is free
|
||||
Serial.println(F("channel is free!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
// wait 100 ms before new scan
|
||||
delay(100);
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
RadioLib LR2021 Channel Activity Detection Example
|
||||
|
||||
This example uses LR2021 to scan the current LoRa
|
||||
channel and detect ongoing LoRa transmissions.
|
||||
Unlike SX127x CAD, LR2021 can detect any part
|
||||
of LoRa transmission, not just the preamble.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr2021---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR2021 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR2021 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or detect the pinout automatically using RadioBoards
|
||||
// https://github.com/radiolib-org/RadioBoards
|
||||
/*
|
||||
#define RADIO_BOARD_AUTO
|
||||
#include <RadioBoards.h>
|
||||
Radio radio = new RadioModule();
|
||||
*/
|
||||
|
||||
// flag to indicate that a packet was detected or CAD timed out
|
||||
volatile bool scanFlag = false;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// something happened, set the flag
|
||||
scanFlag = true;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// LR2021 allows to use any DIO pin as the interrupt
|
||||
// as an example, we set DIO10 to be the IRQ
|
||||
// this has to be done prior to calling begin()!
|
||||
radio.irqDioNum = 10;
|
||||
|
||||
// initialize LR2021 with default settings
|
||||
Serial.print(F("[LR2021] 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) { delay(10); }
|
||||
}
|
||||
|
||||
// set the function that will be called
|
||||
// when LoRa packet or timeout is detected
|
||||
radio.setIrqAction(setFlag);
|
||||
|
||||
// start scanning the channel
|
||||
Serial.print(F("[LR2021] Starting scan for LoRa preamble ... "));
|
||||
state = radio.startChannelScan();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check if the flag is set
|
||||
if(scanFlag) {
|
||||
// reset flag
|
||||
scanFlag = false;
|
||||
|
||||
// check CAD result
|
||||
int state = radio.getChannelScanResult();
|
||||
|
||||
if (state == RADIOLIB_LORA_DETECTED) {
|
||||
// LoRa packet was detected
|
||||
Serial.println(F("[LR2021] Packet detected!"));
|
||||
|
||||
} else if (state == RADIOLIB_CHANNEL_FREE) {
|
||||
// channel is free
|
||||
Serial.println(F("[LR2021] Channel is free!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("[LR2021] Failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
// start scanning the channel again
|
||||
Serial.print(F("[LR2021] Starting scan for LoRa preamble ... "));
|
||||
state = radio.startChannelScan();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
RadioLib LR2021 GFSK Modem Example
|
||||
|
||||
This example shows how to use GFSK modem in LR2021 chips.
|
||||
|
||||
NOTE: The sketch below is just a guide on how to use
|
||||
GFSK modem, so this code should not be run directly!
|
||||
Instead, modify the other examples to use GFSK
|
||||
modem and use the appropriate configuration
|
||||
methods.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr2021---gfsk-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR2021 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR2021 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or detect the pinout automatically using RadioBoards
|
||||
// https://github.com/radiolib-org/RadioBoards
|
||||
/*
|
||||
#define RADIO_BOARD_AUTO
|
||||
#include <RadioBoards.h>
|
||||
Radio radio = new RadioModule();
|
||||
*/
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// LR2021 allows to use any DIO pin as the interrupt
|
||||
// as an example, we set DIO10 to be the IRQ
|
||||
// this has to be done prior to calling begin()!
|
||||
radio.irqDioNum = 10;
|
||||
|
||||
// initialize LR2021 with default settings
|
||||
Serial.print(F("[LR2021] Initializing ... "));
|
||||
int state = radio.beginGFSK();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true) { delay(10); }
|
||||
}
|
||||
|
||||
// if needed, you can switch between any of the modems
|
||||
//
|
||||
// radio.begin() start LoRa modem (and disable GFSK)
|
||||
// radio.beginGFSK() start GFSK modem (and disable LoRa)
|
||||
|
||||
// the following settings can also
|
||||
// be modified at run-time
|
||||
state = radio.setFrequency(433.5);
|
||||
state = radio.setBitRate(100.0);
|
||||
state = radio.setFrequencyDeviation(10.0);
|
||||
state = radio.setRxBandwidth(250.0);
|
||||
state = radio.setOutputPower(10.0);
|
||||
state = radio.setDataShaping(RADIOLIB_SHAPING_1_0);
|
||||
uint8_t syncWord[] = {0x01, 0x23, 0x45, 0x67,
|
||||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
state = radio.setSyncWord(syncWord, 8);
|
||||
if (state != RADIOLIB_ERR_NONE) {
|
||||
Serial.print(F("Unable to set configuration, code "));
|
||||
Serial.println(state);
|
||||
while (true) { delay(10); }
|
||||
}
|
||||
|
||||
// GFSK modem allows advanced CRC configuration
|
||||
// Default is CCITT CRC16 (2 bytes, initial 0x1D0F, polynomial 0x1021, inverted)
|
||||
// Set CRC to IBM CRC (2 bytes, initial 0xFFFF, polynomial 0x8005, non-inverted)
|
||||
state = radio.setCRC(2, 0xFFFF, 0x8005, false);
|
||||
// set CRC length to 0 to disable CRC
|
||||
|
||||
#warning "This sketch is just an API guide! Read the note at line 6."
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// GFSK modem can use the same transmit/receive methods
|
||||
// as the LoRa modem, even their interrupt-driven versions
|
||||
|
||||
// transmit GFSK packet
|
||||
int state = radio.transmit("Hello World!");
|
||||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
|
||||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
int state = radio.transmit(byteArr, 8);
|
||||
*/
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("[LR2021] Packet transmitted successfully!"));
|
||||
} else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
|
||||
Serial.println(F("[LR2021] Packet too long!"));
|
||||
} else if (state == RADIOLIB_ERR_TX_TIMEOUT) {
|
||||
Serial.println(F("[LR2021] Timed out while transmitting!"));
|
||||
} else {
|
||||
Serial.println(F("[LR2021] Failed to transmit packet, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// receive GFSK packet
|
||||
String str;
|
||||
state = radio.receive(str);
|
||||
/*
|
||||
byte byteArr[8];
|
||||
int state = radio.receive(byteArr, 8);
|
||||
*/
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("[LR2021] Received packet!"));
|
||||
Serial.print(F("[LR2021] Data:\t"));
|
||||
Serial.println(str);
|
||||
} else if (state == RADIOLIB_ERR_RX_TIMEOUT) {
|
||||
Serial.println(F("[LR2021] Timed out while waiting for packet!"));
|
||||
} else {
|
||||
Serial.print(F("[LR2021] Failed to receive packet, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// GFSK modem has built-in address filtering system
|
||||
// it can be enabled by setting node address, broadcast
|
||||
// address, or both
|
||||
//
|
||||
// to transmit packet to a particular address,
|
||||
// use the following methods:
|
||||
//
|
||||
// radio.transmit("Hello World!", address);
|
||||
// radio.startTransmit("Hello World!", address);
|
||||
|
||||
// set node address to 0x02
|
||||
state = radio.setNodeAddress(0x02);
|
||||
// set broadcast address to 0xFF
|
||||
state = radio.setBroadcastAddress(0xFF);
|
||||
if (state != RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("[LR2021] Unable to set address filter, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// address filtering can also be disabled
|
||||
// NOTE: calling this method will also erase previously set
|
||||
// node and broadcast address
|
||||
/*
|
||||
state = radio.disableAddressFiltering();
|
||||
if (state != RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("Unable to remove address filter, code "));
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
RadioLib SX126x LR-FHSS Modem Example
|
||||
RadioLib LR2021 LR-FHSS Modem Example
|
||||
|
||||
This example shows how to use LR-FHSS modem in SX126x chips.
|
||||
This example shows how to use LR-FHSS modem in LR2021 chips.
|
||||
This modem can only transmit data, and is not able to receive.
|
||||
|
||||
NOTE: The sketch below is just a guide on how to use
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
methods.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lr-fhss-modem
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr2021---lr-fhss-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
|
|
@ -20,12 +20,12 @@
|
|||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// SX1262 has the following connections:
|
||||
// LR2021 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
SX1262 radio = new Module(10, 2, 3, 9);
|
||||
LR2021 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or detect the pinout automatically using RadioBoards
|
||||
// https://github.com/radiolib-org/RadioBoards
|
||||
|
|
@ -38,8 +38,13 @@ Radio radio = new RadioModule();
|
|||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize SX1262 with default settings
|
||||
Serial.print(F("[SX1262] Initializing ... "));
|
||||
// LR2021 allows to use any DIO pin as the interrupt
|
||||
// as an example, we set DIO10 to be the IRQ
|
||||
// this has to be done prior to calling begin()!
|
||||
radio.irqDioNum = 10;
|
||||
|
||||
// initialize LR2021 with default settings
|
||||
Serial.print(F("[LR2021] Initializing ... "));
|
||||
int state = radio.beginLRFHSS();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
|
|
@ -57,8 +62,8 @@ void setup() {
|
|||
// the following settings can also
|
||||
// be modified at run-time
|
||||
state = radio.setFrequency(433.5);
|
||||
state = radio.setLrFhssConfig(RADIOLIB_SX126X_LR_FHSS_BW_1523_4, // bandwidth
|
||||
RADIOLIB_SX126X_LR_FHSS_CR_1_2, // coding rate
|
||||
state = radio.setLrFhssConfig(RADIOLIB_LRXXXX_LR_FHSS_BW_1523_4, // bandwidth
|
||||
RADIOLIB_LRXXXX_LR_FHSS_CR_1_2, // coding rate
|
||||
3, // header count
|
||||
0x13A); // hopping sequence seed
|
||||
state = radio.setOutputPower(10.0);
|
||||
|
|
@ -83,13 +88,13 @@ void loop() {
|
|||
int state = radio.transmit(byteArr, 8);
|
||||
*/
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("[SX1262] Packet transmitted successfully!"));
|
||||
Serial.println(F("[LR2021] Packet transmitted successfully!"));
|
||||
} else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
|
||||
Serial.println(F("[SX1262] Packet too long!"));
|
||||
Serial.println(F("[LR2021] Packet too long!"));
|
||||
} else if (state == RADIOLIB_ERR_TX_TIMEOUT) {
|
||||
Serial.println(F("[SX1262] Timed out while transmitting!"));
|
||||
Serial.println(F("[LR2021] Timed out while transmitting!"));
|
||||
} else {
|
||||
Serial.println(F("[SX1262] Failed to transmit packet, code "));
|
||||
Serial.println(F("[LR2021] Failed to transmit packet, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
155
lib/RadioLib/examples/LR2021/LR2021_PingPong/LR2021_PingPong.ino
Normal file
155
lib/RadioLib/examples/LR2021/LR2021_PingPong/LR2021_PingPong.ino
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
RadioLib LR2021 Ping-Pong Example
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr2021---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// uncomment the following only on one
|
||||
// of the nodes to initiate the pings
|
||||
//#define INITIATING_NODE
|
||||
|
||||
// LR2021 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR2021 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or detect the pinout automatically using RadioBoards
|
||||
// https://github.com/radiolib-org/RadioBoards
|
||||
/*
|
||||
#define RADIO_BOARD_AUTO
|
||||
#include <RadioBoards.h>
|
||||
Radio radio = new RadioModule();
|
||||
*/
|
||||
|
||||
// save transmission states between loops
|
||||
int transmissionState = RADIOLIB_ERR_NONE;
|
||||
|
||||
// flag to indicate transmission or reception state
|
||||
bool transmitFlag = false;
|
||||
|
||||
// flag to indicate that a packet was sent or received
|
||||
volatile bool operationDone = false;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is transmitted or received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// we sent or received a packet, set the flag
|
||||
operationDone = true;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// LR2021 allows to use any DIO pin as the interrupt
|
||||
// as an example, we set DIO10 to be the IRQ
|
||||
// this has to be done prior to calling begin()!
|
||||
radio.irqDioNum = 10;
|
||||
|
||||
// initialize LR2021 with default settings
|
||||
Serial.print(F("[LR2021] 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) { delay(10); }
|
||||
}
|
||||
|
||||
// set the function that will be called
|
||||
// when new packet is received
|
||||
radio.setIrqAction(setFlag);
|
||||
|
||||
#if defined(INITIATING_NODE)
|
||||
// send the first packet on this node
|
||||
Serial.print(F("[LR2021] Sending first packet ... "));
|
||||
transmissionState = radio.startTransmit("Hello World!");
|
||||
transmitFlag = true;
|
||||
#else
|
||||
// start listening for LoRa packets on this node
|
||||
Serial.print(F("[LR2021] Starting to listen ... "));
|
||||
state = radio.startReceive();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true) { delay(10); }
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check if the previous operation finished
|
||||
if(operationDone) {
|
||||
// reset flag
|
||||
operationDone = false;
|
||||
|
||||
if(transmitFlag) {
|
||||
// the previous operation was transmission, listen for response
|
||||
// print the result
|
||||
if (transmissionState == RADIOLIB_ERR_NONE) {
|
||||
// packet was successfully sent
|
||||
Serial.println(F("transmission finished!"));
|
||||
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(transmissionState);
|
||||
|
||||
}
|
||||
|
||||
// listen for response
|
||||
radio.startReceive();
|
||||
transmitFlag = false;
|
||||
|
||||
} else {
|
||||
// the previous operation was reception
|
||||
// print data and send another packet
|
||||
String str;
|
||||
int state = radio.readData(str);
|
||||
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
// packet was successfully received
|
||||
Serial.println(F("[LR2021] Received packet!"));
|
||||
|
||||
// print data of the packet
|
||||
Serial.print(F("[LR2021] Data:\t\t"));
|
||||
Serial.println(str);
|
||||
|
||||
// print RSSI (Received Signal Strength Indicator)
|
||||
Serial.print(F("[LR2021] RSSI:\t\t"));
|
||||
Serial.print(radio.getRSSI());
|
||||
Serial.println(F(" dBm"));
|
||||
|
||||
// print SNR (Signal-to-Noise Ratio)
|
||||
Serial.print(F("[LR2021] SNR:\t\t"));
|
||||
Serial.print(radio.getSNR());
|
||||
Serial.println(F(" dB"));
|
||||
|
||||
}
|
||||
|
||||
// wait a second before transmitting again
|
||||
delay(1000);
|
||||
|
||||
// send another one
|
||||
Serial.print(F("[LR2021] Sending another packet ... "));
|
||||
transmissionState = radio.startTransmit("Hello World!");
|
||||
transmitFlag = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
RadioLib LR2021 Blocking Receive Example
|
||||
|
||||
This example listens for LoRa transmissions using LR2021 Lora modules.
|
||||
To successfully receive data, the following settings have to be the same
|
||||
on both transmitter and receiver:
|
||||
- carrier frequency
|
||||
- bandwidth
|
||||
- spreading factor
|
||||
- coding rate
|
||||
- sync word
|
||||
- preamble length
|
||||
|
||||
Using blocking receive is not recommended, as it will lead
|
||||
to significant amount of timeouts, inefficient use of processor
|
||||
time and can some miss packets!
|
||||
Instead, interrupt receive is recommended.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr2021---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR2021 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR2021 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or detect the pinout automatically using RadioBoards
|
||||
// https://github.com/radiolib-org/RadioBoards
|
||||
/*
|
||||
#define RADIO_BOARD_AUTO
|
||||
#include <RadioBoards.h>
|
||||
Radio radio = new RadioModule();
|
||||
*/
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// LR2021 allows to use any DIO pin as the interrupt
|
||||
// as an example, we set DIO10 to be the IRQ
|
||||
// this has to be done prior to calling begin()!
|
||||
radio.irqDioNum = 10;
|
||||
|
||||
// initialize LR2021 with default settings
|
||||
Serial.print(F("[LR2021] 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) { delay(10); }
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.print(F("[LR2021] Waiting for incoming transmission ... "));
|
||||
|
||||
// you can receive data as an Arduino String
|
||||
String str;
|
||||
int state = radio.receive(str);
|
||||
|
||||
// you can also receive data as byte array
|
||||
/*
|
||||
byte byteArr[8];
|
||||
int state = radio.receive(byteArr, 8);
|
||||
*/
|
||||
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
// packet was successfully received
|
||||
Serial.println(F("success!"));
|
||||
|
||||
// print the data of the packet
|
||||
Serial.print(F("[LR2021] Data:\t\t"));
|
||||
Serial.println(str);
|
||||
|
||||
// print the RSSI (Received Signal Strength Indicator)
|
||||
// of the last received packet
|
||||
Serial.print(F("[LR2021] RSSI:\t\t"));
|
||||
Serial.print(radio.getRSSI());
|
||||
Serial.println(F(" dBm"));
|
||||
|
||||
// print the SNR (Signal-to-Noise Ratio)
|
||||
// of the last received packet
|
||||
Serial.print(F("[LR2021] SNR:\t\t"));
|
||||
Serial.print(radio.getSNR());
|
||||
Serial.println(F(" dB"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_RX_TIMEOUT) {
|
||||
// timeout occurred while waiting for a packet
|
||||
Serial.println(F("timeout!"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_CRC_MISMATCH) {
|
||||
// packet was received, but is malformed
|
||||
Serial.println(F("CRC error!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
RadioLib LR2021 Receive with Interrupts Example
|
||||
|
||||
This example listens for LoRa transmissions and tries to
|
||||
receive them. Once a packet is received, an interrupt is
|
||||
triggered. To successfully receive data, the following
|
||||
settings have to be the same on both transmitter
|
||||
and receiver:
|
||||
- carrier frequency
|
||||
- bandwidth
|
||||
- spreading factor
|
||||
- coding rate
|
||||
- sync word
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr2021---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR2021 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR2021 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or detect the pinout automatically using RadioBoards
|
||||
// https://github.com/radiolib-org/RadioBoards
|
||||
/*
|
||||
#define RADIO_BOARD_AUTO
|
||||
#include <RadioBoards.h>
|
||||
Radio radio = new RadioModule();
|
||||
*/
|
||||
|
||||
// flag to indicate that a packet was received
|
||||
volatile bool receivedFlag = false;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// we got a packet, set the flag
|
||||
receivedFlag = true;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// LR2021 allows to use any DIO pin as the interrupt
|
||||
// as an example, we set DIO10 to be the IRQ
|
||||
// this has to be done prior to calling begin()!
|
||||
radio.irqDioNum = 10;
|
||||
|
||||
// initialize LR2021 with default settings
|
||||
Serial.print(F("[LR2021] 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) { delay(10); }
|
||||
}
|
||||
|
||||
// set the function that will be called
|
||||
// when new packet is received
|
||||
radio.setPacketReceivedAction(setFlag);
|
||||
|
||||
// start listening for LoRa packets
|
||||
Serial.print(F("[LR2021] Starting to listen ... "));
|
||||
state = radio.startReceive();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true) { delay(10); }
|
||||
}
|
||||
|
||||
// if needed, 'listen' mode can be disabled by calling
|
||||
// any of the following methods:
|
||||
//
|
||||
// radio.standby()
|
||||
// radio.sleep()
|
||||
// radio.transmit();
|
||||
// radio.receive();
|
||||
// radio.scanChannel();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check if the flag is set
|
||||
if(receivedFlag) {
|
||||
// reset flag
|
||||
receivedFlag = false;
|
||||
|
||||
// you can read received data as an Arduino String
|
||||
String str;
|
||||
int state = radio.readData(str);
|
||||
|
||||
// you can also read received data as byte array
|
||||
/*
|
||||
byte byteArr[8];
|
||||
int numBytes = radio.getPacketLength();
|
||||
int state = radio.readData(byteArr, numBytes);
|
||||
*/
|
||||
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
// packet was successfully received
|
||||
Serial.println(F("[LR2021] Received packet!"));
|
||||
|
||||
// print data of the packet
|
||||
Serial.print(F("[LR2021] Data:\t\t"));
|
||||
Serial.println(str);
|
||||
|
||||
// print RSSI (Received Signal Strength Indicator)
|
||||
Serial.print(F("[LR2021] RSSI:\t\t"));
|
||||
Serial.print(radio.getRSSI());
|
||||
Serial.println(F(" dBm"));
|
||||
|
||||
// print SNR (Signal-to-Noise Ratio)
|
||||
Serial.print(F("[LR2021] SNR:\t\t"));
|
||||
Serial.print(radio.getSNR());
|
||||
Serial.println(F(" dB"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_CRC_MISMATCH) {
|
||||
// packet was received, but is malformed
|
||||
Serial.println(F("CRC error!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
RadioLib LR2021 Receive Multi-SF Example
|
||||
|
||||
This example listens for LoRa transmissions with different
|
||||
spreading factors and tries to receive them.
|
||||
Once a packet is received, an interrupt is triggered.
|
||||
|
||||
There are the following limits on configuration of multi-SF
|
||||
(or side-detect) reception:
|
||||
* In Rx mode, all side-detector spreading factors must be higher
|
||||
than the primary one (configured via begin or setSpreadingFactor).
|
||||
* For CAD mode, the above condition is inverted,
|
||||
all side-detector spreading factors must be smaller.
|
||||
* All packets to be detected/received must have the same header type
|
||||
(implicit or explicit).
|
||||
* If bandwidth is higher than 500 kHz,
|
||||
at most 2 side detectors are allowed.
|
||||
* If the primary spreading factor is 10, 11 or 12,
|
||||
at most 2 side detectors are allowed.
|
||||
* All spreading factors must be different.
|
||||
* The difference between maximum and minimum spreading factor used
|
||||
must be less than or equal to 4.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr2021---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR2021 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR2021 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or detect the pinout automatically using RadioBoards
|
||||
// https://github.com/radiolib-org/RadioBoards
|
||||
/*
|
||||
#define RADIO_BOARD_AUTO
|
||||
#include <RadioBoards.h>
|
||||
Radio radio = new RadioModule();
|
||||
*/
|
||||
|
||||
// flag to indicate that a packet was received
|
||||
volatile bool receivedFlag = false;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// we got a packet, set the flag
|
||||
receivedFlag = true;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// LR2021 allows to use any DIO pin as the interrupt
|
||||
// as an example, we set DIO10 to be the IRQ
|
||||
// this has to be done prior to calling begin()!
|
||||
radio.irqDioNum = 10;
|
||||
|
||||
// initialize LR2021 with default settings
|
||||
Serial.print(F("[LR2021] 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) { delay(10); }
|
||||
}
|
||||
|
||||
// prepare array of side detector configuration structures
|
||||
// for spreading factors 10 - 12
|
||||
// as the default spreading factor is 9, this satisfies
|
||||
// the conditions listed at the top of this example
|
||||
// this is just an example; you can also set different
|
||||
// sync words, IQ inversions and low data-rate optimization
|
||||
// depending on the types of transmitters you expect
|
||||
const struct LR2021LoRaSideDetector_t sideDet[3] = {
|
||||
{ .sf = 10, .ldro = false, .invertIQ = false,
|
||||
.syncWord = RADIOLIB_LR2021_LORA_SYNC_WORD_PRIVATE },
|
||||
{ .sf = 11, .ldro = true, .invertIQ = false,
|
||||
.syncWord = RADIOLIB_LR2021_LORA_SYNC_WORD_PRIVATE },
|
||||
{ .sf = 12, .ldro = true, .invertIQ = false,
|
||||
.syncWord = RADIOLIB_LR2021_LORA_SYNC_WORD_PRIVATE },
|
||||
};
|
||||
Serial.print(F("[LR2021] Setting side detector configuration ... "));
|
||||
state = radio.setSideDetector(sideDet, 3);
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true) { delay(10); }
|
||||
}
|
||||
|
||||
// set the function that will be called
|
||||
// when new packet is received
|
||||
radio.setPacketReceivedAction(setFlag);
|
||||
|
||||
// start listening for LoRa packets
|
||||
Serial.print(F("[LR2021] Starting to listen ... "));
|
||||
state = radio.startReceive();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true) { delay(10); }
|
||||
}
|
||||
|
||||
// if needed, 'listen' mode can be disabled by calling
|
||||
// any of the following methods:
|
||||
//
|
||||
// radio.standby()
|
||||
// radio.sleep()
|
||||
// radio.transmit();
|
||||
// radio.receive();
|
||||
// radio.scanChannel();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check if the flag is set
|
||||
if(receivedFlag) {
|
||||
// reset flag
|
||||
receivedFlag = false;
|
||||
|
||||
// you can read received data as an Arduino String
|
||||
String str;
|
||||
int state = radio.readData(str);
|
||||
|
||||
// you can also read received data as byte array
|
||||
/*
|
||||
byte byteArr[8];
|
||||
int numBytes = radio.getPacketLength();
|
||||
int state = radio.readData(byteArr, numBytes);
|
||||
*/
|
||||
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
// packet was successfully received
|
||||
Serial.println(F("[LR2021] Received packet!"));
|
||||
|
||||
// print data of the packet
|
||||
Serial.print(F("[LR2021] Data:\t\t"));
|
||||
Serial.println(str);
|
||||
|
||||
// print RSSI (Received Signal Strength Indicator)
|
||||
Serial.print(F("[LR2021] RSSI:\t\t"));
|
||||
Serial.print(radio.getRSSI());
|
||||
Serial.println(F(" dBm"));
|
||||
|
||||
// print SNR (Signal-to-Noise Ratio)
|
||||
Serial.print(F("[LR2021] SNR:\t\t"));
|
||||
Serial.print(radio.getSNR());
|
||||
Serial.println(F(" dB"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_CRC_MISMATCH) {
|
||||
// packet was received, but is malformed
|
||||
Serial.println(F("CRC error!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
RadioLib LR2021 Blocking Transmit Example
|
||||
|
||||
This example transmits packets using LR2021 LoRa radio module.
|
||||
Each packet contains up to 256 bytes of data, in the form of:
|
||||
- Arduino String
|
||||
- null-terminated char array (C-string)
|
||||
- arbitrary binary data (byte array)
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr2021---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR2021 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR2021 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or detect the pinout automatically using RadioBoards
|
||||
// https://github.com/radiolib-org/RadioBoards
|
||||
/*
|
||||
#define RADIO_BOARD_AUTO
|
||||
#include <RadioBoards.h>
|
||||
Radio radio = new RadioModule();
|
||||
*/
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// LR2021 allows to use any DIO pin as the interrupt
|
||||
// as an example, we set DIO10 to be the IRQ
|
||||
// this has to be done prior to calling begin()!
|
||||
radio.irqDioNum = 10;
|
||||
|
||||
// initialize LR2021 with default settings
|
||||
Serial.print(F("[LR2021] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
delay(1000);
|
||||
while (true) { delay(10); }
|
||||
}
|
||||
}
|
||||
|
||||
// counter to keep track of transmitted packets
|
||||
int count = 0;
|
||||
|
||||
void loop() {
|
||||
Serial.print(F("[LR2021] Transmitting packet ... "));
|
||||
|
||||
// you can transmit C-string or Arduino string up to
|
||||
// 256 characters long
|
||||
// NOTE: transmit() is a blocking method!
|
||||
// See example LR11x0_Transmit_Interrupt for details
|
||||
// on non-blocking transmission method.
|
||||
String str = "Hello World! #" + String(count++);
|
||||
int state = radio.transmit(str);
|
||||
|
||||
// you can also transmit byte array up to 256 bytes long
|
||||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x56, 0x78, 0xAB, 0xCD, 0xEF};
|
||||
int state = radio.transmit(byteArr, 8);
|
||||
*/
|
||||
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
// the packet was successfully transmitted
|
||||
Serial.println(F("success!"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
|
||||
// the supplied packet was longer than 256 bytes
|
||||
Serial.println(F("too long!"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_TX_TIMEOUT) {
|
||||
// timeout occurred while transmitting packet
|
||||
Serial.println(F("timeout!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
// wait for a second before transmitting again
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
RadioLib LR2021 Transmit with Interrupts Example
|
||||
|
||||
This example transmits LoRa packets with one second delays
|
||||
between them. Each packet contains up to 256 bytes
|
||||
of data, in the form of:
|
||||
- Arduino String
|
||||
- null-terminated char array (C-string)
|
||||
- arbitrary binary data (byte array)
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr2021---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR2021 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR2021 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or detect the pinout automatically using RadioBoards
|
||||
// https://github.com/radiolib-org/RadioBoards
|
||||
/*
|
||||
#define RADIO_BOARD_AUTO
|
||||
#include <RadioBoards.h>
|
||||
Radio radio = new RadioModule();
|
||||
*/
|
||||
|
||||
// save transmission state between loops
|
||||
int transmissionState = RADIOLIB_ERR_NONE;
|
||||
|
||||
// flag to indicate that a packet was sent
|
||||
volatile bool transmittedFlag = false;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is transmitted by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// we sent a packet, set the flag
|
||||
transmittedFlag = true;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// LR2021 allows to use any DIO pin as the interrupt
|
||||
// as an example, we set DIO10 to be the IRQ
|
||||
// this has to be done prior to calling begin()!
|
||||
radio.irqDioNum = 10;
|
||||
|
||||
// initialize LR2021 with default settings
|
||||
Serial.print(F("[LR2021] 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) { delay(10); }
|
||||
}
|
||||
|
||||
// set the function that will be called
|
||||
// when packet transmission is finished
|
||||
radio.setPacketSentAction(setFlag);
|
||||
|
||||
// start transmitting the first packet
|
||||
Serial.print(F("[LR2021] Sending first packet ... "));
|
||||
|
||||
// you can transmit C-string or Arduino string up to
|
||||
// 256 characters long
|
||||
transmissionState = radio.startTransmit("Hello World!");
|
||||
|
||||
// you can also transmit byte array up to 256 bytes long
|
||||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
|
||||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
state = radio.startTransmit(byteArr, 8);
|
||||
*/
|
||||
}
|
||||
|
||||
// counter to keep track of transmitted packets
|
||||
int count = 0;
|
||||
|
||||
void loop() {
|
||||
// check if the previous transmission finished
|
||||
if(transmittedFlag) {
|
||||
// reset flag
|
||||
transmittedFlag = false;
|
||||
|
||||
if (transmissionState == RADIOLIB_ERR_NONE) {
|
||||
// packet was successfully sent
|
||||
Serial.println(F("transmission finished!"));
|
||||
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(transmissionState);
|
||||
|
||||
}
|
||||
|
||||
// clean up after transmission is finished
|
||||
// this will ensure transmitter is disabled,
|
||||
// RF switch is powered down etc.
|
||||
radio.finishTransmit();
|
||||
|
||||
// wait a second before transmitting again
|
||||
delay(1000);
|
||||
|
||||
// send another one
|
||||
Serial.print(F("[LR2021] Sending another packet ... "));
|
||||
|
||||
// you can transmit C-string or Arduino string up to
|
||||
// 256 characters long
|
||||
String str = "Hello World! #" + String(count++);
|
||||
transmissionState = radio.startTransmit(str);
|
||||
|
||||
// you can also transmit byte array up to 256 bytes long
|
||||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
|
||||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
transmissionState = radio.startTransmit(byteArr, 8);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
@ -41,9 +41,11 @@ const uint32_t uplinkIntervalSeconds = 5UL * 60UL; // minutes x seconds
|
|||
// 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, AS923_2, AS923_3, AS923_4, IN865, KR920, CN500
|
||||
// regional choices: EU868, US915, AU915, AS923, AS923_2, AS923_3, AS923_4, IN865, KR920, CN470
|
||||
const LoRaWANBand_t Region = EU868;
|
||||
const uint8_t subBand = 0; // For US915, change this to 2, otherwise leave on 0
|
||||
|
||||
// subband choice: for US915/AU915 set to 2, for CN470 set to 1, otherwise leave on 0
|
||||
const uint8_t subBand = 0;
|
||||
|
||||
// ============================================================================
|
||||
// Below is to support the sketch - only make changes if the notes say so ...
|
||||
|
|
@ -70,8 +72,8 @@ String stateDecode(const int16_t result) {
|
|||
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_MIC_MISMATCH:
|
||||
return "ERR_MIC_MISMATCH";
|
||||
case RADIOLIB_ERR_INVALID_BANDWIDTH:
|
||||
return "ERR_INVALID_BANDWIDTH";
|
||||
case RADIOLIB_ERR_INVALID_SPREADING_FACTOR:
|
||||
|
|
@ -102,10 +104,6 @@ String stateDecode(const int16_t result) {
|
|||
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:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
RadioLib LoRaWAN Class C Example
|
||||
|
||||
This example joins a LoRaWAN network and switches to Class C.
|
||||
Note that a confirmed uplink with a confirming downlink is
|
||||
required for the switch to Class C to complete. This example
|
||||
assumes that coverage is good enough to receive the downlink
|
||||
at once. It is up to you to handle the situation if coverage
|
||||
is worse.
|
||||
|
||||
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("Initialise the radio"));
|
||||
int16_t state = radio.begin();
|
||||
debug(state != RADIOLIB_ERR_NONE, F("Initialise radio failed"), state, true);
|
||||
|
||||
// Setup the OTAA session information
|
||||
state = node.beginOTAA(joinEUI, devEUI, nwkKey, appKey);
|
||||
debug(state != RADIOLIB_ERR_NONE, F("Initialise node failed"), state, true);
|
||||
|
||||
Serial.println(F("Join ('login') the LoRaWAN Network"));
|
||||
state = node.activateOTAA();
|
||||
debug(state != RADIOLIB_LORAWAN_NEW_SESSION, F("Join failed"), state, true);
|
||||
|
||||
// switch class
|
||||
node.setClass(RADIOLIB_LORAWAN_CLASS_C);
|
||||
|
||||
// read the note at the top about this first confirmed uplink
|
||||
const char* payload = "C";
|
||||
Serial.println(F("Sending a confirmed uplink"));
|
||||
state = node.sendReceive(payload, 1, true);
|
||||
debug(state <= 0, F("No downlink received"), state, true);
|
||||
|
||||
Serial.println(F("Ready!\n"));
|
||||
}
|
||||
|
||||
uint32_t lastUplink = 0;
|
||||
|
||||
void loop() {
|
||||
uint8_t downlinkPayload[255];
|
||||
size_t downlinkLen = 0;
|
||||
LoRaWANEvent_t downlinkEvent;
|
||||
|
||||
// check if a Class C downlink is ready for processing
|
||||
// tip: internally, this just checks a boolean;
|
||||
// it does not poll the radio over SPI.
|
||||
// tip: you are not required to continuously call
|
||||
// this function; you can do other stuff in between.
|
||||
// however, a downlink may be overwritten if you
|
||||
// don't call this function in time for the previous one.
|
||||
int16_t state = node.getDownlinkClassC(downlinkPayload, &downlinkLen, &downlinkEvent);
|
||||
if(state > 0) {
|
||||
Serial.println(F("Received a Class C downlink!"));
|
||||
// Did we get a downlink with data for us
|
||||
if(downlinkLen > 0) {
|
||||
Serial.println(F("Downlink data: "));
|
||||
arrayDump(downlinkPayload, downlinkLen);
|
||||
}
|
||||
|
||||
// print extra information about the event
|
||||
Serial.println(F("[LoRaWAN] Event information:"));
|
||||
Serial.print(F("[LoRaWAN] Datarate:\t"));
|
||||
Serial.println(downlinkEvent.datarate);
|
||||
Serial.print(F("[LoRaWAN] Frequency:\t"));
|
||||
Serial.print(downlinkEvent.freq, 3);
|
||||
Serial.println(F(" MHz"));
|
||||
Serial.print(F("[LoRaWAN] Frame count:\t"));
|
||||
Serial.println(downlinkEvent.fCnt);
|
||||
Serial.print(F("[LoRaWAN] Port:\t\t"));
|
||||
Serial.println(downlinkEvent.fPort);
|
||||
Serial.println(F(" ms"));
|
||||
Serial.print(F("[LoRaWAN] Rx window: \t"));
|
||||
Serial.println(state);
|
||||
Serial.print(F("[LoRaWAN] Cast:\t\t"));
|
||||
Serial.println(downlinkEvent.multicast ? "Multi" : "Uni");
|
||||
}
|
||||
|
||||
// if less than uplinkIntervalSeconds have elapsed since previous uplink,
|
||||
// stop and go back to the top of the loop()
|
||||
if(millis() - lastUplink < uplinkIntervalSeconds * 1000) {
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload));
|
||||
debug(state < RADIOLIB_ERR_NONE, F("Error in sendReceive"), state, false);
|
||||
|
||||
// Check if a downlink was received
|
||||
// (state 0 = no downlink, state 1/2/3 = downlink in window Rx1/Rx2/RxC)
|
||||
if(state > 0) {
|
||||
Serial.println(F("Received a downlink"));
|
||||
} else {
|
||||
Serial.println(F("No downlink received"));
|
||||
}
|
||||
|
||||
Serial.print(F("Next uplink in "));
|
||||
Serial.print(uplinkIntervalSeconds);
|
||||
Serial.println(F(" seconds\n"));
|
||||
|
||||
// set timestamp of last uplink
|
||||
lastUplink = millis();
|
||||
}
|
||||
141
lib/RadioLib/examples/LoRaWAN/LoRaWAN_Class_C/config.h
Normal file
141
lib/RadioLib/examples/LoRaWAN/LoRaWAN_Class_C/config.h
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
#ifndef _RADIOLIB_EX_LORAWAN_CONFIG_H
|
||||
#define _RADIOLIB_EX_LORAWAN_CONFIG_H
|
||||
|
||||
#include <RadioLib.h>
|
||||
|
||||
// first you have to set your radio model and pin configuration
|
||||
// this is provided just as a default example
|
||||
SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
// if you have RadioBoards (https://github.com/radiolib-org/RadioBoards)
|
||||
// and are using one of the supported boards, you can do the following:
|
||||
/*
|
||||
#define RADIO_BOARD_AUTO
|
||||
#include <RadioBoards.h>
|
||||
|
||||
Radio radio = new RadioModule();
|
||||
*/
|
||||
|
||||
// how often to send an uplink - consider legal & FUP constraints - see notes
|
||||
const uint32_t uplinkIntervalSeconds = 1UL * 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, AS923_2, AS923_3, AS923_4, IN865, KR920, 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 ...
|
||||
|
||||
// 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);
|
||||
|
||||
// result code to text - these are error codes that can be raised when using LoRaWAN
|
||||
// however, RadioLib has many more - see https://jgromes.github.io/RadioLib/group__status__codes.html for a complete list
|
||||
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_MIC_MISMATCH:
|
||||
return "ERR_MIC_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_DWELL_TIME_EXCEEDED:
|
||||
return "RADIOLIB_ERR_DWELL_TIME_EXCEEDED";
|
||||
case RADIOLIB_ERR_CHECKSUM_MISMATCH:
|
||||
return "RADIOLIB_ERR_CHECKSUM_MISMATCH";
|
||||
case RADIOLIB_ERR_NO_JOIN_ACCEPT:
|
||||
return "RADIOLIB_ERR_NO_JOIN_ACCEPT";
|
||||
case RADIOLIB_LORAWAN_SESSION_RESTORED:
|
||||
return "RADIOLIB_LORAWAN_SESSION_RESTORED";
|
||||
case RADIOLIB_LORAWAN_NEW_SESSION:
|
||||
return "RADIOLIB_LORAWAN_NEW_SESSION";
|
||||
case RADIOLIB_ERR_NONCES_DISCARDED:
|
||||
return "RADIOLIB_ERR_NONCES_DISCARDED";
|
||||
case RADIOLIB_ERR_SESSION_DISCARDED:
|
||||
return "RADIOLIB_ERR_SESSION_DISCARDED";
|
||||
}
|
||||
return "See https://jgromes.github.io/RadioLib/group__status__codes.html";
|
||||
}
|
||||
|
||||
// helper function to display any issues
|
||||
void debug(bool failed, const __FlashStringHelper* message, int state, bool halt) {
|
||||
if(failed) {
|
||||
Serial.print(message);
|
||||
Serial.print(" - ");
|
||||
Serial.print(stateDecode(state));
|
||||
Serial.print(" (");
|
||||
Serial.print(state);
|
||||
Serial.println(")");
|
||||
while(halt) { delay(1); }
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
RadioLib LoRaWAN Multicast Example
|
||||
|
||||
This example joins a LoRaWAN network and starts a
|
||||
Multicast session (only Multicast over Class C is implemented).
|
||||
You should refer to the network's documentation on how
|
||||
to create a Multicast group (or device).
|
||||
Note that you can switch the device to Class C as well
|
||||
to receive Unicast downlinks. In this case, you must
|
||||
use the downlink event details to discern whether a
|
||||
downlink belongs to the Unicast or Multicast session.
|
||||
|
||||
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("Initialise the radio"));
|
||||
int16_t state = radio.begin();
|
||||
debug(state != RADIOLIB_ERR_NONE, F("Initialise radio failed"), state, true);
|
||||
|
||||
// Setup the OTAA session information
|
||||
state = node.beginOTAA(joinEUI, devEUI, nwkKey, appKey);
|
||||
debug(state != RADIOLIB_ERR_NONE, F("Initialise node failed"), state, true);
|
||||
|
||||
Serial.println(F("Join ('login') the LoRaWAN Network"));
|
||||
state = node.activateOTAA();
|
||||
debug(state != RADIOLIB_LORAWAN_NEW_SESSION, F("Join failed"), state, true);
|
||||
|
||||
// Start a Multicast session over Class C
|
||||
// (this will automatically perform a switch to Class C for Multicast)
|
||||
node.startMulticastSession(RADIOLIB_LORAWAN_CLASS_C, mcDevAddr, mcAppSKey, mcNwkSKey);
|
||||
|
||||
Serial.println(F("Ready!\n"));
|
||||
}
|
||||
|
||||
uint32_t lastUplink = 0;
|
||||
|
||||
void loop() {
|
||||
uint8_t downlinkPayload[255];
|
||||
size_t downlinkLen = 0;
|
||||
LoRaWANEvent_t downlinkEvent;
|
||||
|
||||
// check if a Class C downlink is ready for processing
|
||||
// tip: internally, this just checks a boolean;
|
||||
// it does not poll the radio over SPI.
|
||||
// tip: you are not required to continuously call
|
||||
// this function; you can do other stuff in between.
|
||||
// however, a downlink may be overwritten if you
|
||||
// don't call this function in time for the previous one.
|
||||
int16_t state = node.getDownlinkClassC(downlinkPayload, &downlinkLen, &downlinkEvent);
|
||||
if(state > 0) {
|
||||
Serial.println(F("Received a Class C downlink!"));
|
||||
// Did we get a downlink with data for us
|
||||
if(downlinkLen > 0) {
|
||||
Serial.println(F("Downlink data: "));
|
||||
arrayDump(downlinkPayload, downlinkLen);
|
||||
}
|
||||
|
||||
// print extra information about the event
|
||||
Serial.println(F("[LoRaWAN] Event information:"));
|
||||
Serial.print(F("[LoRaWAN] Datarate:\t"));
|
||||
Serial.println(downlinkEvent.datarate);
|
||||
Serial.print(F("[LoRaWAN] Frequency:\t"));
|
||||
Serial.print(downlinkEvent.freq, 3);
|
||||
Serial.println(F(" MHz"));
|
||||
Serial.print(F("[LoRaWAN] Frame count:\t"));
|
||||
Serial.println(downlinkEvent.fCnt);
|
||||
Serial.print(F("[LoRaWAN] Port:\t\t"));
|
||||
Serial.println(downlinkEvent.fPort);
|
||||
Serial.println(F(" ms"));
|
||||
Serial.print(F("[LoRaWAN] Rx window: \t"));
|
||||
Serial.println(state);
|
||||
Serial.print(F("[LoRaWAN] Cast:\t\t"));
|
||||
Serial.println(downlinkEvent.multicast ? "Multi" : "Uni");
|
||||
}
|
||||
|
||||
// if less than uplinkIntervalSeconds have elapsed since previous uplink,
|
||||
// stop and go back to the top of the loop()
|
||||
if(millis() - lastUplink < uplinkIntervalSeconds * 1000) {
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload));
|
||||
debug(state < RADIOLIB_ERR_NONE, F("Error in sendReceive"), state, false);
|
||||
|
||||
// Check if a downlink was received
|
||||
// (state 0 = no downlink, state 1/2/3 = downlink in window Rx1/Rx2/RxC)
|
||||
if(state > 0) {
|
||||
Serial.println(F("Received a downlink"));
|
||||
} else {
|
||||
Serial.println(F("No downlink received"));
|
||||
}
|
||||
|
||||
Serial.print(F("Next uplink in "));
|
||||
Serial.print(uplinkIntervalSeconds);
|
||||
Serial.println(F(" seconds\n"));
|
||||
|
||||
// set timestamp of last uplink
|
||||
lastUplink = millis();
|
||||
}
|
||||
154
lib/RadioLib/examples/LoRaWAN/LoRaWAN_Multicast/config.h
Normal file
154
lib/RadioLib/examples/LoRaWAN/LoRaWAN_Multicast/config.h
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
#ifndef _RADIOLIB_EX_LORAWAN_CONFIG_H
|
||||
#define _RADIOLIB_EX_LORAWAN_CONFIG_H
|
||||
|
||||
#include <RadioLib.h>
|
||||
|
||||
// first you have to set your radio model and pin configuration
|
||||
// this is provided just as a default example
|
||||
SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
// if you have RadioBoards (https://github.com/radiolib-org/RadioBoards)
|
||||
// and are using one of the supported boards, you can do the following:
|
||||
/*
|
||||
#define RADIO_BOARD_AUTO
|
||||
#include <RadioBoards.h>
|
||||
|
||||
Radio radio = new RadioModule();
|
||||
*/
|
||||
|
||||
// how often to send an uplink - consider legal & FUP constraints - see notes
|
||||
const uint32_t uplinkIntervalSeconds = 1UL * 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
|
||||
|
||||
#ifndef RADIOLIB_LORAWAN_MC_DEV_ADDR // Replace with your Multicast Device Address
|
||||
#define RADIOLIB_LORAWAN_MC_DEV_ADDR 0x---------------
|
||||
#endif
|
||||
#ifndef RADIOLIB_LORAWAN_MC_APP_SKEY // Replace with your Multicast App SKey
|
||||
#define RADIOLIB_LORAWAN_MC_APP_SKEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
|
||||
#endif
|
||||
#ifndef RADIOLIB_LORAWAN_MC_NWK_SKEY // Put your Multicast Nwk SKey here
|
||||
#define RADIOLIB_LORAWAN_MC_NWK_SKEY 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, AS923_2, AS923_3, AS923_4, IN865, KR920, 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 ...
|
||||
|
||||
// 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 };
|
||||
uint32_t mcDevAddr = RADIOLIB_LORAWAN_MC_DEV_ADDR;
|
||||
uint8_t mcAppSKey[] = { RADIOLIB_LORAWAN_MC_APP_SKEY };
|
||||
uint8_t mcNwkSKey[] = { RADIOLIB_LORAWAN_MC_NWK_SKEY };
|
||||
|
||||
// create the LoRaWAN node
|
||||
LoRaWANNode node(&radio, &Region, subBand);
|
||||
|
||||
// result code to text - these are error codes that can be raised when using LoRaWAN
|
||||
// however, RadioLib has many more - see https://jgromes.github.io/RadioLib/group__status__codes.html for a complete list
|
||||
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_MIC_MISMATCH:
|
||||
return "ERR_MIC_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_DWELL_TIME_EXCEEDED:
|
||||
return "RADIOLIB_ERR_DWELL_TIME_EXCEEDED";
|
||||
case RADIOLIB_ERR_CHECKSUM_MISMATCH:
|
||||
return "RADIOLIB_ERR_CHECKSUM_MISMATCH";
|
||||
case RADIOLIB_ERR_NO_JOIN_ACCEPT:
|
||||
return "RADIOLIB_ERR_NO_JOIN_ACCEPT";
|
||||
case RADIOLIB_LORAWAN_SESSION_RESTORED:
|
||||
return "RADIOLIB_LORAWAN_SESSION_RESTORED";
|
||||
case RADIOLIB_LORAWAN_NEW_SESSION:
|
||||
return "RADIOLIB_LORAWAN_NEW_SESSION";
|
||||
case RADIOLIB_ERR_NONCES_DISCARDED:
|
||||
return "RADIOLIB_ERR_NONCES_DISCARDED";
|
||||
case RADIOLIB_ERR_SESSION_DISCARDED:
|
||||
return "RADIOLIB_ERR_SESSION_DISCARDED";
|
||||
}
|
||||
return "See https://jgromes.github.io/RadioLib/group__status__codes.html";
|
||||
}
|
||||
|
||||
// helper function to display any issues
|
||||
void debug(bool failed, const __FlashStringHelper* message, int state, bool halt) {
|
||||
if(failed) {
|
||||
Serial.print(message);
|
||||
Serial.print(" - ");
|
||||
Serial.print(stateDecode(state));
|
||||
Serial.print(" (");
|
||||
Serial.print(state);
|
||||
Serial.println(")");
|
||||
while(halt) { delay(1); }
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -44,15 +44,18 @@ void setup() {
|
|||
Serial.println(F("Initialise the radio"));
|
||||
state = radio.begin();
|
||||
debug(state != RADIOLIB_ERR_NONE, F("Initialise radio failed"), state, true);
|
||||
|
||||
// Override the default join rate
|
||||
uint8_t joinDR = 4;
|
||||
|
||||
|
||||
// Optionally provide a custom sleep function - see config.h
|
||||
//node.setSleepFunction(customDelay);
|
||||
|
||||
// Setup the OTAA session information
|
||||
node.beginOTAA(joinEUI, devEUI, nwkKey, appKey);
|
||||
|
||||
// Override the default join rate
|
||||
node.setDatarate(4);
|
||||
|
||||
Serial.println(F("Join ('login') the LoRaWAN Network"));
|
||||
state = node.activateOTAA(joinDR);
|
||||
state = node.activateOTAA();
|
||||
debug(state != RADIOLIB_LORAWAN_NEW_SESSION, F("Join failed"), state, true);
|
||||
|
||||
// Print the DevAddr
|
||||
|
|
@ -175,13 +178,14 @@ void loop() {
|
|||
Serial.println(gwCnt);
|
||||
}
|
||||
|
||||
uint32_t networkTime = 0;
|
||||
uint8_t fracSecond = 0;
|
||||
if(node.getMacDeviceTimeAns(&networkTime, &fracSecond, true) == RADIOLIB_ERR_NONE) {
|
||||
uint32_t timestamp = 0;
|
||||
uint16_t milliseconds = 0;
|
||||
if(node.getMacDeviceTimeAns(×tamp, &milliseconds, true) == RADIOLIB_ERR_NONE) {
|
||||
Serial.print(F("[LoRaWAN] DeviceTime Unix:\t"));
|
||||
Serial.println(networkTime);
|
||||
Serial.print(F("[LoRaWAN] DeviceTime second:\t1/"));
|
||||
Serial.println(fracSecond);
|
||||
Serial.println(timestamp);
|
||||
Serial.print(F("[LoRaWAN] DeviceTime frac:\t"));
|
||||
Serial.print(milliseconds);
|
||||
Serial.println(F(" ms"));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -37,9 +37,11 @@ const uint32_t uplinkIntervalSeconds = 5UL * 60UL; // minutes x seconds
|
|||
// 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, AS923_2, AS923_3, AS923_4, IN865, KR920, CN500
|
||||
// regional choices: EU868, US915, AU915, AS923, AS923_2, AS923_3, AS923_4, IN865, KR920, CN470
|
||||
const LoRaWANBand_t Region = EU868;
|
||||
const uint8_t subBand = 0; // For US915, change this to 2, otherwise leave on 0
|
||||
|
||||
// subband choice: for US915/AU915 set to 2, for CN470 set to 1, otherwise leave on 0
|
||||
const uint8_t subBand = 0;
|
||||
|
||||
// ============================================================================
|
||||
// Below is to support the sketch - only make changes if the notes say so ...
|
||||
|
|
@ -65,8 +67,8 @@ String stateDecode(const int16_t result) {
|
|||
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_MIC_MISMATCH:
|
||||
return "ERR_MIC_MISMATCH";
|
||||
case RADIOLIB_ERR_INVALID_BANDWIDTH:
|
||||
return "ERR_INVALID_BANDWIDTH";
|
||||
case RADIOLIB_ERR_INVALID_SPREADING_FACTOR:
|
||||
|
|
@ -97,10 +99,6 @@ String stateDecode(const int16_t result) {
|
|||
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:
|
||||
|
|
@ -142,4 +140,19 @@ void arrayDump(uint8_t *buffer, uint16_t len) {
|
|||
Serial.println();
|
||||
}
|
||||
|
||||
// Custom delay function:
|
||||
// Communication over LoRaWAN includes a lot of delays.
|
||||
// By default, RadioLib will use the Arduino delay() function,
|
||||
// which will waste a lot of power. However, you can put your
|
||||
// microcontroller to sleep instead by customizing the function below,
|
||||
// and providing it to RadioLib via "node.setSleepFunction".
|
||||
// NOTE: You ahve to ensure that this function is timed precisely, and
|
||||
// does actually wait for the amount of time specified!
|
||||
// Failure to do so will result in missed downlinks or failed join!
|
||||
void customDelay(RadioLibTime_t ms) {
|
||||
// this is just an example, so we use the Arduino delay() function,
|
||||
// but you can put your microcontroller to sleep here
|
||||
::delay(ms);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -37,9 +37,11 @@ const uint32_t uplinkIntervalSeconds = 5UL * 60UL; // minutes x seconds
|
|||
// 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, AS923_2, AS923_3, AS923_4, IN865, KR920, CN500
|
||||
// regional choices: EU868, US915, AU915, AS923, AS923_2, AS923_3, AS923_4, IN865, KR920, CN470
|
||||
const LoRaWANBand_t Region = EU868;
|
||||
const uint8_t subBand = 0; // For US915, change this to 2, otherwise leave on 0
|
||||
|
||||
// subband choice: for US915/AU915 set to 2, for CN470 set to 1, otherwise leave on 0
|
||||
const uint8_t subBand = 0;
|
||||
|
||||
// ============================================================================
|
||||
// Below is to support the sketch - only make changes if the notes say so ...
|
||||
|
|
@ -65,8 +67,8 @@ String stateDecode(const int16_t result) {
|
|||
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_MIC_MISMATCH:
|
||||
return "ERR_MIC_MISMATCH";
|
||||
case RADIOLIB_ERR_INVALID_BANDWIDTH:
|
||||
return "ERR_INVALID_BANDWIDTH";
|
||||
case RADIOLIB_ERR_INVALID_SPREADING_FACTOR:
|
||||
|
|
@ -97,10 +99,6 @@ String stateDecode(const int16_t result) {
|
|||
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:
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
|
||||
|
||||
# RadioLib LoRaWAN on TTN starter script
|
||||
|
||||
## Welcome
|
||||
|
||||
These notes are for someone who has successfully created a few sketches for their Arduino based device but is starting out with LoRaWAN. You don't have to be a C coding ninja but some familarity with C and procedural programming is assumed. The absolutely simplest way to get started is to buy some known good hardware that's all done for you so you can concentrate on the code & configuration.
|
||||
These notes are for someone who has successfully created a few sketches for their Arduino based device but is starting out with LoRaWAN. You don't have to be a C++ coding ninja but some familarity with C++ and procedural programming is assumed. The absolutely simplest way to get started is to buy some known good hardware that's all done for you so you can concentrate on the code & configuration.
|
||||
|
||||
|
||||
## Introduction
|
||||
|
|
@ -18,7 +16,7 @@ For questions about using RadioLib there is the discussions section (https://git
|
|||
|
||||
## Register & setup on TTN
|
||||
|
||||
This sketch isn't particularly aimed at The Things Stack (TTS) but you can get a free Sandbox account and the following instructions are for that. Helium does not support LoRaWAN v1.1 which is the version implemented by RadioLib. Chirpstack & other LoRaWAN Network Server (LNS) stacks have not yet been tried so YMMV.
|
||||
This sketch isn't particularly aimed at The Things Stack (TTS) but you can get a free Sandbox account and the following instructions are for that. Chirpstack works just as well, but the buttons and labels may have different names. We discourage the use of Helium as it does not support LoRaWAN v1.1 and has some other odd limitations. Other LoRaWAN Network Servers (LNS) have not been tested by the developers, so YMMV.
|
||||
|
||||
Why no screen shots? TTS is a web based app, one that you will need to become familiar with and we will need to direct you to some of the less obvious parts. So much better that you learn the layouts in concept than slavishly follow screen shots that can & will go stale.
|
||||
|
||||
|
|
@ -52,13 +50,13 @@ You are making your own device using a third party LoRaWAN stack so there will n
|
|||
|
||||
Choose the Frequency plan appropriate for your region. Consider that almost all countries have laws relating to what frequencies you use so don't get creative. For Europe please use the recommended option. For other regions use the entry marked 'used by TTN'.
|
||||
|
||||
Choose LoRaWAN 1.1.0 - the last one in the list - the latest specfication. RadioLib uses RP001 Regional Parameters 1.1 revision B.
|
||||
Choose LoRaWAN 1.1.0 - the last one in the list - the latest specfication. RadioLib uses RP002 Regional Parameters 1.0.4.
|
||||
|
||||
At this point you will be asked for your JoinEUI. As this is a DIY device and we are using RadioLib, you can use all zero's as recommended by The LoRa Alliance TR007 Technical Recommendations document. Once you've put in all zeros and clicked confirm you will be asked for a DevEUI, AppKey and NwkKey. It is preferable to have the console generate them so they are properly formatted.
|
||||
|
||||
Your End device ID can be changed to make the device more identifiable. Something related to your hardware helps - like devicename-01. The you can click the blue 'Register device'.
|
||||
Your End device ID can be changed to make the device more identifiable. Something related to your hardware helps - like `devicename-01`. The you can click the blue 'Register device'.
|
||||
|
||||
When many sensors are big deployed, a device is registered, batteries put in, it joins and gets on with sending data for the next few years. For development purposes we need to turn off one of the security settings so that you can join & uplink out of the normal sequence that a device in the field would do.
|
||||
When retail sensors are being deployed, a device is registered, batteries put in, it joins and gets on with sending data for the next few years. For development purposes however we need to turn off one of the security settings so that you can join & uplink out of the normal sequence that a device in the field would do.
|
||||
|
||||
Click on General Settings, scroll down to Join settings, click the Expand button, scroll down and click the 'Resets join nonces' option. You will see a warning about replay attacks which is entirely proper & correct. If anyone eavesdropping in your area on your LoRa transmissions could fake a join and send uplinks from their device but only if they happened to find out your AppKey & NwkKey which is kept securely on the TTN servers and is never transmitted over the air, so they'd also have to login to your account, which is protected by your password.
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,238 @@
|
|||
#include <Arduino.h>
|
||||
#include <RadioLib.h>
|
||||
// #include <RadioBoards.h>
|
||||
|
||||
#warning "The variables below must match your main code. Please check your radio type!"
|
||||
extern SX1278 radio; // this can be any LoRaWAN-compatible type (e.g. SX1262)
|
||||
extern LoRaWANNode node;
|
||||
extern uint32_t periodicity;
|
||||
extern bool isConfirmed;
|
||||
extern bool reply;
|
||||
extern uint8_t dataUp[255];
|
||||
extern size_t lenUp;
|
||||
extern uint8_t fPort;
|
||||
|
||||
#define RADIOLIB_LORAWAN_TS009_PACKAGE_VERSION (0x00)
|
||||
#define RADIOLIB_LORAWAN_TS009_DUT_RESET (0x01)
|
||||
#define RADIOLIB_LORAWAN_TS009_DUT_JOIN (0x02)
|
||||
#define RADIOLIB_LORAWAN_TS009_SWITCH_CLASS (0x03)
|
||||
#define RADIOLIB_LORAWAN_TS009_ADR_BIT_CHANGE (0x04)
|
||||
#define RADIOLIB_LORAWAN_TS009_REGIONAL_DUTY_CYCLE (0x05)
|
||||
#define RADIOLIB_LORAWAN_TS009_TX_PERIODICITY_CHANGE (0x06)
|
||||
#define RADIOLIB_LORAWAN_TS009_TX_FRAMES_CTRL (0x07)
|
||||
#define RADIOLIB_LORAWAN_TS009_ECHO_PAYLOAD (0x08)
|
||||
#define RADIOLIB_LORAWAN_TS009_RX_APP_CNT (0x09)
|
||||
#define RADIOLIB_LORAWAN_TS009_RX_APP_CNT_RESET (0x0A)
|
||||
#define RADIOLIB_LORAWAN_TS009_LINK_CHECK (0x20)
|
||||
#define RADIOLIB_LORAWAN_TS009_DEVICE_TIME (0x21)
|
||||
#define RADIOLIB_LORAWAN_TS009_PING_SLOT_INFO (0x22)
|
||||
#define RADIOLIB_LORAWAN_TS009_TX_CW (0x7D)
|
||||
#define RADIOLIB_LORAWAN_TS009_DUT_FPORT224_DISABLE (0x7E)
|
||||
#define RADIOLIB_LORAWAN_TS009_DUT_VERSIONS (0x7F)
|
||||
|
||||
/*!
|
||||
\brief This function implements the TS009 specification.
|
||||
To enable this package, add this to your setup:
|
||||
`node.addAppPackage(RADIOLIB_LORAWAN_PACKAGE_TS009, handleTS009)`
|
||||
Make sure that all `extern` variables are handled in your user code!
|
||||
*/
|
||||
void handleTS009(uint8_t* dataDown, size_t lenDown) {
|
||||
if(lenDown == 0 || dataDown == NULL) {
|
||||
return;
|
||||
}
|
||||
RADIOLIB_DEBUG_PRINTLN("CID = %02x, len = %d", dataDown[0], lenDown - 1);
|
||||
|
||||
switch(dataDown[0]) {
|
||||
case(RADIOLIB_LORAWAN_TS009_PACKAGE_VERSION): {
|
||||
lenUp = 3;
|
||||
dataUp[1] = 5; // PackageIdentifier
|
||||
dataUp[2] = 1; // PackageVersion
|
||||
fPort = RADIOLIB_LORAWAN_FPORT_TS009;
|
||||
RADIOLIB_DEBUG_PRINTLN("PackageIdentifier: %d, PackageVersion: %d", dataUp[1], dataUp[2]);
|
||||
|
||||
reply = true;
|
||||
} break;
|
||||
|
||||
case(RADIOLIB_LORAWAN_TS009_DUT_RESET): {
|
||||
RADIOLIB_DEBUG_PRINTLN("Restarting...");
|
||||
|
||||
#warning "Please implement this reset function yourself!"
|
||||
|
||||
// the function to reset the MCU is platform-dependent
|
||||
// for ESP32 for example, this would be:
|
||||
// ESP.restart();
|
||||
|
||||
reply = false;
|
||||
} break;
|
||||
|
||||
case(RADIOLIB_LORAWAN_TS009_DUT_JOIN): {
|
||||
RADIOLIB_DEBUG_PRINTLN("Reverting to Join state");
|
||||
node.clearSession();
|
||||
|
||||
reply = false;
|
||||
} break;
|
||||
|
||||
case(RADIOLIB_LORAWAN_TS009_SWITCH_CLASS): {
|
||||
uint8_t classType = dataDown[1];
|
||||
node.setClass(classType);
|
||||
RADIOLIB_DEBUG_PRINTLN("Switching to class: %s", classType == 0 ? "A" : (classType == 1 ? "B" : "C"));
|
||||
|
||||
reply = false;
|
||||
} break;
|
||||
|
||||
case(RADIOLIB_LORAWAN_TS009_ADR_BIT_CHANGE): {
|
||||
bool adr = (bool)dataDown[1];
|
||||
node.setADR(adr);
|
||||
RADIOLIB_DEBUG_PRINTLN("ADR: %d", adr);
|
||||
|
||||
reply = false;
|
||||
} break;
|
||||
|
||||
case(RADIOLIB_LORAWAN_TS009_REGIONAL_DUTY_CYCLE): {
|
||||
bool dutycycle = (bool)dataDown[1];
|
||||
node.setDutyCycle(dutycycle, 36000);
|
||||
RADIOLIB_DEBUG_PRINTLN("Dutycycle: %d", dutycycle);
|
||||
|
||||
reply = false;
|
||||
} break;
|
||||
|
||||
case(RADIOLIB_LORAWAN_TS009_TX_PERIODICITY_CHANGE): {
|
||||
uint32_t defaultIntervalSecs = 30;
|
||||
uint32_t intervals[11] = {defaultIntervalSecs, 5, 10, 20, 30, 40, 50, 60, 120, 240, 480};
|
||||
periodicity = intervals[dataDown[1]];
|
||||
|
||||
RADIOLIB_DEBUG_PRINTLN("Tx Periodicity: %d", periodicity);
|
||||
|
||||
reply = false;
|
||||
} break;
|
||||
|
||||
case(RADIOLIB_LORAWAN_TS009_TX_FRAMES_CTRL): {
|
||||
switch(dataDown[1]) {
|
||||
case(0):
|
||||
// no change
|
||||
// isConfirmed = isConfirmed;
|
||||
break;
|
||||
case(1):
|
||||
isConfirmed = false;
|
||||
break;
|
||||
case(2):
|
||||
isConfirmed = true;
|
||||
break;
|
||||
}
|
||||
RADIOLIB_DEBUG_PRINTLN("Confirmed: %d", isConfirmed);
|
||||
|
||||
reply = false;
|
||||
} break;
|
||||
|
||||
case(RADIOLIB_LORAWAN_TS009_ECHO_PAYLOAD): {
|
||||
lenUp = lenDown;
|
||||
for (size_t i = 1; i < lenDown; i++) {
|
||||
dataUp[i] = dataDown[i] + 1;
|
||||
}
|
||||
fPort = RADIOLIB_LORAWAN_FPORT_TS009;
|
||||
RADIOLIB_DEBUG_PRINTLN("Echoing payload");
|
||||
|
||||
reply = true;
|
||||
} break;
|
||||
|
||||
case(RADIOLIB_LORAWAN_TS009_RX_APP_CNT): {
|
||||
lenUp = 3;
|
||||
uint16_t aFcntDown16 = (uint16_t)node.getAFCntDown();
|
||||
dataUp[1] = aFcntDown16 & 0xFF;
|
||||
dataUp[2] = aFcntDown16 >> 8;
|
||||
fPort = RADIOLIB_LORAWAN_FPORT_TS009;
|
||||
RADIOLIB_DEBUG_PRINTLN("aFCntDown16: %d", aFcntDown16);
|
||||
|
||||
reply = true;
|
||||
} break;
|
||||
|
||||
case(RADIOLIB_LORAWAN_TS009_RX_APP_CNT_RESET): {
|
||||
RADIOLIB_DEBUG_PRINTLN("Resetting Application Frame count");
|
||||
RADIOLIB_DEBUG_PRINTLN("WARNING: not implemented - never used in tests!");
|
||||
|
||||
reply = false;
|
||||
} break;
|
||||
|
||||
case(RADIOLIB_LORAWAN_TS009_LINK_CHECK): {
|
||||
lenUp = 0;
|
||||
fPort = RADIOLIB_LORAWAN_FPORT_MAC_COMMAND;
|
||||
node.sendMacCommandReq(RADIOLIB_LORAWAN_MAC_LINK_CHECK);
|
||||
RADIOLIB_DEBUG_PRINTLN("Requesting LinkCheck");
|
||||
|
||||
reply = true;
|
||||
} break;
|
||||
|
||||
case(RADIOLIB_LORAWAN_TS009_DEVICE_TIME): {
|
||||
lenUp = 0;
|
||||
fPort = RADIOLIB_LORAWAN_FPORT_MAC_COMMAND;
|
||||
node.sendMacCommandReq(RADIOLIB_LORAWAN_MAC_DEVICE_TIME);
|
||||
RADIOLIB_DEBUG_PRINTLN("Requesting DeviceTime");
|
||||
|
||||
reply = true;
|
||||
} break;
|
||||
|
||||
case(RADIOLIB_LORAWAN_TS009_PING_SLOT_INFO): {
|
||||
lenUp = 0;
|
||||
RADIOLIB_DEBUG_PRINTLN("Requesting PingSlotInfo not implemented");
|
||||
// send PingSlotInfo MAC command which is not implemented
|
||||
reply = false;
|
||||
} break;
|
||||
|
||||
case(RADIOLIB_LORAWAN_TS009_TX_CW): {
|
||||
uint16_t timeout = ((uint16_t)dataDown[2] << 8) | (uint16_t)dataDown[1];
|
||||
uint32_t freqRaw = ((uint32_t)dataDown[5] << 16) | ((uint32_t)dataDown[4] << 8) | ((uint32_t)dataDown[3]);
|
||||
float freq = (float)freqRaw/10000.0;
|
||||
uint8_t txPower = dataDown[6];
|
||||
RADIOLIB_DEBUG_PRINTLN("Continuous wave: %7.3f MHz, %d dBm, %d s", freq, txPower, timeout);
|
||||
radio.setFrequency(freq);
|
||||
radio.setOutputPower(txPower);
|
||||
radio.transmitDirect();
|
||||
delay(timeout * 1000);
|
||||
radio.standby();
|
||||
|
||||
reply = false;
|
||||
} break;
|
||||
|
||||
case(RADIOLIB_LORAWAN_TS009_DUT_FPORT224_DISABLE): {
|
||||
RADIOLIB_DEBUG_PRINTLN("Disabling FPort 224");
|
||||
node.removePackage(RADIOLIB_LORAWAN_PACKAGE_TS009);
|
||||
|
||||
reply = false;
|
||||
} break;
|
||||
|
||||
case(RADIOLIB_LORAWAN_TS009_DUT_VERSIONS): {
|
||||
lenUp = 13;
|
||||
// firmware version - this is RadioLib's version as an example
|
||||
dataUp[1] = RADIOLIB_VERSION_MAJOR;
|
||||
dataUp[2] = RADIOLIB_VERSION_MINOR;
|
||||
dataUp[3] = RADIOLIB_VERSION_PATCH;
|
||||
dataUp[4] = RADIOLIB_VERSION_EXTRA;
|
||||
|
||||
// lorawan version
|
||||
dataUp[5] = 1;
|
||||
#if (LORAWAN_VERSION == 1)
|
||||
dataUp[6] = 1;
|
||||
dataUp[7] = 0;
|
||||
#else
|
||||
dataUp[6] = 0;
|
||||
dataUp[7] = 4;
|
||||
#endif
|
||||
dataUp[8] = 0;
|
||||
|
||||
// regional parameters version
|
||||
dataUp[9] = 1;
|
||||
dataUp[10] = 0;
|
||||
dataUp[11] = 4;
|
||||
dataUp[12] = 0;
|
||||
fPort = RADIOLIB_LORAWAN_FPORT_TS009;
|
||||
RADIOLIB_DEBUG_PRINTLN("Requested DUT versions");
|
||||
|
||||
reply = true;
|
||||
} break;
|
||||
}
|
||||
|
||||
// if we must reply, copy the command ID into the uplink buffer
|
||||
if(reply) {
|
||||
dataUp[0] = dataDown[0];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
RadioLib LoRaWAN Packages Example
|
||||
|
||||
This example shows how the TS009 package can be used
|
||||
and is the sketch used for passing pre-certification testing.
|
||||
This scheme can also be used for other future packages
|
||||
such as TS003/004/005/006/007 which, combined, build FUOTA.
|
||||
|
||||
PLEASE NOTE that this is a highly customized sketch with
|
||||
settings that likely violate laws & regulations, and it is
|
||||
intended to be used with RF blocking materials and attenuators.
|
||||
|
||||
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 <Arduino.h>
|
||||
#include <RadioLib.h>
|
||||
|
||||
#include "LoRaWAN_TS009.h"
|
||||
#include "config.h"
|
||||
#include "lorawan.h"
|
||||
|
||||
uint32_t periodicity = uplinkIntervalSeconds;
|
||||
bool isConfirmed = false;
|
||||
bool reply = false;
|
||||
|
||||
uint8_t fPort = 1;
|
||||
uint8_t dataUp[255];
|
||||
uint8_t dataDown[255];
|
||||
size_t lenUp = 0;
|
||||
size_t lenDown = 0;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(3000);
|
||||
|
||||
Serial.print(F("Initialise 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);
|
||||
}
|
||||
|
||||
// setup, restore and join the network
|
||||
lwBegin();
|
||||
lwRestore();
|
||||
lwActivate();
|
||||
|
||||
// add TS009 package
|
||||
node.addAppPackage(RADIOLIB_LORAWAN_PACKAGE_TS009, handleTS009);
|
||||
|
||||
// LCTT (TS009 testing) has a huge timing problem on the JoinAccept Rx2 window...
|
||||
node.scanGuard = 100;
|
||||
|
||||
// these settings are totally not recommended
|
||||
// but unfortunately they are the default settings for TS009 testing
|
||||
node.setDutyCycle(false);
|
||||
node.setADR(false);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
while(!node.isActivated()) {
|
||||
lwActivate();
|
||||
// this 5s interval is way too short for normal use!
|
||||
// but you'd be waiting around for long minutes during TS009 testing otherwise
|
||||
if(!node.isActivated()) {
|
||||
delay(5000);
|
||||
}
|
||||
node.setDutyCycle(false);
|
||||
}
|
||||
|
||||
int state = RADIOLIB_ERR_NONE;
|
||||
LoRaWANEvent_t eventUp;
|
||||
LoRaWANEvent_t eventDown;
|
||||
|
||||
uint32_t start = millis();
|
||||
|
||||
Serial.println("--------------------");
|
||||
Serial.println("[LoRaWAN] Sending uplink packet ... ");
|
||||
if (!reply) {
|
||||
memset(dataUp, 0, 255);
|
||||
lenUp = 4;
|
||||
fPort = 1;
|
||||
sprintf((char*)dataUp, "%04lu", node.getFCntUp());
|
||||
state = node.sendReceive(dataUp, lenUp, fPort, dataDown, &lenDown, isConfirmed, &eventUp, &eventDown);
|
||||
} else {
|
||||
reply = false;
|
||||
state = node.sendReceive(dataUp, lenUp, fPort, dataDown, &lenDown, isConfirmed, &eventUp, &eventDown);
|
||||
}
|
||||
|
||||
if(state >= RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("[LoRaWAN] success!"));
|
||||
}
|
||||
|
||||
if(state > 0) {
|
||||
// print data of the packet (if there are any)
|
||||
Serial.print(F("[LoRaWAN] Data:\t\t"));
|
||||
if(lenDown > 0) {
|
||||
arrayDump(dataDown, lenDown);
|
||||
} else {
|
||||
Serial.println(F("<MAC / package commands only>"));
|
||||
}
|
||||
|
||||
Serial.print(F("[LoRaWAN] FPort:\t"));
|
||||
Serial.print(eventDown.fPort);
|
||||
|
||||
// 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"));
|
||||
|
||||
uint8_t margin = 0;
|
||||
uint8_t gwCnt = 0;
|
||||
if(node.getMacLinkCheckAns(&margin, &gwCnt) == RADIOLIB_ERR_NONE) {
|
||||
Serial.print(F("[LoRaWAN] LinkCheck margin:\t"));
|
||||
Serial.println(margin);
|
||||
Serial.print(F("[LoRaWAN] LinkCheck count:\t"));
|
||||
Serial.println(gwCnt);
|
||||
}
|
||||
|
||||
uint32_t timestamp = 0;
|
||||
uint16_t milliseconds = 0;
|
||||
if(node.getMacDeviceTimeAns(×tamp, &milliseconds, true) == RADIOLIB_ERR_NONE) {
|
||||
Serial.print(F("[LoRaWAN] DeviceTime Unix:\t"));
|
||||
Serial.println(timestamp);
|
||||
Serial.print(F("[LoRaWAN] DeviceTime frac:\t"));
|
||||
Serial.print(milliseconds);
|
||||
Serial.println(F(" ms"));
|
||||
}
|
||||
|
||||
} else if(state == 0) {
|
||||
Serial.println(F("No downlink!"));
|
||||
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
uint32_t end = millis();
|
||||
|
||||
uint32_t delayDc = node.timeUntilUplink();
|
||||
uint32_t delayMs = periodicity*1000;
|
||||
if(delayMs > end - start) {
|
||||
delayMs -= (end - start);
|
||||
} else {
|
||||
delayMs = 1;
|
||||
}
|
||||
delayMs += 50;
|
||||
Serial.print(F("Delay: "));
|
||||
Serial.print(max(delayDc, delayMs));
|
||||
Serial.println(F(" ms"));
|
||||
|
||||
// wait before sending another packet
|
||||
delay(max(delayDc, delayMs));
|
||||
}
|
||||
115
lib/RadioLib/examples/LoRaWAN/LoRaWAN_TS_Packages/config.h
Normal file
115
lib/RadioLib/examples/LoRaWAN/LoRaWAN_TS_Packages/config.h
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
|
||||
#include <RadioLib.h>
|
||||
|
||||
// first you have to set your radio model and pin configuration
|
||||
// this is provided just as a default example
|
||||
SX1278 radio = new Module(10, 2, 9, 3);
|
||||
|
||||
// if you have RadioBoards (https://github.com/radiolib-org/RadioBoards)
|
||||
// and are using one of the supported boards, you can do the following:
|
||||
/*
|
||||
#define RADIO_BOARD_AUTO
|
||||
#include <RadioBoards.h>
|
||||
|
||||
Radio radio = new RadioModule();
|
||||
*/
|
||||
|
||||
// how often to send an uplink - consider legal & FUP constraints
|
||||
const uint32_t uplinkIntervalSeconds = 1UL * 60UL; // minutes x seconds
|
||||
|
||||
#define LORAWAN_VERSION (0) // use version 1.LORAWAN_VERSION when joining
|
||||
#define LORAWAN_OTAA (1) // use OTAA (1) or ABP (0)
|
||||
|
||||
#if (LORAWAN_OTAA == 1)
|
||||
// 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
|
||||
|
||||
// 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 };
|
||||
|
||||
#if (LORAWAN_VERSION == 1)
|
||||
#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
|
||||
uint8_t nwkKey[] = { RADIOLIB_LORAWAN_NWK_KEY }; // LW v1.1 only
|
||||
#endif
|
||||
|
||||
#else // ABP
|
||||
|
||||
#ifndef RADIOLIB_LORAWAN_DEV_ADDR // Replace with your DevAddr
|
||||
#define RADIOLIB_LORAWAN_DEV_ADDR 0x------
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
// copy over the keys in to the something that will not compile if incorrectly formatted
|
||||
uint32_t devAddr = RADIOLIB_LORAWAN_DEV_ADDR;
|
||||
uint8_t sNwkSEncKey[] = { RADIOLIB_LORAWAN_NWKSENC_KEY };
|
||||
uint8_t appSKey[] = { RADIOLIB_LORAWAN_APPS_KEY };
|
||||
|
||||
#if (LORAWAN_VERSION == 1)
|
||||
#ifndef RADIOLIB_LORAWAN_FNWKSINT_KEY // Replace with your FNwkSInt Key
|
||||
#define RADIOLIB_LORAWAN_FNWKSINT_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
|
||||
#endif
|
||||
#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
|
||||
uint8_t fNwkSIntKey[] = { RADIOLIB_LORAWAN_FNWKSINT_KEY }; // LW v1.1 only
|
||||
uint8_t sNwkSIntKey[] = { RADIOLIB_LORAWAN_SNWKSINT_KEY }; // LW v1.1 only
|
||||
#endif
|
||||
|
||||
#endif // OTAA/ABP
|
||||
|
||||
// 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 ...
|
||||
|
||||
// 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 = 0; c < len; c++) {
|
||||
char b = buffer[c];
|
||||
if(b < 0x10) { Serial.print('0'); }
|
||||
Serial.print(b, HEX);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
#endif
|
||||
76
lib/RadioLib/examples/LoRaWAN/LoRaWAN_TS_Packages/lorawan.h
Normal file
76
lib/RadioLib/examples/LoRaWAN/LoRaWAN_TS_Packages/lorawan.h
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
#ifndef _LORAWAN_H
|
||||
#define _LORAWAN_H
|
||||
|
||||
#include <RadioLib.h>
|
||||
#include "config.h"
|
||||
|
||||
#warning "You are required to implement persistence here! (ESP32 example provided in comments)"
|
||||
|
||||
// #include <Preferences.h>
|
||||
// Preferences store;
|
||||
// uint8_t LWnonces[RADIOLIB_LORAWAN_NONCES_BUF_SIZE];
|
||||
|
||||
bool lwBegin() {
|
||||
#if (LORAWAN_OTAA == 1)
|
||||
#if (LORAWAN_VERSION == 1)
|
||||
node.beginOTAA(joinEUI, devEUI, nwkKey, appKey);
|
||||
#else
|
||||
node.beginOTAA(joinEUI, devEUI, NULL, appKey);
|
||||
#endif
|
||||
#else
|
||||
#if (LORAWAN_VERSION == 1)
|
||||
node.beginABP(devAddr, fNwkSIntKey, sNwkSIntKey, sNwkSEncKey, appSKey);
|
||||
#else
|
||||
node.beginABP(devAddr, NULL, NULL, sNwkSEncKey, appSKey);
|
||||
#endif
|
||||
#endif
|
||||
return(true);
|
||||
}
|
||||
|
||||
int16_t lwRestore() {
|
||||
int16_t state = RADIOLIB_ERR_UNKNOWN;
|
||||
|
||||
// store.begin("radiolib");
|
||||
// if (store.isKey("nonces")) {
|
||||
// radio.standby();
|
||||
|
||||
// store.getBytes("nonces", LWnonces, RADIOLIB_LORAWAN_NONCES_BUF_SIZE);
|
||||
// state = node.setBufferNonces(LWnonces);
|
||||
// }
|
||||
// store.end();
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
void lwActivate() {
|
||||
int16_t state = RADIOLIB_ERR_NETWORK_NOT_JOINED;
|
||||
Serial.println(F("[LoRaWAN] Attempting network join ... "));
|
||||
|
||||
radio.standby();
|
||||
|
||||
#if (LORAWAN_OTAA == 1)
|
||||
state = node.activateOTAA();
|
||||
#else
|
||||
state = node.activateABP();
|
||||
#endif
|
||||
|
||||
if(state == RADIOLIB_LORAWAN_SESSION_RESTORED) {
|
||||
Serial.println(F("[LoRaWAN] Session restored!"));
|
||||
return;
|
||||
}
|
||||
|
||||
// store.begin("radiolib");
|
||||
// uint8_t *persist = node.getBufferNonces();
|
||||
// store.putBytes("nonces", persist, RADIOLIB_LORAWAN_NONCES_BUF_SIZE);
|
||||
// store.end();
|
||||
|
||||
if(state == RADIOLIB_LORAWAN_NEW_SESSION) {
|
||||
Serial.println(F("[LoRaWAN] Successfully started new session!"));
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.print(F("[LoRaWAN] Failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -3,35 +3,12 @@ RadioLib LoRaWAN examples.
|
|||
|
||||
* [LoRaWAN_Starter](https://github.com/jgromes/RadioLib/tree/master/examples/LoRaWAN/LoRaWAN_Starter): this is the recommended entry point for new users. Please read the [`notes`](https://github.com/jgromes/RadioLib/blob/master/examples/LoRaWAN/LoRaWAN_Starter/notes.md) that come with this example to learn more about LoRaWAN and how to use it in RadioLib!
|
||||
* [LoRaWAN_Reference](https://github.com/jgromes/RadioLib/tree/master/examples/LoRaWAN/LoRaWAN_Reference): this sketch showcases most of the available API for LoRaWAN in RadioLib. Be frightened by the possibilities! It is recommended you have read all the [`notes`](https://github.com/jgromes/RadioLib/blob/master/examples/LoRaWAN/LoRaWAN_Starter/notes.md) for the Starter sketch first, as well as the [Learn section on The Things Network](https://www.thethingsnetwork.org/docs/lorawan/)!
|
||||
* [LoRaWAN_ABP](https://github.com/jgromes/RadioLib/tree/master/examples/LoRaWAN/LoRaWAN_ABP): if you wish to use ABP instead of OTAA (but why?), this example shows how you can do this using RadioLib.
|
||||
* [LoRaWAN_ABP](https://github.com/jgromes/RadioLib/tree/master/examples/LoRaWAN/LoRaWAN_ABP): if you wish to use ABP instead of OTAA, this example shows how you can do this using RadioLib. However, to comply with the specification, the full session must persist through resets and power loss - you would need proper NVM for this. Really, we recommend using OTAA.
|
||||
* [LoRaWAN_Class_C](https://github.com/jgromes/RadioLib/tree/master/examples/LoRaWAN/LoRaWAN_Class_C): this shows how to use Class C on top of Class A. This is useful for continuously-powered devices (no batteries) such as lights. If you deploy multiple similar devices, please use Multicast instead.
|
||||
* [LoRaWAN_Multicast](https://github.com/jgromes/RadioLib/tree/master/examples/LoRaWAN/LoRaWAN_Multicast): a showcase of Multicast over Class C. This is particularly useful for groups of devices such as a series of street lights.
|
||||
|
||||
## LoRaWAN versions & regional parameters
|
||||
RadioLib implements both LoRaWAN Specification 1.1 and 1.0.4. Confusingly, 1.0.4 is newer than 1.1, but 1.1 includes more security checks and as such **LoRaWAN 1.1 is preferred**.
|
||||
The catch is in the Regional Parameters: as RP002 1.0.4 is newer than RP001 1.1, it is more up to date regarding local laws & regulations. Therefore, RadioLib implements 1.0.4 as baseline and 1.1 (revision B) as fallback, and as such **RP002 Regional Parameters 1.0.4 is preferred**.
|
||||
_Note: the CN500 band is implemented as specified in RP001 1.1 revision B, as the RP002 1.0.4 version is much too complex._
|
||||
> [!CAUTION]
|
||||
> These examples are quick wins during development. However, for production devices, you will need to add persistence to your device. See the wiki for more details, or head straight to some [persistence examples](https://github.com/radiolib-org/radiolib-persistence).
|
||||
|
||||
To activate a LoRaWAN 1.1 session, supply all the required keys:
|
||||
```cpp
|
||||
node.beginOTAA(joinEUI, devEUI, nwkKey, appKey);
|
||||
node.beginABP(devAddr, fNwkSIntKey, sNwkSIntKey, nwkSEncKey, appSKey);
|
||||
```
|
||||
|
||||
To activate a LoRaWAN 1.0.4 session, set the keys that are not available to `NULL`:
|
||||
```cpp
|
||||
node.beginOTAA(joinEUI, devEUI, NULL, appKey);
|
||||
node.beginABP(devAddr, NULL, NULL, nwkSEncKey, appSKey);
|
||||
```
|
||||
|
||||
The device doesn't need to know the Regional Parameters version - that is of importance on the console.
|
||||
|
||||
## LoRaWAN persistence
|
||||
> [!WARNING]
|
||||
> These examples do not actually comply with LoRaWAN 1.0.4/1.1: for that, persistent storage is necessary. As the implementation of persistent storage differs between different platforms, these are not given here, but in a separate repository, see below:
|
||||
|
||||
In [this repository](https://github.com/radiolib-org/radiolib-persistence), examples are provided that do comply with the required persistence of certain parameters for LoRaWAN 1.1. Examples are (or will become) available for some of the most popular platforms. **These examples assume you have successfully used the Starter sketch and understood (most of) the accompanying notes!**
|
||||
Currently, examples are available for the following platforms:
|
||||
|
||||
* [LoRaWAN for ESP32](https://github.com/radiolib-org/radiolib-persistence/tree/main/examples/LoRaWAN_ESP32)
|
||||
* [LoRaWAN for ESP8266](https://github.com/radiolib-org/radiolib-persistence/tree/main/examples/LoRaWAN_ESP8266)
|
||||
|
||||
_This list is last updated at 30/03/2024._
|
||||
> [!TIP]
|
||||
> Refer to the [Wiki](https://github.com/jgromes/RadioLib/wiki/LoRaWAN) for guides and information, for example on LoRaWAN versions, registering your device and more.
|
||||
|
|
|
|||
|
|
@ -8,3 +8,4 @@ This example shows how to use RadioLib as ESP-IDF component, without the Arduino
|
|||
* `main/EspHal.h` - RadioLib HAL example implementation
|
||||
* `main/idf_component.yml` - declaration of the RadioLib dependency for this example
|
||||
* `main/main.cpp` - the example source code
|
||||
* `sdkconfig.defaults` - List of preset configuration option values for ESP-IDF. All other options use default values provided by ESP-IDF.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,2 @@
|
|||
# Increase FreeRTOS tick rate to 1000 Hz
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
|
|
@ -20,12 +20,13 @@ add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../../../../RadioLib" "${CMAKE_CUR
|
|||
|
||||
add_executable(${PROJECT_NAME}
|
||||
main.cpp
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../../../RadioLib/src/hal/RPiPico/PicoHal.cpp"
|
||||
)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC RADIOLIB_BUILD_RPI_PICO)
|
||||
|
||||
# Pull in common dependencies
|
||||
target_link_libraries(${PROJECT_NAME} pico_stdlib hardware_spi hardware_gpio hardware_timer pico_multicore hardware_pwm RadioLib)
|
||||
|
||||
|
||||
pico_enable_stdio_usb(${PROJECT_NAME} 1)
|
||||
pico_enable_stdio_uart(${PROJECT_NAME} 0)
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ SX1278 radio = new Module(10, 2, 9, 3);
|
|||
// SX1231: DIO2
|
||||
// CC1101: GDO2
|
||||
// Si443x/RFM2x: GPIO
|
||||
// SX126x/LLCC68: DIO2
|
||||
const int pin = 5;
|
||||
|
||||
// create Pager client instance using the FSK module
|
||||
|
|
|
|||
|
|
@ -93,6 +93,8 @@ void loop() {
|
|||
delay(500);
|
||||
|
||||
// we can also send only a tone
|
||||
state |= pager.sendTone(1234567);
|
||||
delay(500);
|
||||
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
|
|
@ -101,6 +103,6 @@ void loop() {
|
|||
Serial.println(state);
|
||||
}
|
||||
|
||||
// wait for a second before transmitting again
|
||||
// wait for 3 seconds before transmitting again
|
||||
delay(3000);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,10 +113,6 @@ void loop() {
|
|||
// packet was successfully sent
|
||||
Serial.println(F("transmission finished!"));
|
||||
|
||||
// NOTE: when using interrupt-driven transmit method,
|
||||
// it is not possible to automatically measure
|
||||
// transmission data rate using getDataRate()
|
||||
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(transmissionState);
|
||||
|
|
|
|||
|
|
@ -94,11 +94,6 @@ void loop() {
|
|||
// the packet was successfully transmitted
|
||||
Serial.println(F("success!"));
|
||||
|
||||
// print measured data rate
|
||||
Serial.print(F("[STM32WL] Datarate:\t"));
|
||||
Serial.print(radio.getDataRate());
|
||||
Serial.println(F(" bps"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
|
||||
// the supplied packet was longer than 256 bytes
|
||||
Serial.println(F("too long!"));
|
||||
|
|
|
|||
|
|
@ -110,10 +110,6 @@ void loop() {
|
|||
// packet was successfully sent
|
||||
Serial.println(F("transmission finished!"));
|
||||
|
||||
// NOTE: when using interrupt-driven transmit method,
|
||||
// it is not possible to automatically measure
|
||||
// transmission data rate using getDataRate()
|
||||
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(transmissionState);
|
||||
|
|
|
|||
|
|
@ -71,13 +71,6 @@ void setup() {
|
|||
while (true) { delay(10); }
|
||||
}
|
||||
|
||||
// FSK modem on SX126x can handle the sync word setting in bits, not just
|
||||
// whole bytes. The value used is left-justified.
|
||||
// This makes same result as radio.setSyncWord(syncWord, 8):
|
||||
state = radio.setSyncBits(syncWord, 64);
|
||||
// This will use 0x012 as sync word (12 bits only):
|
||||
state = radio.setSyncBits(syncWord, 12);
|
||||
|
||||
// FSK modem allows advanced CRC configuration
|
||||
// Default is CCIT CRC16 (2 bytes, initial 0x1D0F, polynomial 0x1021, inverted)
|
||||
// Set CRC to IBM CRC (2 bytes, initial 0xFFFF, polynomial 0x8005, non-inverted)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
RadioLib SX126x LR-FHSS Modem Example
|
||||
|
||||
This example shows how to use LR-FHSS modem in SX126x chips.
|
||||
This modem can only transmit data, and is not able to receive.
|
||||
|
||||
This example transmits packets using SX1262 LoRa radio module.
|
||||
Each packet contains up to 256 bytes of data, in the form of:
|
||||
- Arduino String
|
||||
- null-terminated char array (C-string)
|
||||
- arbitrary binary data (byte array)
|
||||
|
||||
Other modules from SX126x family can also be used.
|
||||
|
||||
Using blocking transmit is not recommended, as it will lead
|
||||
to inefficient use of processor time!
|
||||
Instead, interrupt transmit is recommended.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lr-fhss-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// SX1262 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
SX1262 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or detect the pinout automatically using RadioBoards
|
||||
// https://github.com/radiolib-org/RadioBoards
|
||||
/*
|
||||
#define RADIO_BOARD_AUTO
|
||||
#include <RadioBoards.h>
|
||||
Radio radio = new RadioModule();
|
||||
*/
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize SX1262 with default settings
|
||||
Serial.print(F("[SX1262] Initializing ... "));
|
||||
int state = radio.beginLRFHSS();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true) { delay(10); }
|
||||
}
|
||||
|
||||
// some modules have an external RF switch
|
||||
// controlled via two pins (RX enable, TX enable)
|
||||
// to enable automatic control of the switch,
|
||||
// call the following method
|
||||
// RX enable: 4
|
||||
// TX enable: 5
|
||||
/*
|
||||
radio.setRfSwitchPins(4, 5);
|
||||
*/
|
||||
}
|
||||
|
||||
// counter to keep track of transmitted packets
|
||||
int count = 0;
|
||||
|
||||
void loop() {
|
||||
// LR-FHSS modem can only transmit!
|
||||
Serial.print(F("[SX1262] Transmitting packet ... "));
|
||||
|
||||
// you can transmit C-string or Arduino string up to
|
||||
// 256 characters long
|
||||
String str = "Hello World! #" + String(count++);
|
||||
int state = radio.transmit(str);
|
||||
|
||||
// you can also transmit byte array up to 256 bytes long
|
||||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x56, 0x78, 0xAB, 0xCD, 0xEF};
|
||||
int state = radio.transmit(byteArr, 8);
|
||||
*/
|
||||
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
// the packet was successfully transmitted
|
||||
Serial.println(F("success!"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
|
||||
// the supplied packet was longer than 256 bytes
|
||||
Serial.println(F("too long!"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_TX_TIMEOUT) {
|
||||
// timeout occurred while transmitting packet
|
||||
Serial.println(F("timeout!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
// wait for a second before transmitting again
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
RadioLib SX126x LR-FHSS Transmit with Interrupts Example
|
||||
|
||||
This example shows how to use LR-FHSS modem in SX126x chips.
|
||||
This modem can only transmit data, and is not able to receive.
|
||||
|
||||
This example transmits packets using SX1262 LoRa radio module.
|
||||
Each packet contains up to 256 bytes of data, in the form of:
|
||||
- Arduino String
|
||||
- null-terminated char array (C-string)
|
||||
- arbitrary binary data (byte array)
|
||||
|
||||
Other modules from SX126x family can also be used.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lr-fhss-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// SX1262 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
SX1262 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or detect the pinout automatically using RadioBoards
|
||||
// https://github.com/radiolib-org/RadioBoards
|
||||
/*
|
||||
#define RADIO_BOARD_AUTO
|
||||
#include <RadioBoards.h>
|
||||
Radio radio = new RadioModule();
|
||||
*/
|
||||
|
||||
// save transmission state between loops
|
||||
int transmissionState = RADIOLIB_ERR_NONE;
|
||||
|
||||
// flag to indicate that a packet was sent
|
||||
// or a frequency hop is needed
|
||||
volatile bool flag = false;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is transmitted by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// we sent a packet or need to hop, set the flag
|
||||
flag = true;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize SX1262 with default settings
|
||||
Serial.print(F("[SX1262] Initializing ... "));
|
||||
int state = radio.beginLRFHSS();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true) { delay(10); }
|
||||
}
|
||||
|
||||
// set the function that will be called
|
||||
// when packet transmission is finished
|
||||
radio.setPacketSentAction(setFlag);
|
||||
|
||||
// start transmitting the first packet
|
||||
Serial.print(F("[SX1262] Sending first packet ... "));
|
||||
|
||||
// you can transmit C-string or Arduino string up to
|
||||
// 256 characters long
|
||||
transmissionState = radio.startTransmit("Hello World!");
|
||||
|
||||
// you can also transmit byte array up to 256 bytes long
|
||||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
|
||||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
state = radio.startTransmit(byteArr, 8);
|
||||
*/
|
||||
}
|
||||
|
||||
// counter to keep track of transmitted packets
|
||||
int count = 0;
|
||||
|
||||
void loop() {
|
||||
// LR-FHSS modem can only transmit!
|
||||
|
||||
// check if the previous transmission finished
|
||||
if(flag) {
|
||||
// reset flag
|
||||
flag = false;
|
||||
|
||||
// check if this was caused by hopping or transmission finished
|
||||
if(radio.getIrqFlags() & RADIOLIB_SX126X_IRQ_LR_FHSS_HOP) {
|
||||
radio.hopLRFHSS();
|
||||
|
||||
} else {
|
||||
if (transmissionState == RADIOLIB_ERR_NONE) {
|
||||
// packet was successfully sent
|
||||
Serial.println(F("transmission finished!"));
|
||||
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(transmissionState);
|
||||
|
||||
}
|
||||
|
||||
// clean up after transmission is finished
|
||||
// this will ensure transmitter is disabled,
|
||||
// RF switch is powered down etc.
|
||||
radio.finishTransmit();
|
||||
|
||||
// wait a second before transmitting again
|
||||
delay(1000);
|
||||
|
||||
// send another one
|
||||
Serial.print(F("[SX1262] Sending another packet ... "));
|
||||
|
||||
// you can transmit C-string or Arduino string up to
|
||||
// 256 characters long
|
||||
String str = "Hello World! #" + String(count++);
|
||||
transmissionState = radio.startTransmit(str);
|
||||
|
||||
// you can also transmit byte array up to 256 bytes long
|
||||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
|
||||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
transmissionState = radio.startTransmit(byteArr, 8);
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -84,11 +84,6 @@ void loop() {
|
|||
// the packet was successfully transmitted
|
||||
Serial.println(F("success!"));
|
||||
|
||||
// print measured data rate
|
||||
Serial.print(F("[SX1262] Datarate:\t"));
|
||||
Serial.print(radio.getDataRate());
|
||||
Serial.println(F(" bps"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
|
||||
// the supplied packet was longer than 256 bytes
|
||||
Serial.println(F("too long!"));
|
||||
|
|
|
|||
|
|
@ -99,10 +99,6 @@ void loop() {
|
|||
// packet was successfully sent
|
||||
Serial.println(F("transmission finished!"));
|
||||
|
||||
// NOTE: when using interrupt-driven transmit method,
|
||||
// it is not possible to automatically measure
|
||||
// transmission data rate using getDataRate()
|
||||
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(transmissionState);
|
||||
|
|
|
|||
|
|
@ -84,11 +84,6 @@ void loop() {
|
|||
// the packet was successfully transmitted
|
||||
Serial.println(F(" success!"));
|
||||
|
||||
// print measured data rate
|
||||
Serial.print(F("[SX1278] Datarate:\t"));
|
||||
Serial.print(radio.getDataRate());
|
||||
Serial.println(F(" bps"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
|
||||
// the supplied packet was longer than 256 bytes
|
||||
Serial.println(F("too long!"));
|
||||
|
|
|
|||
|
|
@ -99,10 +99,6 @@ void loop() {
|
|||
// packet was successfully sent
|
||||
Serial.println(F("transmission finished!"));
|
||||
|
||||
// NOTE: when using interrupt-driven transmit method,
|
||||
// it is not possible to automatically measure
|
||||
// transmission data rate using getDataRate()
|
||||
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(transmissionState);
|
||||
|
|
|
|||
|
|
@ -130,10 +130,6 @@ void loop() {
|
|||
// packet was successfully sent
|
||||
Serial.println(F("transmission finished!"));
|
||||
|
||||
// NOTE: when using interrupt-driven transmit method,
|
||||
// it is not possible to automatically measure
|
||||
// transmission data rate using getDataRate()
|
||||
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(transmissionState);
|
||||
|
|
|
|||
|
|
@ -112,10 +112,6 @@ void loop() {
|
|||
// packet was successfully sent
|
||||
Serial.println(F("transmission finished!"));
|
||||
|
||||
// NOTE: when using interrupt-driven transmit method,
|
||||
// it is not possible to automatically measure
|
||||
// transmission data rate using getDataRate()
|
||||
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(transmissionState);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue