diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..6612607 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +github: [sandeepmistry] diff --git a/API.md b/API.md index 1eebd9a..572eded 100644 --- a/API.md +++ b/API.md @@ -15,7 +15,7 @@ Initialize the library with the specified frequency. ```arduino LoRa.begin(frequency); ``` - * `frequency` - frequency in Hz (`433E6`, `866E6`, `915E6`) + * `frequency` - frequency in Hz (`433E6`, `868E6`, `915E6`) Returns `1` on success, `0` on failure. @@ -194,7 +194,7 @@ The `onReceive` callback will be called when a packet is received. int rssi = LoRa.packetRssi(); ``` -Returns the RSSI of the received packet. +Returns the averaged RSSI of the last received packet (dBm). ### Packet SNR @@ -204,6 +204,14 @@ float snr = LoRa.packetSnr(); Returns the estimated SNR of the received packet in dB. +## RSSI + +```arduino +int rssi = LoRa.rssi(); +``` + +Returns the current RSSI of the radio (dBm). RSSI can be read at any time (during packet reception or not) + ### Packet Frequency Error ```arduino @@ -306,7 +314,7 @@ Change the frequency of the radio. ```arduino LoRa.setFrequency(frequency); ``` - * `frequency` - frequency in Hz (`433E6`, `866E6`, `915E6`) + * `frequency` - frequency in Hz (`433E6`, `868E6`, `915E6`) ### Spreading Factor @@ -329,7 +337,7 @@ LoRa.setSignalBandwidth(signalBandwidth); * `signalBandwidth` - signal bandwidth in Hz, defaults to `125E3`. -Supported values are `7.8E3`, `10.4E3`, `15.6E3`, `20.8E3`, `31.25E3`, `41.7E3`, `62.5E3`, `125E3`, and `250E3`. +Supported values are `7.8E3`, `10.4E3`, `15.6E3`, `20.8E3`, `31.25E3`, `41.7E3`, `62.5E3`, `125E3`, `250E3`, and `500E3`. ### Coding Rate @@ -384,6 +392,17 @@ LoRa.enableInvertIQ(); LoRa.disableInvertIQ(); ``` +### LNA Gain + +Set LNA Gain for better RX sensitivity, by default AGC (Automatic Gain Control) is used and LNA gain is not used. + +```arduino +LoRa.setGain(gain); +``` + + * `gain` - LNA gain + +Supported values are between `0` and `6`. If gain is 0, AGC will be enabled and LNA gain will not be used. Else if gain is from 1 to 6, AGC will be disabled and LNA gain will be used. ## Other functions diff --git a/README.md b/README.md index c89956a..51341ff 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,9 @@ An [Arduino](https://arduino.cc/) library for sending and receiving data using [ ## Compatible Hardware - * [Semtech SX1276/77/78/79](http://www.semtech.com/apps/product.php?pn=SX1276) based boards including: - * [Dragino Lora Shield](http://www.dragino.com/products/module/item/102-lora-shield.html) - * [HopeRF](http://www.hoperf.com/rf_transceiver/lora/) [RFM95W](http://www.hoperf.com/rf_transceiver/lora/RFM95W.html), [RFM96W](http://www.hoperf.com/rf_transceiver/lora/RFM96W.html), and [RFM98W](http://www.hoperf.com/rf_transceiver/lora/RFM98W.html) + * [Semtech SX1276/77/78/79](https://www.semtech.com/apps/product.php?pn=SX1276) based boards including: + * [Dragino Lora Shield](https://www.dragino.com/products/lora/item/102-lora-shield.html) + * [HopeRF](https://www.hoperf.com/modules/lora/index.html) [RFM95W](https://www.hoperf.com/modules/lora/RFM95.html), [RFM96W](https://www.hoperf.com/modules/lora/RFM96.html), and [RFM98W](https://www.hoperf.com/modules/lora/RFM98.html) * [Modtronix](http://modtronix.com/) [inAir4](http://modtronix.com/inair4.html), [inAir9](http://modtronix.com/inair9.html), and [inAir9B](http://modtronix.com/inair9b.html) * [Arduino MKR WAN 1300](https://store.arduino.cc/usa/mkr-wan-1300) * **NOTE:** Requires firmware v1.1.6 or later on the on-board Murata module. Please use the [MKRWANFWUpdate_standalone example](https://github.com/arduino-libraries/MKRWAN/blob/master/examples/MKRWANFWUpdate_standalone/MKRWANFWUpdate_standalone.ino) from latest [MKRWAN library](https://github.com/arduino-libraries/MKRWAN) release to update the firmware. diff --git a/examples/LoRaReceiverCallback/LoRaReceiverCallback.ino b/examples/LoRaReceiverCallback/LoRaReceiverCallback.ino index e227e23..ed554d9 100644 --- a/examples/LoRaReceiverCallback/LoRaReceiverCallback.ino +++ b/examples/LoRaReceiverCallback/LoRaReceiverCallback.ino @@ -1,43 +1,45 @@ -#include -#include - -#ifdef ARDUINO_SAMD_MKRWAN1300 -#error "This example is not compatible with the Arduino MKR WAN 1300 board!" -#endif - -void setup() { - Serial.begin(9600); - while (!Serial); - - Serial.println("LoRa Receiver Callback"); - - if (!LoRa.begin(915E6)) { - Serial.println("Starting LoRa failed!"); - while (1); - } - - // register the receive callback - LoRa.onReceive(onReceive); - - // put the radio into receive mode - LoRa.receive(); -} - -void loop() { - // do nothing -} - -void onReceive(int packetSize) { - // received a packet - Serial.print("Received packet '"); - - // read packet - for (int i = 0; i < packetSize; i++) { - Serial.print((char)LoRa.read()); - } - - // print RSSI of packet - Serial.print("' with RSSI "); - Serial.println(LoRa.packetRssi()); -} - +#include +#include + +#ifdef ARDUINO_SAMD_MKRWAN1300 +#error "This example is not compatible with the Arduino MKR WAN 1300 board!" +#endif + +void setup() { + Serial.begin(9600); + while (!Serial); + + Serial.println("LoRa Receiver Callback"); + + if (!LoRa.begin(915E6)) { + Serial.println("Starting LoRa failed!"); + while (1); + } + + // Uncomment the next line to disable the default AGC and set LNA gain, values between 1 - 6 are supported + // LoRa.setGain(6); + + // register the receive callback + LoRa.onReceive(onReceive); + + // put the radio into receive mode + LoRa.receive(); +} + +void loop() { + // do nothing +} + +void onReceive(int packetSize) { + // received a packet + Serial.print("Received packet '"); + + // read packet + for (int i = 0; i < packetSize; i++) { + Serial.print((char)LoRa.read()); + } + + // print RSSI of packet + Serial.print("' with RSSI "); + Serial.println(LoRa.packetRssi()); +} diff --git a/examples/LoRaSenderNonBlockingCallback/LoRaSenderNonBlockingCallback.ino b/examples/LoRaSenderNonBlockingCallback/LoRaSenderNonBlockingCallback.ino index 88e5e2f..aa79499 100644 --- a/examples/LoRaSenderNonBlockingCallback/LoRaSenderNonBlockingCallback.ino +++ b/examples/LoRaSenderNonBlockingCallback/LoRaSenderNonBlockingCallback.ino @@ -18,7 +18,7 @@ void setup() { } void loop() { - if (runEvery(1000)) { // repeat every 1000 millis + if (runEvery(5000)) { // repeat every 5000 millis Serial.print("Sending packet non-blocking: "); Serial.println(counter); diff --git a/keywords.txt b/keywords.txt index 5367d52..f4b7e4e 100644 --- a/keywords.txt +++ b/keywords.txt @@ -23,6 +23,8 @@ packetRssi KEYWORD2 packetSnr KEYWORD2 packetFrequencyError KEYWORD2 +rssi KEYWORD2 + write KEYWORD2 available KEYWORD2 @@ -49,6 +51,7 @@ enableCrc KEYWORD2 disableCrc KEYWORD2 enableInvertIQ KEYWORD2 disableInvertIQ KEYWORD2 +setGain KEYWORD2 random KEYWORD2 setPins KEYWORD2 diff --git a/library.properties b/library.properties index db6d845..e869420 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=LoRa -version=0.7.0 +version=0.8.0 author=Sandeep Mistry maintainer=Sandeep Mistry sentence=An Arduino library for sending and receiving data using LoRa radios. diff --git a/src/LoRa.cpp b/src/LoRa.cpp index be4f24e..5cdb5cd 100644 --- a/src/LoRa.cpp +++ b/src/LoRa.cpp @@ -20,6 +20,7 @@ #define REG_RX_NB_BYTES 0x13 #define REG_PKT_SNR_VALUE 0x19 #define REG_PKT_RSSI_VALUE 0x1a +#define REG_RSSI_VALUE 0x1b #define REG_MODEM_CONFIG_1 0x1d #define REG_MODEM_CONFIG_2 0x1e #define REG_PREAMBLE_MSB 0x20 @@ -58,6 +59,10 @@ #define IRQ_CAD_DONE_MASK 0x04 #define IRQ_CAD_DETECTED_MASK 0x01 +#define RF_MID_BAND_THRESHOLD 525E6 +#define RSSI_OFFSET_HF_PORT 157 +#define RSSI_OFFSET_LF_PORT 164 + #define MAX_PKT_LENGTH 255 #if (ESP8266 || ESP32) @@ -262,7 +267,7 @@ int LoRaClass::parsePacket(int size) int LoRaClass::packetRssi() { - return (readRegister(REG_PKT_RSSI_VALUE) - (_frequency < 868E6 ? 164 : 157)); + return (readRegister(REG_PKT_RSSI_VALUE) - (_frequency < RF_MID_BAND_THRESHOLD ? RSSI_OFFSET_LF_PORT : RSSI_OFFSET_HF_PORT)); } float LoRaClass::packetSnr() @@ -273,14 +278,14 @@ float LoRaClass::packetSnr() long LoRaClass::packetFrequencyError() { int32_t freqError = 0; - freqError = static_cast(readRegister(REG_FREQ_ERROR_MSB) & B111); + freqError = static_cast(readRegister(REG_FREQ_ERROR_MSB) & 0b111); freqError <<= 8L; freqError += static_cast(readRegister(REG_FREQ_ERROR_MID)); freqError <<= 8L; freqError += static_cast(readRegister(REG_FREQ_ERROR_LSB)); - if (readRegister(REG_FREQ_ERROR_MSB) & B1000) { // Sign bit is on - freqError -= 524288; // B1000'0000'0000'0000'0000 + if (readRegister(REG_FREQ_ERROR_MSB) & 0b1000) { // Sign bit is on + freqError -= 524288; // 0b1000'0000'0000'0000'0000 } const float fXtal = 32E6; // FXOSC: crystal oscillator (XTAL) frequency (2.5. Chip Specification, p. 14) @@ -289,6 +294,11 @@ long LoRaClass::packetFrequencyError() return static_cast(fError); } +int LoRaClass::rssi() +{ + return (readRegister(REG_RSSI_VALUE) - (_frequency < RF_MID_BAND_THRESHOLD ? RSSI_OFFSET_LF_PORT : RSSI_OFFSET_HF_PORT)); +} + size_t LoRaClass::write(uint8_t byte) { return write(&byte, sizeof(byte)); @@ -635,6 +645,32 @@ void LoRaClass::setOCP(uint8_t mA) writeRegister(REG_OCP, 0x20 | (0x1F & ocpTrim)); } +void LoRaClass::setGain(uint8_t gain) +{ + // check allowed range + if (gain > 6) { + gain = 6; + } + + // set to standby + idle(); + + // set gain + if (gain == 0) { + // if gain = 0, enable AGC + writeRegister(REG_MODEM_CONFIG_3, 0x04); + } else { + // disable AGC + writeRegister(REG_MODEM_CONFIG_3, 0x00); + + // clear Gain and set LNA boost + writeRegister(REG_LNA, 0x03); + + // set gain + writeRegister(REG_LNA, readRegister(REG_LNA) | (gain << 5)); + } +} + byte LoRaClass::random() { return readRegister(REG_RSSI_WIDEBAND); @@ -707,10 +743,6 @@ void LoRaClass::handleDio0Rise() if (_onReceive) { _onReceive(packetLength); } - - // reset FIFO address - writeRegister(REG_FIFO_ADDR_PTR, 0); - } else if ((irqFlags & IRQ_TX_DONE_MASK) != 0) { if (_onTxDone) { _onTxDone(); diff --git a/src/LoRa.h b/src/LoRa.h index 5e05c79..bad87da 100644 --- a/src/LoRa.h +++ b/src/LoRa.h @@ -45,6 +45,8 @@ public: float packetSnr(); long packetFrequencyError(); + int rssi(); + // from Print virtual size_t write(uint8_t byte); virtual size_t write(const uint8_t *buffer, size_t size); @@ -79,6 +81,8 @@ public: void disableInvertIQ(); void setOCP(uint8_t mA); // Over Current Protection control + + void setGain(uint8_t gain); // Set LNA gain // deprecated void crc() { enableCrc(); }