diff --git a/examples/SX128x/SX128x_Ranging/SX128x_Ranging.ino b/examples/SX128x/SX128x_Ranging/SX128x_Ranging.ino index 2776f4f6..d7427880 100644 --- a/examples/SX128x/SX128x_Ranging/SX128x_Ranging.ino +++ b/examples/SX128x/SX128x_Ranging/SX128x_Ranging.ino @@ -6,7 +6,10 @@ distance between the modules using time-of-flight measurement. - Only SX1280 and SX1282 support ranging! + Only SX1280 and SX1282 without external RF switch support ranging! + + Note that to get accurate ranging results, calibration is needed! + The process is described in Semtech SX1280 Application Note AN1200.29 For default module settings, see the wiki page https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx128x---lora-modem @@ -57,12 +60,24 @@ void loop() { int state = radio.range(false, 0x12345678); */ + // if ranging calibration is known, it can be provided + // this should improve the accuracy and precision + /* + uint16_t calibration[3][6] = { + { 10299, 10271, 10244, 10242, 10230, 10246 }, + { 11486, 11474, 11453, 11426, 11417, 11401 }, + { 13308, 13493, 13528, 13515, 13430, 13376 } + }; + + int state = radio.range(true, 0x12345678, calibration); + */ + if (state == RADIOLIB_ERR_NONE) { // ranging finished successfully Serial.println(F("success!")); Serial.print(F("[SX1280] Distance:\t\t\t")); Serial.print(radio.getRangingResult()); - Serial.println(F(" meters")); + Serial.println(F(" meters (raw)")); } else if (state == RADIOLIB_ERR_RANGING_TIMEOUT) { // timed out waiting for ranging packet diff --git a/src/modules/SX128x/SX1280.cpp b/src/modules/SX128x/SX1280.cpp index 293e588f..3d963c8d 100644 --- a/src/modules/SX128x/SX1280.cpp +++ b/src/modules/SX128x/SX1280.cpp @@ -5,9 +5,9 @@ SX1280::SX1280(Module* mod) : SX1281(mod) { } -int16_t SX1280::range(bool master, uint32_t addr) { +int16_t SX1280::range(bool master, uint32_t addr, uint16_t calTable[3][6]) { // start ranging - int16_t state = startRanging(master, addr); + int16_t state = startRanging(master, addr, calTable); RADIOLIB_ASSERT(state); // wait until ranging is finished @@ -31,7 +31,7 @@ int16_t SX1280::range(bool master, uint32_t addr) { return(state); } -int16_t SX1280::startRanging(bool master, uint32_t addr) { +int16_t SX1280::startRanging(bool master, uint32_t addr, uint16_t calTable[3][6]) { // check active modem uint8_t modem = getPacketType(); if(!((modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) || (modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING))) { @@ -86,23 +86,30 @@ int16_t SX1280::startRanging(bool master, uint32_t addr) { state = setDioIrqParams(irqMask, irqDio1); RADIOLIB_ASSERT(state); - // set calibration values - uint8_t index = (_sf >> 4) - 5; - static const uint16_t calTable[3][6] = { + // this is the default calibration from AN1200.29 + uint16_t calTbl[3][6] = { { 10299, 10271, 10244, 10242, 10230, 10246 }, { 11486, 11474, 11453, 11426, 11417, 11401 }, { 13308, 13493, 13528, 13515, 13430, 13376 } }; + + // check if user provided some custom calibration + if(calTable != NULL) { + memcpy(calTbl, calTable, sizeof(calTbl)); + } + + // set calibration values + uint8_t index = (_sf >> 4) - 5; uint16_t val = 0; switch(_bw) { case(RADIOLIB_SX128X_LORA_BW_406_25): - val = calTable[0][index]; + val = calTbl[0][index]; break; case(RADIOLIB_SX128X_LORA_BW_812_50): - val = calTable[1][index]; + val = calTbl[1][index]; break; case(RADIOLIB_SX128X_LORA_BW_1625_00): - val = calTable[2][index]; + val = calTbl[2][index]; break; default: return(RADIOLIB_ERR_INVALID_BANDWIDTH); diff --git a/src/modules/SX128x/SX1280.h b/src/modules/SX128x/SX1280.h index f72d125a..10f48ab1 100644 --- a/src/modules/SX128x/SX1280.h +++ b/src/modules/SX128x/SX1280.h @@ -30,9 +30,11 @@ class SX1280: public SX1281 { \param addr Ranging address to be used. + \param calTable Ranging calibration table - set to NULL to use the default. + \returns \ref status_codes */ - int16_t range(bool master, uint32_t addr); + int16_t range(bool master, uint32_t addr, uint16_t calTable[3][6] = NULL); /*! \brief Interrupt-driven ranging method. @@ -41,9 +43,11 @@ class SX1280: public SX1281 { \param addr Ranging address to be used. + \param calTable Ranging calibration table - set to NULL to use the default. + \returns \ref status_codes */ - int16_t startRanging(bool master, uint32_t addr); + int16_t startRanging(bool master, uint32_t addr, uint16_t calTable[3][6] = NULL); /*! \brief Gets ranging result of the last ranging exchange.