[SX127x] Updated FHSS example formatting

This commit is contained in:
jgromes 2022-01-23 12:05:30 +01:00
parent bd0158c734
commit 73e3da212a
2 changed files with 239 additions and 102 deletions
examples/SX127x
SX127x_Receive_FHSS
SX127x_Transmit_FHSS

View file

@ -15,56 +15,98 @@
For full API reference, see the GitHub Pages For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/ https://jgromes.github.io/RadioLib/
The SX1276 / 7 / 8 / 9 supports FHSS or Frequency Hopping Spread Spectrum. SX127x supports FHSS or Frequency Hopping Spread Spectrum.
Once a hopping period is set and a transmission is started the radio Once a hopping period is set and a transmission is started, the radio
will begin triggering interrupts every hop period where the radio frequency will begin triggering interrupts every hop period where the radio frequency
is changed to the next channel. is changed to the next channel.
*/ */
#include <RadioLib.h> //Click here to get the library: http://librarymanager/All#RadioLib #include <RadioLib.h>
// SX1276 has the following connections: // SX1278 has the following connections:
const int pin_cs = 10; // NSS pin: 10
const int pin_dio0 = 2; // DIO0 pin: 2
const int pin_dio1 = 9; // RESET pin: 9
const int pin_rst = 3; // DIO1 pin: 3
SX1276 radio = new Module(pin_cs, pin_dio0, pin_rst, pin_dio1); SX1278 radio = new Module(10, 2, 9, 3);
volatile bool rxComplete = false; // or using RadioShield
volatile bool fhssChange = false; // https://github.com/jgromes/RadioShield
//SX1278 radio = RadioShield.ModuleA;
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// flag to indicate frequency must be changed
volatile bool fhssChangeFlag = false;
// the channel frequencies can be generated randomly or hard coded // the channel frequencies can be generated randomly or hard coded
float channels[] = {908.0, 906.0, 907.0, 905.0, 903.0, 910.0, 909.0}; // NOTE: The frequency list MUST be the same on both sides!
float channels[] = { 433.0, 433.4, 433.2, 433.6, 434.0, 433.8 };
int numberOfChannels = sizeof(channels) / sizeof(float); int numberOfChannels = sizeof(channels) / sizeof(float);
// counter to keep track of how many frequency hops were performed
int hopsCompleted = 0; int hopsCompleted = 0;
// 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 setRxFlag(void) {
receivedFlag = true;
}
// this function is called when FhssChangeChannel interrupt occurs
// (at the beginning of each transmission)
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFHSSFlag(void) {
fhssChangeFlag = true;
}
void setup() { void setup() {
Serial.begin(9600); Serial.begin(9600);
// begin radio on home channel // begin radio on home channel
Serial.print(F("[SX127x] Initializing ... ")); Serial.print(F("[SX1278] Initializing ... "));
int state = radio.begin(channels[0]); int state = radio.begin(channels[0]);
if (state != RADIOLIB_ERR_NONE) { if (state == RADIOLIB_ERR_NONE) {
Serial.print(F("Failed with code: ")); Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state); Serial.println(state);
while (true);
} }
else
Serial.println(F("Success!"));
// set hop period to enable FHSS // set hop period in symbols
// this will also enable FHSS
state = radio.setFHSSHoppingPeriod(9); state = radio.setFHSSHoppingPeriod(9);
if (state != RADIOLIB_ERR_NONE) { if (state == RADIOLIB_ERR_NONE) {
Serial.print(F("Error setting hopping period: ")); Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state); Serial.println(state);
while (true);
} }
radio.setDio0Action(dio0ISR); // called when transmission is finished
radio.setDio1Action(dio1ISR); // called after a transmission has started, so we can move to next freq // set the function to call when reception is finished
radio.setDio0Action(setRxFlag);
// set the function to call when we need to hcange frequency
radio.setDio1Action(setFHSSFlag);
// start listening for LoRa packets // start listening for LoRa packets
Serial.print(F("[SX1278] Starting to listen ... ")); Serial.print(F("[SX1278] Starting to listen ... "));
state = radio.startReceive(); state = radio.startReceive();
if (state != RADIOLIB_ERR_NONE) { if (state == RADIOLIB_ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code ")); Serial.print(F("failed, code "));
Serial.println(state); Serial.println(state);
while (true); while (true);
@ -72,39 +114,67 @@ void setup() {
} }
void loop() { void loop() {
if (rxComplete == true) { // check if the reception flag is set
uint8_t incomingBuffer[255]; if (receivedFlag == true) {
radio.readData(incomingBuffer, 255); // you can read received data as an Arduino String
uint8_t receivedBytes = radio.getPacketLength(); String str;
Serial.write(incomingBuffer, receivedBytes); int state = radio.readData(str);
Serial.println();
Serial.print(F("Hops completed: ")); // you can also read received data as byte array
/*
byte byteArr[8];
int state = radio.readData(byteArr, 8);
*/
if (state == RADIOLIB_ERR_NONE) {
// packet was successfully received
Serial.println(F("[SX1278] Received packet!"));
// print data of the packet
Serial.print(F("[SX1278] Data:\t\t"));
Serial.println(str);
} else if (state == RADIOLIB_ERR_CRC_MISMATCH) {
// packet was received, but is malformed
Serial.println(F("[SX1278] CRC error!"));
} else {
// some other error occurred
Serial.print(F("[SX1278] Failed, code "));
Serial.println(state);
}
// print the number of hops it took
Serial.print(F("[SX1278] Hops completed: "));
Serial.println(hopsCompleted); Serial.println(hopsCompleted);
// reset the counter
hopsCompleted = 0; hopsCompleted = 0;
// put the module back to listen mode
radio.startReceive(); radio.startReceive();
rxComplete = false; // we're ready to receive more packets, clear the flag
receivedFlag = false;
} }
if (fhssChange == true) { // check if we need to do another frequency hop
radio.setFrequency(channels[radio.getFHSSChannel() % numberOfChannels]); if (fhssChangeFlag == true) {
// we do, change it now
int state = radio.setFrequency(channels[radio.getFHSSChannel() % numberOfChannels]);
if (state != RADIOLIB_ERR_NONE) {
Serial.print(F("[SX1278] Failed to change frequency, code "));
Serial.println(state);
}
// increment the counter
hopsCompleted++; hopsCompleted++;
// clear the FHSS interrupt
radio.clearFHSSInt(); radio.clearFHSSInt();
fhssChange = false;
// we're ready to do another hop, clear the flag
fhssChangeFlag = false;
} }
} }
// ISR when DIO0 goes low
// called when transmission is complete or when RX is received
void dio0ISR(void) {
rxComplete = true;
}
// ISR when DIO1 goes low
// called when FhssChangeChannel interrupt occurs (at the beginning of each transmission)
void dio1ISR(void) {
fhssChange = true;
}

View file

@ -15,99 +15,166 @@
For full API reference, see the GitHub Pages For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/ https://jgromes.github.io/RadioLib/
The SX1276 / 7 / 8 / 9 supports FHSS or Frequency Hopping Spread Spectrum. SX127x supports FHSS or Frequency Hopping Spread Spectrum.
Once a hopping period is set and a transmission is started the radio Once a hopping period is set and a transmission is started, the radio
will begin triggering interrupts every hop period where the radio frequency will begin triggering interrupts every hop period where the radio frequency
is changed to the next channel. is changed to the next channel.
*/ */
#include <RadioLib.h> //Click here to get the library: http://librarymanager/All#RadioLib #include <RadioLib.h>
// SX1276 has the following connections: // SX1278 has the following connections:
const int pin_cs = 10; // NSS pin: 10
const int pin_dio0 = 2; // DIO0 pin: 2
const int pin_dio1 = 9; // RESET pin: 9
const int pin_rst = 3; // DIO1 pin: 3
SX1276 radio = new Module(pin_cs, pin_dio0, pin_rst, pin_dio1); SX1278 radio = new Module(10, 2, 9, 3);
volatile bool xmitComplete = false; // or using RadioShield
volatile bool fhssChange = false; // https://github.com/jgromes/RadioShield
//SX1278 radio = RadioShield.ModuleA;
// flag to indicate that a packet was received
volatile bool transmittedFlag = false;
// flag to indicate frequency must be changed
volatile bool fhssChangeFlag = false;
// the channel frequencies can be generated randomly or hard coded // the channel frequencies can be generated randomly or hard coded
float channels[] = {908.0, 906.0, 907.0, 905.0, 903.0, 910.0, 909.0}; // NOTE: The frequency list MUST be the same on both sides!
float channels[] = { 433.0, 433.4, 433.2, 433.6, 434.0, 433.8 };
int numberOfChannels = sizeof(channels) / sizeof(float); int numberOfChannels = sizeof(channels) / sizeof(float);
// counter to keep track of how many frequency hops were performed
int hopsCompleted = 0; int hopsCompleted = 0;
int counter = 0;
// counter that increments with each sent packet
int packetCounter = 0;
// save transmission state between loops
int transmissionState = RADIOLIB_ERR_NONE;
// this is the packet that will be sent
String longPacket = "Let's create a really long packet to trigger \
lots of hop interrupts. A packet can be up to 256 bytes long. \
This packet is 222 bytes so using sf = 9, bw = 125, timeOnAir is \
1488ms. 1488ms / (9*4.10ms) = 40 hops. Counter: ";
// 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 setTxFlag(void) {
transmittedFlag = true;
}
// this function is called when FhssChangeChannel interrupt occurs
// (at the beginning of each transmission)
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFHSSFlag(void) {
fhssChangeFlag = true;
}
void setup() { void setup() {
Serial.begin(9600); Serial.begin(9600);
// begin radio on home channel // begin radio on home channel
Serial.print(F("[SX127x] Initializing ... ")); Serial.print(F("[SX1278] Initializing ... "));
int state = radio.begin(channels[0]); int state = radio.begin(channels[0]);
if (state != RADIOLIB_ERR_NONE) { if (state == RADIOLIB_ERR_NONE) {
Serial.print(F("Failed with code: ")); Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state); Serial.println(state);
while (true);
} }
else
Serial.println(F("Success!"));
// set hop period to enable FHSS // set hop period in symbols
// this will also enable FHSS
state = radio.setFHSSHoppingPeriod(9); state = radio.setFHSSHoppingPeriod(9);
if(state != RADIOLIB_ERR_NONE) { if (state == RADIOLIB_ERR_NONE) {
Serial.print(F("Error setting hopping period: ")); Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state); Serial.println(state);
while (true);
} }
radio.setDio0Action(dio0ISR); // called when transmission is finished // set the function to call when transmission is finished
radio.setDio1Action(dio1ISR); // called after a transmission has started, so we can move to next freq radio.setDio0Action(setTxFlag);
Serial.print(F("Transmitting packet...")); // set the function to call when we need to hcange frequency
radio.setDio1Action(setFHSSFlag);
String longOutput = "Let's create a really long packet to trigger lots of hop interrupts. A packet can be up to 256 bytes long. This packet is 222 bytes so using sf = 9, bw = 125, timeOnAir is 1488ms. 1488ms / (9*4.10ms) = 40 hops. Counter: "; // start transmitting the first packet
Serial.print(F("[SX1278] Sending first packet ... "));
state = radio.startTransmit(longOutput + counter); transmissionState = radio.startTransmit(longPacket + packetCounter);
if (state != RADIOLIB_ERR_NONE) {
Serial.print(F("Error transmitting with code: "));
Serial.println(state);
}
} }
void loop() { void loop() {
if (xmitComplete == true) { // check if the transmission flag is set
xmitComplete = false; if (transmittedFlag == true) {
Serial.println(F("Transmit complete")); // reset flag
Serial.print(F("Radio after xmit is on channel: ")); 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);
}
// The channel is automatically reset to 0 upon completion
Serial.print(F("[SX1278] Radio is on channel: "));
Serial.println(radio.getFHSSChannel()); Serial.println(radio.getFHSSChannel());
// the FHSS channel is automatically reset to 0 upon end of transmission
radio.setFrequency(channels[radio.getFHSSChannel() % numberOfChannels]); // Return to home channel before next transaction // print the number of hops it took
Serial.print(F("[SX1278] Hops completed: "));
Serial.print(F("Hops completed: "));
Serial.println(hopsCompleted); Serial.println(hopsCompleted);
// reset the counter
hopsCompleted = 0; hopsCompleted = 0;
radio.startReceive(); // return to home channel before the next transaction
}
if (fhssChange == true) {
radio.setFrequency(channels[radio.getFHSSChannel() % numberOfChannels]); radio.setFrequency(channels[radio.getFHSSChannel() % numberOfChannels]);
// wait a second before transmitting again
delay(1000);
// increment the packet counter
packetCounter++;
// send another packet
Serial.print(F("[SX1278] Sending another packet ... "));
transmissionState = radio.startTransmit(longPacket + packetCounter);
}
// check if we need to do another frequency hop
if (fhssChangeFlag == true) {
// we do, change it now
int state = radio.setFrequency(channels[radio.getFHSSChannel() % numberOfChannels]);
if (state != RADIOLIB_ERR_NONE) {
Serial.print(F("[SX1278] Failed to change frequency, code "));
Serial.println(state);
}
// increment the counter
hopsCompleted++; hopsCompleted++;
fhssChange = false;
// clear the FHSS interrupt
radio.clearFHSSInt(); radio.clearFHSSInt();
// we're ready to do another hop, clear the flag
fhssChangeFlag = false;
} }
} }
// ISR when DIO0 goes low
// called when transmission is complete or when RX is received
void dio0ISR(void) {
xmitComplete = true;
}
// ISR when DIO1 goes low
// called when FhssChangeChannel interrupt occurs (at regular HoppingPeriods)
void dio1ISR(void) {
fhssChange = true;
}