From 240be8cd98dc75c103d300be22d46ffbb1d26626 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 9 Dec 2023 17:09:05 +0100 Subject: [PATCH] 0.8.16 * updated heuristic #1080 #1259 * fix compile opendtufusion fusion ethernet --- src/CHANGES.md | 2 + src/hm/Communication.h | 34 ++++++--------- src/hm/Heuristic.h | 94 ++++++++++++++++++++++++------------------ src/hm/HeuristicInv.h | 15 ++++--- src/hm/hmRadio.h | 4 ++ 5 files changed, 83 insertions(+), 66 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 7186a4366..6cba50404 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,8 @@ ## 0.8.16 - 2023-12-09 * fix crash if NRF is not enabled +* updated heuristic #1080 #1259 +* fix compile opendtufusion fusion ethernet ## 0.8.15 - 2023-12-09 * added support for opendtufusion fusion ethernet shield #886 diff --git a/src/hm/Communication.h b/src/hm/Communication.h index 393330bae..9d92992fa 100644 --- a/src/hm/Communication.h +++ b/src/hm/Communication.h @@ -88,8 +88,7 @@ class Communication : public CommQueue<> { } else q->iv->radio->prepareDevInformCmd(q->iv, q->cmd, q->ts, q->iv->alarmLastId, false); - if(!mHeu.getTestModeEnabled(q->iv)) - q->iv->radioStatistics.txCnt++; + q->iv->radioStatistics.txCnt++; mWaitTimeout = millis() + timeout; mWaitTimeout_min = millis() + timeout_min; mIsResend = false; @@ -115,8 +114,7 @@ class Communication : public CommQueue<> { } mFirstTry = false; mlastTO_min = timeout_min; - if(!mHeu.getTestModeEnabled(q->iv)) - q->iv->radioStatistics.retransmits++; // got nothing + q->iv->radioStatistics.retransmits++; // got nothing mState = States::START; break; } @@ -166,6 +164,7 @@ class Communication : public CommQueue<> { DBGPRINT(String(p->ch)); DBGPRINT(F(" ")); } else { + DBGPRINT(F(" ")); DBGPRINT(String(p->rssi)); DBGPRINT(F("dBm | ")); } @@ -180,8 +179,7 @@ class Communication : public CommQueue<> { } if(checkIvSerial(&p->packet[1], q->iv)) { - if(!mHeu.getTestModeEnabled(q->iv)) - q->iv->radioStatistics.frmCnt++; + q->iv->radioStatistics.frmCnt++; if (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command parseFrame(p); @@ -193,8 +191,7 @@ class Communication : public CommQueue<> { parseMiFrame(p, q); } } else { - if(!mHeu.getTestModeEnabled(q->iv)) - q->iv->radioStatistics.rxFail++; // got no complete payload + q->iv->radioStatistics.rxFail++; // got no complete payload DPRINTLN(DBG_WARN, F("Inverter serial does not match")); mWaitTimeout = millis() + timeout; } @@ -370,8 +367,7 @@ class Communication : public CommQueue<> { DBGPRINT(F("CRC Error ")); if(q->attempts == 0) { DBGPRINTLN(F("-> Fail")); - /*if(!mHeu.getTestModeEnabled()) - q->iv->radioStatistics.rxFail++; // got fragments but not complete response + /*q->iv->radioStatistics.rxFail++; // got fragments but not complete response cmdDone();*/ closeRequest(q->iv, false, false); @@ -420,8 +416,7 @@ class Communication : public CommQueue<> { DBGPRINT(String(rec->pyldLen)); DBGPRINTLN(F(" bytes")); } - /*if(!mHeu.getTestModeEnabled()) - q->iv->radioStatistics.rxFail++;*/ + /*q->iv->radioStatistics.rxFail++;*/ closeRequest(q->iv, false, false); return; @@ -464,15 +459,12 @@ class Communication : public CommQueue<> { // ordering of lines is relevant for statistics if(succeeded) { mHeu.setGotAll(iv); - if(!mHeu.getTestModeEnabled(iv)) - iv->radioStatistics.rxSuccess++; + iv->radioStatistics.rxSuccess++; } else if(iv->mGotFragment) { mHeu.setGotFragment(iv); - if(!mHeu.getTestModeEnabled(iv)) - iv->radioStatistics.rxFail++; // got no complete payload + iv->radioStatistics.rxFail++; // got no complete payload } else { - if(!mHeu.getTestModeEnabled(iv)) - iv->radioStatistics.rxFailNoAnser++; // got nothing + iv->radioStatistics.rxFailNoAnser++; // got nothing mHeu.setGotNothing(iv); mWaitTimeout = millis() + WAIT_GAP_TIMEOUT; } @@ -682,12 +674,10 @@ class Communication : public CommQueue<> { if(q->iv->miMultiParts == 7) { mHeu.setGotAll(q->iv); - if(!mHeu.getTestModeEnabled(q->iv)) - q->iv->radioStatistics.rxSuccess++; + q->iv->radioStatistics.rxSuccess++; } else mHeu.setGotFragment(q->iv); - /*if(!mHeu.getTestModeEnabled()) - iv->radioStatistics.rxFail++; // got no complete payload*/ + /*iv->radioStatistics.rxFail++; // got no complete payload*/ //q->iv->radioStatistics.retransmits++; q->iv->radio->sendCmdPacket(q->iv, cmd, 0x00, true); diff --git a/src/hm/Heuristic.h b/src/hm/Heuristic.h index c75cf5452..c0101e623 100644 --- a/src/hm/Heuristic.h +++ b/src/hm/Heuristic.h @@ -10,61 +10,79 @@ #include "hmInverter.h" #include "HeuristicInv.h" +#define RF_TEST_PERIOD_MAX_SEND_CNT 50 +#define RF_TEST_PERIOD_MAX_FAIL_CNT 5 + +#define RF_TX_TEST_CHAN_1ST_USE 0xff + class Heuristic { public: uint8_t getTxCh(Inverter<> *iv) { if((IV_HMS == iv->ivGen) || (IV_HMT == iv->ivGen)) return 0; // not used for these inverter types - uint8_t bestId = 0; - int8_t bestQuality = -6; - for(uint8_t i = 0; i < RF_MAX_CHANNEL_ID; i++) { - if(iv->heuristics.txRfQuality[i] > bestQuality) { - bestQuality = iv->heuristics.txRfQuality[i]; - bestId = i; - } + HeuristicInv *ih = &iv->heuristics; + + // start with the next index: round robbin in case of same 'best' quality + uint8_t curId = (ih->txRfChId + 1) % RF_MAX_CHANNEL_ID; + uint8_t lastBestId = ih->txRfChId; + ih->txRfChId = curId; + curId = (curId + 1) % RF_MAX_CHANNEL_ID; + for(uint8_t i = 1; i < RF_MAX_CHANNEL_ID; i++) { + if(ih->txRfQuality[curId] > ih->txRfQuality[ih->txRfChId]) + ih->txRfChId = curId; + curId = (curId + 1) % RF_MAX_CHANNEL_ID; } - if(iv->heuristics.testEn) { - DPRINTLN(DBG_INFO, F("heuristic test mode")); - iv->heuristics.testIdx = (iv->heuristics.testIdx + 1) % RF_MAX_CHANNEL_ID; + if(ih->testPeriodSendCnt < 0xff) + ih->testPeriodSendCnt++; - if (iv->heuristics.testIdx == bestId) - iv->heuristics.testIdx = (iv->heuristics.testIdx + 1) % RF_MAX_CHANNEL_ID; + if((ih->txRfChId == lastBestId) && (ih->testPeriodSendCnt >= RF_TEST_PERIOD_MAX_SEND_CNT)) { + if(ih->testPeriodFailCnt > RF_TEST_PERIOD_MAX_FAIL_CNT) { + // try round robbin another chan and see if it works even better + ih->testChId = (ih->testChId + 1) % RF_MAX_CHANNEL_ID; + if(ih->testChId = ih->txRfChId) + ih->testChId = (ih->testChId + 1) % RF_MAX_CHANNEL_ID; - // test channel get's quality of best channel (maybe temporarily, see in 'setGotNothing') - iv->heuristics.storedIdx = iv->heuristics.txRfQuality[iv->heuristics.testIdx]; - iv->heuristics.txRfQuality[iv->heuristics.testIdx] = bestQuality; + // give it a fair chance but remember old status in case of immediate fail + ih->txRfChId = ih->testChId; + ih->testChId = RF_TX_TEST_CHAN_1ST_USE; // mark the chan as a test and as 1st use during new test period + DPRINTLN(DBG_INFO, "Test CH " + String(id2Ch(ih->txRfChId))); + } - iv->heuristics.txRfChId = iv->heuristics.testIdx; - } else - iv->heuristics.txRfChId = bestId; + // start new test period + ih->testPeriodSendCnt = 0; + ih->testPeriodFailCnt = 0; + } else if(ih->txRfChId != lastBestId) { + // start new test period + ih->testPeriodSendCnt = 0; + ih->testPeriodFailCnt = 0; + } - return id2Ch(iv->heuristics.txRfChId); + return id2Ch(ih->txRfChId); } void setGotAll(Inverter<> *iv) { updateQuality(iv, 2); // GOOD - iv->heuristics.testEn = false; } void setGotFragment(Inverter<> *iv) { updateQuality(iv, 1); // OK - iv->heuristics.testEn = false; } void setGotNothing(Inverter<> *iv) { - if(RF_NA != iv->heuristics.storedIdx) { - // if communication fails on first try with temporarily good level, revert it back to its original level - iv->heuristics.txRfQuality[iv->heuristics.txRfChId] = iv->heuristics.storedIdx; - iv->heuristics.storedIdx = RF_NA; + HeuristicInv *ih = &iv->heuristics; + + if(RF_TX_TEST_CHAN_1ST_USE == ih->testChId) { + // immediate fail + ih->testChId = ih->txRfChId; // reset to best + return; } - if(!iv->heuristics.testEn) { - updateQuality(iv, -2); // BAD - iv->heuristics.testEn = true; - } else - iv->heuristics.testEn = false; + if(ih->testPeriodFailCnt < 0xff) + ih->testPeriodFailCnt++; + + updateQuality(iv, -2); // BAD } void printStatus(Inverter<> *iv) { @@ -86,17 +104,15 @@ class Heuristic { DBGPRINTLN(String(iv->config->powerLevel)); } - bool getTestModeEnabled(Inverter<> *iv) { - return iv->heuristics.testEn; - } - private: void updateQuality(Inverter<> *iv, uint8_t quality) { - iv->heuristics.txRfQuality[iv->heuristics.txRfChId] += quality; - if(iv->heuristics.txRfQuality[iv->heuristics.txRfChId] > RF_MAX_QUALITY) - iv->heuristics.txRfQuality[iv->heuristics.txRfChId] = RF_MAX_QUALITY; - else if(iv->heuristics.txRfQuality[iv->heuristics.txRfChId] < RF_MIN_QUALTIY) - iv->heuristics.txRfQuality[iv->heuristics.txRfChId] = RF_MIN_QUALTIY; + HeuristicInv *ih = &iv->heuristics; + + ih->txRfQuality[ih->txRfChId] += quality; + if(ih->txRfQuality[ih->txRfChId] > RF_MAX_QUALITY) + ih->txRfQuality[ih->txRfChId] = RF_MAX_QUALITY; + else if(ih->txRfQuality[ih->txRfChId] < RF_MIN_QUALTIY) + ih->txRfQuality[ih->txRfChId] = RF_MIN_QUALTIY; } inline uint8_t id2Ch(uint8_t id) { diff --git a/src/hm/HeuristicInv.h b/src/hm/HeuristicInv.h index 1ca9c4489..d3c2cdf03 100644 --- a/src/hm/HeuristicInv.h +++ b/src/hm/HeuristicInv.h @@ -13,12 +13,17 @@ class HeuristicInv { public: - int8_t txRfQuality[5]; // heuristics tx quality (check 'Heuristics.h') - uint8_t txRfChId; // RF TX channel id + HeuristicInv() { + memset(txRfQuality, -6, RF_MAX_CHANNEL_ID); + } - bool testEn = false; - uint8_t testIdx = 0; - int8_t storedIdx = RF_NA; + public: + int8_t txRfQuality[RF_MAX_CHANNEL_ID]; // heuristics tx quality (check 'Heuristics.h') + uint8_t txRfChId = 0; // RF TX channel id + + uint8_t testPeriodSendCnt = 0; + uint8_t testPeriodFailCnt = 0; + uint8_t testChId = 0; }; #endif /*__HEURISTIC_INV_H__*/ diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index e227efe11..618f8e9ab 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -35,7 +35,11 @@ class HmRadio : public Radio { HmRadio() { mDtuSn = DTU_SN; mIrqRcvd = false; + #if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(ETHERNET) + mNrf24.reset(new RF24()); + #else mNrf24.reset(new RF24(CE_PIN, CS_PIN, SPI_SPEED)); + #endif } ~HmRadio() {}