kopia lustrzana https://github.com/jgromes/RadioLib
[LoRaWAN] Improve window timing accuracy (#1491)
rodzic
3002cdf371
commit
9209afcf86
|
@ -930,8 +930,11 @@ int16_t LoRaWANNode::activateOTAA(uint8_t joinDr, LoRaWANJoinEvent_t *joinEvent)
|
|||
}
|
||||
}
|
||||
|
||||
// start transmission
|
||||
// start transmission, and time the duration of launchMode() to offset window timing
|
||||
RadioLibTime_t spiStart = mod->hal->millis();
|
||||
state = this->phyLayer->launchMode();
|
||||
RadioLibTime_t spiEnd = mod->hal->millis();
|
||||
this->launchDuration = spiEnd - spiStart;
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// sleep for the duration of the transmission
|
||||
|
@ -1345,8 +1348,11 @@ int16_t LoRaWANNode::transmitUplink(const LoRaWANChannel_t* chnl, uint8_t* in, u
|
|||
}
|
||||
}
|
||||
|
||||
// start transmission
|
||||
// start transmission, and time the duration of launchMode() to offset window timing
|
||||
RadioLibTime_t spiStart = mod->hal->millis();
|
||||
state = this->phyLayer->launchMode();
|
||||
RadioLibTime_t spiEnd = mod->hal->millis();
|
||||
this->launchDuration = spiEnd - spiStart;
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// sleep for the duration of the transmission
|
||||
|
@ -1433,15 +1439,16 @@ int16_t LoRaWANNode::receiveCommon(uint8_t dir, const LoRaWANChannel_t* dlChanne
|
|||
state = this->phyLayer->stageMode(RADIOLIB_RADIO_MODE_RX, &modeCfg);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for the start of the Rx window
|
||||
RadioLibTime_t waitLen = tReference + dlDelays[window] - mod->hal->millis();
|
||||
// make sure that no underflow occured; if so, clip the delay (although this will likely miss any downlink)
|
||||
// calculate time at which the window should open
|
||||
RadioLibTime_t tWindow = tReference + dlDelays[window];
|
||||
// wait for the start of the Rx window launch
|
||||
// - the launch of Rx window takes a few milliseconds, so shorten the waitLen a bit (launchDuration)
|
||||
// - the Rx window is padded using scanGuard, so shorten the waitLen a bit (scanGuard / 2)
|
||||
RadioLibTime_t waitLen = tWindow - mod->hal->millis() - this->launchDuration - this->scanGuard / 2;
|
||||
|
||||
// make sure that no underflow occured; if so, there's something weird going on so return an error
|
||||
if(waitLen > dlDelays[window]) {
|
||||
waitLen = dlDelays[window];
|
||||
}
|
||||
// the waiting duration is shortened a bit to cover any possible timing errors
|
||||
if(waitLen > this->scanGuard) {
|
||||
waitLen -= this->scanGuard;
|
||||
return(RADIOLIB_ERR_NO_RX_WINDOW);
|
||||
}
|
||||
this->sleepDelay(waitLen);
|
||||
|
||||
|
@ -1449,11 +1456,17 @@ int16_t LoRaWANNode::receiveCommon(uint8_t dir, const LoRaWANChannel_t* dlChanne
|
|||
state = this->phyLayer->launchMode();
|
||||
tOpen = mod->hal->millis();
|
||||
RADIOLIB_ASSERT(state);
|
||||
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Opening Rx%d window (%d ms timeout)... <-- Rx Delay end ", window, (int)(timeoutHost / 1000 + 2));
|
||||
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Opened Rx%d window (%d ms timeout)... <-- Rx Delay end ", window, (int)(timeoutHost / 1000 + 2));
|
||||
|
||||
// wait for the timeout to complete (and a small additional delay)
|
||||
this->sleepDelay(timeoutHost / 1000 + this->scanGuard / 2);
|
||||
// wait for the timeout to complete (and a small delay in case the RxTimeout interrupt needs to fire)
|
||||
this->sleepDelay(timeoutHost / 1000);
|
||||
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Closing Rx%d window", window);
|
||||
while(mod->hal->millis() - tOpen <= timeoutHost / 1000 + this->scanGuard) {
|
||||
// wait for the DIO interrupt to fire (RxDone or RxTimeout)
|
||||
if(downlinkAction) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if the IRQ bit for Rx Timeout is not set, something is received, so stop the windows
|
||||
timedOut = this->phyLayer->checkIrq(RADIOLIB_IRQ_TIMEOUT);
|
||||
|
@ -1485,7 +1498,7 @@ int16_t LoRaWANNode::receiveCommon(uint8_t dir, const LoRaWANChannel_t* dlChanne
|
|||
while(!downlinkAction) {
|
||||
mod->hal->yield();
|
||||
// stay in Rx mode for the maximum allowed Time-on-Air plus small grace period
|
||||
if(mod->hal->millis() - tOpen > tMax + scanGuard) {
|
||||
if(mod->hal->millis() - tOpen > tMax + this->scanGuard) {
|
||||
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Downlink missing!");
|
||||
downlinkComplete = false;
|
||||
break;
|
||||
|
|
|
@ -865,7 +865,7 @@ class LoRaWANNode {
|
|||
500 is the **maximum** value, but it is not a good idea to go anywhere near that.
|
||||
If you have to go above 50 you probably have a bug somewhere. Check your device timing.
|
||||
*/
|
||||
RadioLibTime_t scanGuard = 5;
|
||||
RadioLibTime_t scanGuard = 10;
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
protected:
|
||||
|
@ -976,6 +976,9 @@ class LoRaWANNode {
|
|||
// timestamp when the Rx1/2 windows were closed (timeout or uplink received)
|
||||
RadioLibTime_t rxDelayEnd = 0;
|
||||
|
||||
// duration of SPI transaction for phyLayer->launchMode()
|
||||
RadioLibTime_t launchDuration = 0;
|
||||
|
||||
// device status - battery level
|
||||
uint8_t battLevel = 0xFF;
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue