Add weighted tx delay for flooding router

This commit is contained in:
Jm Casler 2022-03-14 17:47:01 -07:00
parent bb15a001f7
commit 3816a2fbe0
4 changed files with 66 additions and 2 deletions

View File

@ -180,7 +180,38 @@ uint32_t RadioInterface::getTxDelayMsec()
*/ */
// const uint32_t MAX_TX_WAIT_MSEC = 2000; // stress test would still fail occasionally with 1000 // const uint32_t MAX_TX_WAIT_MSEC = 2000; // stress test would still fail occasionally with 1000
return random(MIN_TX_WAIT_MSEC, shortPacketMsec); return random((MIN_TX_WAIT_MSEC), (MIN_TX_WAIT_MSEC + shortPacketMsec));
}
/** The delay to use when we want to send something but the ether is busy */
uint32_t RadioInterface::getTxDelayMsecWeighted(float snr)
{
/** At the low end we want to pick a delay large enough that anyone who just completed sending (some other node)
* has had enough time to switch their radio back into receive mode.
*/
const uint32_t MIN_TX_WAIT_MSEC = 100;
// The minimum value for a LoRa SNR
const uint32_t SNR_MIN = -20;
// The maximum value for a LoRa SNR
const uint32_t SNR_MAX = 15;
// high SNR = Long Delay
// low SNR = Short Delay
uint32_t delay = 0;
if (radioConfig.preferences.role == Role_Router) {
delay = map(snr, SNR_MIN, SNR_MAX, MIN_TX_WAIT_MSEC, (MIN_TX_WAIT_MSEC + (shortPacketMsec / 2)));
DEBUG_MSG("rx_snr found in packet. As a router, setting tx delay:%d\n", delay);
} else {
delay = map(snr, SNR_MIN, SNR_MAX, MIN_TX_WAIT_MSEC + (shortPacketMsec / 2), (MIN_TX_WAIT_MSEC + shortPacketMsec * 2));
DEBUG_MSG("rx_snr found in packet. Setting tx delay:%d\n", delay);
}
return delay;
} }
void printPacket(const char *prefix, const MeshPacket *p) void printPacket(const char *prefix, const MeshPacket *p)

View File

@ -129,6 +129,10 @@ class RadioInterface
/** The delay to use when we want to send something but the ether is busy */ /** The delay to use when we want to send something but the ether is busy */
uint32_t getTxDelayMsec(); uint32_t getTxDelayMsec();
/** The delay to use when we want to send something but the ether is busy. Use a weighted scale based on SNR */
uint32_t getTxDelayMsecWeighted(float snr);
/** /**
* Calculate airtime per * Calculate airtime per
* https://www.rs-online.com/designspark/rel-assets/ds-assets/uploads/knowledge-items/application-notes-for-the-internet-of-things/LoRa%20Design%20Guide.pdf * https://www.rs-online.com/designspark/rel-assets/ds-assets/uploads/knowledge-items/application-notes-for-the-internet-of-things/LoRa%20Design%20Guide.pdf

View File

@ -113,7 +113,19 @@ ErrorCode RadioLibInterface::send(MeshPacket *p)
// We want all sending/receiving to be done by our daemon thread, We use a delay here because this packet might have been sent // We want all sending/receiving to be done by our daemon thread, We use a delay here because this packet might have been sent
// in response to a packet we just received. So we want to make sure the other side has had a chance to reconfigure its radio // in response to a packet we just received. So we want to make sure the other side has had a chance to reconfigure its radio
/* We assume if rx_snr = 0 and rx_rssi = 0, the packet was not generated locally.
* This assumption is valid because of the offset generated by the radio to account for the noise
* floor.
*/
if (p->rx_snr == 0 && p->rx_rssi == 0) {
startTransmitTimer(true); startTransmitTimer(true);
} else {
// If there is a SNR, start a timer scaled based on that SNR.
DEBUG_MSG("rx_snr found. hop_limit:%d rx_snr:%f\n", p->hop_limit, p->rx_snr);
startTransmitTimerSNR(p->rx_snr);
}
return res; return res;
#else #else
@ -208,6 +220,16 @@ void RadioLibInterface::startTransmitTimer(bool withDelay)
} }
} }
void RadioLibInterface::startTransmitTimerSNR(float snr)
{
// If we have work to do and the timer wasn't already scheduled, schedule it now
if (!txQueue.empty()) {
uint32_t delay = getTxDelayMsecWeighted(snr);
// DEBUG_MSG("xmit timer %d\n", delay);
notifyLater(delay, TRANSMIT_DELAY_COMPLETED, false); // This will implicitly enable
}
}
void RadioLibInterface::handleTransmitInterrupt() void RadioLibInterface::handleTransmitInterrupt()
{ {
// DEBUG_MSG("handling lora TX interrupt\n"); // DEBUG_MSG("handling lora TX interrupt\n");

View File

@ -148,6 +148,13 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
* */ * */
void startTransmitTimer(bool withDelay = true); void startTransmitTimer(bool withDelay = true);
/** if we have something waiting to send, start a short scaled timer based on SNR so we can come check for collision before actually doing
* the transmit
*
* If the timer was already running, we just wait for that one to occur.
* */
void startTransmitTimerSNR(float snr);
void handleTransmitInterrupt(); void handleTransmitInterrupt();
void handleReceiveInterrupt(); void handleReceiveInterrupt();