From 73e3da212a79ba0c6498083890201f4b7c7bf33f Mon Sep 17 00:00:00 2001 From: jgromes <jan.gromes@gmail.com> Date: Sun, 23 Jan 2022 12:05:30 +0100 Subject: [PATCH] [SX127x] Updated FHSS example formatting --- .../SX127x_Receive_FHSS.ino | 162 +++++++++++----- .../SX127x_Transmit_FHSS.ino | 179 ++++++++++++------ 2 files changed, 239 insertions(+), 102 deletions(-) diff --git a/examples/SX127x/SX127x_Receive_FHSS/SX127x_Receive_FHSS.ino b/examples/SX127x/SX127x_Receive_FHSS/SX127x_Receive_FHSS.ino index 7ee31b83..3aeca4a8 100644 --- a/examples/SX127x/SX127x_Receive_FHSS/SX127x_Receive_FHSS.ino +++ b/examples/SX127x/SX127x_Receive_FHSS/SX127x_Receive_FHSS.ino @@ -15,56 +15,98 @@ For full API reference, see the GitHub Pages https://jgromes.github.io/RadioLib/ - The SX1276 / 7 / 8 / 9 supports FHSS or Frequency Hopping Spread Spectrum. - Once a hopping period is set and a transmission is started the radio + SX127x supports FHSS or Frequency Hopping Spread Spectrum. + Once a hopping period is set and a transmission is started, the radio will begin triggering interrupts every hop period where the radio frequency 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: -const int pin_cs = 10; -const int pin_dio0 = 2; -const int pin_dio1 = 9; -const int pin_rst = 3; -SX1276 radio = new Module(pin_cs, pin_dio0, pin_rst, pin_dio1); +// SX1278 has the following connections: +// NSS pin: 10 +// DIO0 pin: 2 +// RESET pin: 9 +// DIO1 pin: 3 +SX1278 radio = new Module(10, 2, 9, 3); -volatile bool rxComplete = false; -volatile bool fhssChange = false; +// or using RadioShield +// 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 -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); +// counter to keep track of how many frequency hops were performed 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() { Serial.begin(9600); // begin radio on home channel - Serial.print(F("[SX127x] Initializing ... ")); + Serial.print(F("[SX1278] Initializing ... ")); int state = radio.begin(channels[0]); - if (state != RADIOLIB_ERR_NONE) { - Serial.print(F("Failed with code: ")); + if (state == RADIOLIB_ERR_NONE) { + Serial.println(F("success!")); + } else { + Serial.print(F("failed, code ")); 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); - if (state != RADIOLIB_ERR_NONE) { - Serial.print(F("Error setting hopping period: ")); + if (state == RADIOLIB_ERR_NONE) { + Serial.println(F("success!")); + } else { + Serial.print(F("failed, code ")); 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 Serial.print(F("[SX1278] Starting to listen ... ")); state = radio.startReceive(); - if (state != RADIOLIB_ERR_NONE) { + if (state == RADIOLIB_ERR_NONE) { + Serial.println(F("success!")); + } else { Serial.print(F("failed, code ")); Serial.println(state); while (true); @@ -72,39 +114,67 @@ void setup() { } void loop() { - if (rxComplete == true) { - uint8_t incomingBuffer[255]; - radio.readData(incomingBuffer, 255); - uint8_t receivedBytes = radio.getPacketLength(); - Serial.write(incomingBuffer, receivedBytes); - Serial.println(); + // check if the reception flag is set + if (receivedFlag == true) { + // you can read received data as an Arduino String + String str; + int state = radio.readData(str); - 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); + + // reset the counter hopsCompleted = 0; + // put the module back to listen mode radio.startReceive(); - rxComplete = false; + // we're ready to receive more packets, clear the flag + receivedFlag = false; } - if (fhssChange == true) { - radio.setFrequency(channels[radio.getFHSSChannel() % numberOfChannels]); + // 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++; + + // clear the FHSS interrupt 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; -} \ No newline at end of file diff --git a/examples/SX127x/SX127x_Transmit_FHSS/SX127x_Transmit_FHSS.ino b/examples/SX127x/SX127x_Transmit_FHSS/SX127x_Transmit_FHSS.ino index f1ecbaf8..b6182af5 100644 --- a/examples/SX127x/SX127x_Transmit_FHSS/SX127x_Transmit_FHSS.ino +++ b/examples/SX127x/SX127x_Transmit_FHSS/SX127x_Transmit_FHSS.ino @@ -15,99 +15,166 @@ For full API reference, see the GitHub Pages https://jgromes.github.io/RadioLib/ - The SX1276 / 7 / 8 / 9 supports FHSS or Frequency Hopping Spread Spectrum. - Once a hopping period is set and a transmission is started the radio + SX127x supports FHSS or Frequency Hopping Spread Spectrum. + Once a hopping period is set and a transmission is started, the radio will begin triggering interrupts every hop period where the radio frequency 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: -const int pin_cs = 10; -const int pin_dio0 = 2; -const int pin_dio1 = 9; -const int pin_rst = 3; -SX1276 radio = new Module(pin_cs, pin_dio0, pin_rst, pin_dio1); +// SX1278 has the following connections: +// NSS pin: 10 +// DIO0 pin: 2 +// RESET pin: 9 +// DIO1 pin: 3 +SX1278 radio = new Module(10, 2, 9, 3); -volatile bool xmitComplete = false; -volatile bool fhssChange = false; +// or using RadioShield +// 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 -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); +// counter to keep track of how many frequency hops were performed 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() { Serial.begin(9600); // begin radio on home channel - Serial.print(F("[SX127x] Initializing ... ")); + Serial.print(F("[SX1278] Initializing ... ")); int state = radio.begin(channels[0]); - if (state != RADIOLIB_ERR_NONE) { - Serial.print(F("Failed with code: ")); + if (state == RADIOLIB_ERR_NONE) { + Serial.println(F("success!")); + } else { + Serial.print(F("failed, code ")); 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); - if(state != RADIOLIB_ERR_NONE) { - Serial.print(F("Error setting hopping period: ")); + if (state == RADIOLIB_ERR_NONE) { + Serial.println(F("success!")); + } else { + Serial.print(F("failed, code ")); 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 transmission is finished + 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: "; - - state = radio.startTransmit(longOutput + counter); - if (state != RADIOLIB_ERR_NONE) { - Serial.print(F("Error transmitting with code: ")); - Serial.println(state); - } + // start transmitting the first packet + Serial.print(F("[SX1278] Sending first packet ... ")); + transmissionState = radio.startTransmit(longPacket + packetCounter); } void loop() { - if (xmitComplete == true) { - xmitComplete = false; - Serial.println(F("Transmit complete")); - Serial.print(F("Radio after xmit is on channel: ")); + // check if the transmission flag is set + if (transmittedFlag == true) { + // 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); + + } + + // The channel is automatically reset to 0 upon completion + Serial.print(F("[SX1278] Radio is on channel: ")); 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 - - Serial.print(F("Hops completed: ")); + // print the number of hops it took + Serial.print(F("[SX1278] Hops completed: ")); Serial.println(hopsCompleted); + + // reset the counter hopsCompleted = 0; - radio.startReceive(); - } - - if (fhssChange == true) { + // return to home channel before the next transaction 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++; - fhssChange = false; + + // clear the FHSS interrupt 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; -}