Browse Source

Add files via upload

NRF24L01+ Radio send channel evaluation and hopping heuristik (helps to reduces TX retransmits in relation to TX count)
pull/1080/head
oberfritze 2 years ago
committed by GitHub
parent
commit
3d1a946bff
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 19
      src/hm/hmPayload.h
  2. 99
      src/hm/hmRadio.h

19
src/hm/hmPayload.h

@ -25,6 +25,7 @@ typedef struct {
bool requested; bool requested;
bool gotFragment; bool gotFragment;
bool rxTmo; bool rxTmo;
uint8_t lastFragments; // for send quality measurement
} invPayload_t; } invPayload_t;
@ -246,7 +247,13 @@ class HmPayload {
if (!mPayload[iv->id].complete) { if (!mPayload[iv->id].complete) {
bool crcPass, pyldComplete; bool crcPass, pyldComplete;
crcPass = build(iv->id, &pyldComplete); uint8 Fragments;
crcPass = build(iv->id, &pyldComplete, &Fragments);
// evaluate quality of send channel with rcv params
mSys->Radio.evalSendChannelQuality (crcPass, mPayload[iv->id].retransmits,
Fragments, mPayload[iv->id].lastFragments);
mPayload[iv->id].lastFragments = Fragments;
if (!crcPass && !pyldComplete) { // payload not complete if (!crcPass && !pyldComplete) { // payload not complete
if ((mPayload[iv->id].requested) && (retransmit)) { if ((mPayload[iv->id].requested) && (retransmit)) {
if (mPayload[iv->id].retransmits < mMaxRetrans) { if (mPayload[iv->id].retransmits < mMaxRetrans) {
@ -351,6 +358,7 @@ class HmPayload {
} }
iv->doCalculations(); iv->doCalculations();
uint8_t pos = iv->getPosByChFld(CH0, FLD_PAC, rec); uint8_t pos = iv->getPosByChFld(CH0, FLD_PAC, rec);
if (pos != 0xff) { if (pos != 0xff) {
float ac_power = iv->getValue(pos, rec); float ac_power = iv->getValue(pos, rec);
mSys->handle_pac (iv, (uint16_t)(ac_power+0.5f)); mSys->handle_pac (iv, (uint16_t)(ac_power+0.5f));
@ -396,7 +404,7 @@ class HmPayload {
(mCbAlarm)(code, start, endTime); (mCbAlarm)(code, start, endTime);
} }
bool build(uint8_t id, bool *complete) { bool build(uint8_t id, bool *complete, uint8_t *fragments) {
DPRINTLN(DBG_VERBOSE, F("build")); DPRINTLN(DBG_VERBOSE, F("build"));
uint16_t crc = 0xffff, crcRcv = 0x0000; uint16_t crc = 0xffff, crcRcv = 0x0000;
if (mPayload[id].maxPackId > MAX_PAYLOAD_ENTRIES) if (mPayload[id].maxPackId > MAX_PAYLOAD_ENTRIES)
@ -404,9 +412,13 @@ class HmPayload {
// check if all fragments are there // check if all fragments are there
*complete = true; *complete = true;
*fragments = 0;
for (uint8_t i = 0; i < mPayload[id].maxPackId; i++) { for (uint8_t i = 0; i < mPayload[id].maxPackId; i++) {
if(mPayload[id].len[i] == 0) if(mPayload[id].len[i] == 0) {
*complete = false; *complete = false;
} else {
(*fragments)++;
}
} }
if(!*complete) if(!*complete)
return false; return false;
@ -440,6 +452,7 @@ class HmPayload {
mPayload[id].requested = false; mPayload[id].requested = false;
mPayload[id].ts = *mTimestamp; mPayload[id].ts = *mTimestamp;
mPayload[id].rxTmo = true; // design: dont start with complete retransmit mPayload[id].rxTmo = true; // design: dont start with complete retransmit
mPayload[id].lastFragments = 0; // for send channel quality measurement
} }
IApp *mApp; IApp *mApp;

99
src/hm/hmRadio.h

@ -21,6 +21,15 @@
#define ALL_FRAMES 0x80 #define ALL_FRAMES 0x80
#define SINGLE_FRAME 0x81 #define SINGLE_FRAME 0x81
#define SEND_CHANNEL_QUALITY_INTEGRATOR_SIZE 4
#define SEND_CHANNEL_MAX_QUALITY 4
#define SEND_CHANNEL_MIN_QUALITY -6
#define SEND_CHANNEL_QUALITY_GOOD 2
#define SEND_CHANNEL_QUALITY_OK 1
#define SEND_CHANNEL_QUALITY_NEUTRAL 0
#define SEND_CHANNEL_QUALITY_LOW -1
#define SEND_CHANNEL_QUALITY_BAD -2
const char* const rf24AmpPowerNames[] = {"MIN", "LOW", "HIGH", "MAX"}; const char* const rf24AmpPowerNames[] = {"MIN", "LOW", "HIGH", "MAX"};
@ -269,6 +278,82 @@ class HmRadio {
return mNrf24.isPVariant(); return mNrf24.isPVariant();
} }
bool isNewSendChannel ()
{
return mTxChIdx != mTxLastChIdx;
}
uint8_t getNextSendChannelIndex (void)
{
// start with the next index: round robbin in case of same max bad quality for all channels
uint8_t bestIndex = (mTxChIdx + 1) % RF_CHANNELS;
uint8_t curIndex = (bestIndex + 1) % RF_CHANNELS;
uint16_t i;
for (i=1; i<RF_CHANNELS; i++) {
if (mChQuality[curIndex] > mChQuality[bestIndex]) {
bestIndex = curIndex;
}
curIndex = (curIndex + 1) % RF_CHANNELS;
}
return bestIndex;
}
void addSendChannelQuality (int8_t quality)
{
// continous averaging
// assume: mTxChIdx is still the last send channel index used
quality = mChQuality[mTxChIdx] + quality;
if (quality < SEND_CHANNEL_MIN_QUALITY) {
quality = SEND_CHANNEL_MIN_QUALITY;
} else if (quality > SEND_CHANNEL_MAX_QUALITY) {
quality = SEND_CHANNEL_MAX_QUALITY;
}
mChQuality[mTxChIdx] = quality;
}
void evalSendChannelQuality (bool crcPass, uint8_t Retransmits, uint8_t rxFragments,
uint8_t lastRxFragments)
{
if (lastRxFragments == rxFragments) {
// nothing received: send probably lost
if (!Retransmits || isNewSendChannel()) {
// dont overestimate burst distortion
addSendChannelQuality (SEND_CHANNEL_QUALITY_BAD);
}
} else if (!lastRxFragments && crcPass) {
if (!Retransmits || isNewSendChannel()) {
// every fragment received successfull immediately
addSendChannelQuality (SEND_CHANNEL_QUALITY_GOOD);
} else {
// every fragment received successfully
addSendChannelQuality (SEND_CHANNEL_QUALITY_OK);
}
} else if (crcPass) {
if (isNewSendChannel ()) {
// last Fragment successfully received on new send channel
addSendChannelQuality (SEND_CHANNEL_QUALITY_OK);
}
} else if (!Retransmits || isNewSendChannel()) {
// no complete receive for this send channel
addSendChannelQuality (SEND_CHANNEL_QUALITY_LOW);
}
}
void resetSendChannelQuality ()
{
for(uint8_t i = 0; i < RF_CHANNELS; i++) {
mChQuality[mTxChIdx] = 0;
}
}
void dumpSendQuality()
{
for(uint8_t i = 0; i < RF_CHANNELS; i++) {
DBGPRINT(" " + String (mChQuality[i]));
}
}
std::queue<packet_t> mBufCtrl; std::queue<packet_t> mBufCtrl;
uint32_t mSendCnt; uint32_t mSendCnt;
@ -337,22 +422,26 @@ class HmRadio {
len++; len++;
// set TX and RX channels // set TX and RX channels
mTxChIdx = (mTxChIdx + 1) % RF_CHANNELS;
mTxLastChIdx = mTxChIdx;
mTxChIdx = getNextSendChannelIndex ();
mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS; mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS;
if(mSerialDebug) { if(mSerialDebug) {
#ifdef undef
DPRINT(DBG_INFO, F("TX ")); DPRINT(DBG_INFO, F("TX "));
DBGPRINT(String(len)); DBGPRINT(String(len));
#ifdef undef
DBGPRINT("B Ch"); DBGPRINT("B Ch");
DBGPRINT(String(mRfChLst[mTxChIdx])); DBGPRINT(String(mRfChLst[mTxChIdx]));
DBGPRINT(F(" | ")); DBGPRINT(F(" | "));
dumpBuf(mTxBuf, len); dumpBuf(mTxBuf, len);
#else #else
DBGPRINTLN (" Bytes"); DPRINT(DBG_INFO, F("TX (Ch ") + String (mRfChLst[mTxChIdx]) + "), " +
String (len) + " Bytes, Quality:");
dumpSendQuality();
DBGPRINTLN("");
#endif #endif
} }
mNrf24.stopListening(); mNrf24.stopListening();
mNrf24.setChannel(mRfChLst[mTxChIdx]); mNrf24.setChannel(mRfChLst[mTxChIdx]);
mNrf24.openWritingPipe(reinterpret_cast<uint8_t*>(&invId)); mNrf24.openWritingPipe(reinterpret_cast<uint8_t*>(&invId));
@ -368,7 +457,9 @@ class HmRadio {
uint64_t DTU_RADIO_ID; uint64_t DTU_RADIO_ID;
uint8_t mRfChLst[RF_CHANNELS]; uint8_t mRfChLst[RF_CHANNELS];
int8_t mChQuality[RF_CHANNELS];
uint8_t mTxChIdx; uint8_t mTxChIdx;
uint8_t mTxLastChIdx;
uint8_t mRxChIdx; uint8_t mRxChIdx;
SPIClass* mSpi; SPIClass* mSpi;

Loading…
Cancel
Save