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();
|
state = this->phyLayer->launchMode();
|
||||||
|
RadioLibTime_t spiEnd = mod->hal->millis();
|
||||||
|
this->launchDuration = spiEnd - spiStart;
|
||||||
RADIOLIB_ASSERT(state);
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
// sleep for the duration of the transmission
|
// 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();
|
state = this->phyLayer->launchMode();
|
||||||
|
RadioLibTime_t spiEnd = mod->hal->millis();
|
||||||
|
this->launchDuration = spiEnd - spiStart;
|
||||||
RADIOLIB_ASSERT(state);
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
// sleep for the duration of the transmission
|
// 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);
|
state = this->phyLayer->stageMode(RADIOLIB_RADIO_MODE_RX, &modeCfg);
|
||||||
RADIOLIB_ASSERT(state);
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
// wait for the start of the Rx window
|
// calculate time at which the window should open
|
||||||
RadioLibTime_t waitLen = tReference + dlDelays[window] - mod->hal->millis();
|
RadioLibTime_t tWindow = tReference + dlDelays[window];
|
||||||
// make sure that no underflow occured; if so, clip the delay (although this will likely miss any downlink)
|
// 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]) {
|
if(waitLen > dlDelays[window]) {
|
||||||
waitLen = dlDelays[window];
|
return(RADIOLIB_ERR_NO_RX_WINDOW);
|
||||||
}
|
|
||||||
// the waiting duration is shortened a bit to cover any possible timing errors
|
|
||||||
if(waitLen > this->scanGuard) {
|
|
||||||
waitLen -= this->scanGuard;
|
|
||||||
}
|
}
|
||||||
this->sleepDelay(waitLen);
|
this->sleepDelay(waitLen);
|
||||||
|
|
||||||
|
@ -1449,11 +1456,17 @@ int16_t LoRaWANNode::receiveCommon(uint8_t dir, const LoRaWANChannel_t* dlChanne
|
||||||
state = this->phyLayer->launchMode();
|
state = this->phyLayer->launchMode();
|
||||||
tOpen = mod->hal->millis();
|
tOpen = mod->hal->millis();
|
||||||
RADIOLIB_ASSERT(state);
|
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)
|
// wait for the timeout to complete (and a small delay in case the RxTimeout interrupt needs to fire)
|
||||||
this->sleepDelay(timeoutHost / 1000 + this->scanGuard / 2);
|
this->sleepDelay(timeoutHost / 1000);
|
||||||
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Closing Rx%d window", window);
|
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
|
// if the IRQ bit for Rx Timeout is not set, something is received, so stop the windows
|
||||||
timedOut = this->phyLayer->checkIrq(RADIOLIB_IRQ_TIMEOUT);
|
timedOut = this->phyLayer->checkIrq(RADIOLIB_IRQ_TIMEOUT);
|
||||||
|
@ -1485,7 +1498,7 @@ int16_t LoRaWANNode::receiveCommon(uint8_t dir, const LoRaWANChannel_t* dlChanne
|
||||||
while(!downlinkAction) {
|
while(!downlinkAction) {
|
||||||
mod->hal->yield();
|
mod->hal->yield();
|
||||||
// stay in Rx mode for the maximum allowed Time-on-Air plus small grace period
|
// 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!");
|
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Downlink missing!");
|
||||||
downlinkComplete = false;
|
downlinkComplete = false;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -865,7 +865,7 @@ class LoRaWANNode {
|
||||||
500 is the **maximum** value, but it is not a good idea to go anywhere near that.
|
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.
|
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
|
#if !RADIOLIB_GODMODE
|
||||||
protected:
|
protected:
|
||||||
|
@ -976,6 +976,9 @@ class LoRaWANNode {
|
||||||
// timestamp when the Rx1/2 windows were closed (timeout or uplink received)
|
// timestamp when the Rx1/2 windows were closed (timeout or uplink received)
|
||||||
RadioLibTime_t rxDelayEnd = 0;
|
RadioLibTime_t rxDelayEnd = 0;
|
||||||
|
|
||||||
|
// duration of SPI transaction for phyLayer->launchMode()
|
||||||
|
RadioLibTime_t launchDuration = 0;
|
||||||
|
|
||||||
// device status - battery level
|
// device status - battery level
|
||||||
uint8_t battLevel = 0xFF;
|
uint8_t battLevel = 0xFF;
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue