Browse Source

0.8.16

* updated heuristic #1080 #1259
* fix compile opendtufusion fusion ethernet
pull/1262/head
lumapu 1 year ago
parent
commit
240be8cd98
  1. 2
      src/CHANGES.md
  2. 34
      src/hm/Communication.h
  3. 94
      src/hm/Heuristic.h
  4. 15
      src/hm/HeuristicInv.h
  5. 4
      src/hm/hmRadio.h

2
src/CHANGES.md

@ -2,6 +2,8 @@
## 0.8.16 - 2023-12-09 ## 0.8.16 - 2023-12-09
* fix crash if NRF is not enabled * fix crash if NRF is not enabled
* updated heuristic #1080 #1259
* fix compile opendtufusion fusion ethernet
## 0.8.15 - 2023-12-09 ## 0.8.15 - 2023-12-09
* added support for opendtufusion fusion ethernet shield #886 * added support for opendtufusion fusion ethernet shield #886

34
src/hm/Communication.h

@ -88,8 +88,7 @@ class Communication : public CommQueue<> {
} else } else
q->iv->radio->prepareDevInformCmd(q->iv, q->cmd, q->ts, q->iv->alarmLastId, false); 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 = millis() + timeout;
mWaitTimeout_min = millis() + timeout_min; mWaitTimeout_min = millis() + timeout_min;
mIsResend = false; mIsResend = false;
@ -115,8 +114,7 @@ class Communication : public CommQueue<> {
} }
mFirstTry = false; mFirstTry = false;
mlastTO_min = timeout_min; mlastTO_min = timeout_min;
if(!mHeu.getTestModeEnabled(q->iv)) q->iv->radioStatistics.retransmits++; // got nothing
q->iv->radioStatistics.retransmits++; // got nothing
mState = States::START; mState = States::START;
break; break;
} }
@ -166,6 +164,7 @@ class Communication : public CommQueue<> {
DBGPRINT(String(p->ch)); DBGPRINT(String(p->ch));
DBGPRINT(F(" ")); DBGPRINT(F(" "));
} else { } else {
DBGPRINT(F(" "));
DBGPRINT(String(p->rssi)); DBGPRINT(String(p->rssi));
DBGPRINT(F("dBm | ")); DBGPRINT(F("dBm | "));
} }
@ -180,8 +179,7 @@ class Communication : public CommQueue<> {
} }
if(checkIvSerial(&p->packet[1], q->iv)) { 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 if (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command
parseFrame(p); parseFrame(p);
@ -193,8 +191,7 @@ class Communication : public CommQueue<> {
parseMiFrame(p, q); parseMiFrame(p, q);
} }
} else { } 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")); DPRINTLN(DBG_WARN, F("Inverter serial does not match"));
mWaitTimeout = millis() + timeout; mWaitTimeout = millis() + timeout;
} }
@ -370,8 +367,7 @@ class Communication : public CommQueue<> {
DBGPRINT(F("CRC Error ")); DBGPRINT(F("CRC Error "));
if(q->attempts == 0) { if(q->attempts == 0) {
DBGPRINTLN(F("-> Fail")); 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();*/ cmdDone();*/
closeRequest(q->iv, false, false); closeRequest(q->iv, false, false);
@ -420,8 +416,7 @@ class Communication : public CommQueue<> {
DBGPRINT(String(rec->pyldLen)); DBGPRINT(String(rec->pyldLen));
DBGPRINTLN(F(" bytes")); DBGPRINTLN(F(" bytes"));
} }
/*if(!mHeu.getTestModeEnabled()) /*q->iv->radioStatistics.rxFail++;*/
q->iv->radioStatistics.rxFail++;*/
closeRequest(q->iv, false, false); closeRequest(q->iv, false, false);
return; return;
@ -464,15 +459,12 @@ class Communication : public CommQueue<> {
// ordering of lines is relevant for statistics // ordering of lines is relevant for statistics
if(succeeded) { if(succeeded) {
mHeu.setGotAll(iv); mHeu.setGotAll(iv);
if(!mHeu.getTestModeEnabled(iv)) iv->radioStatistics.rxSuccess++;
iv->radioStatistics.rxSuccess++;
} else if(iv->mGotFragment) { } else if(iv->mGotFragment) {
mHeu.setGotFragment(iv); mHeu.setGotFragment(iv);
if(!mHeu.getTestModeEnabled(iv)) iv->radioStatistics.rxFail++; // got no complete payload
iv->radioStatistics.rxFail++; // got no complete payload
} else { } else {
if(!mHeu.getTestModeEnabled(iv)) iv->radioStatistics.rxFailNoAnser++; // got nothing
iv->radioStatistics.rxFailNoAnser++; // got nothing
mHeu.setGotNothing(iv); mHeu.setGotNothing(iv);
mWaitTimeout = millis() + WAIT_GAP_TIMEOUT; mWaitTimeout = millis() + WAIT_GAP_TIMEOUT;
} }
@ -682,12 +674,10 @@ class Communication : public CommQueue<> {
if(q->iv->miMultiParts == 7) { if(q->iv->miMultiParts == 7) {
mHeu.setGotAll(q->iv); mHeu.setGotAll(q->iv);
if(!mHeu.getTestModeEnabled(q->iv)) q->iv->radioStatistics.rxSuccess++;
q->iv->radioStatistics.rxSuccess++;
} else } else
mHeu.setGotFragment(q->iv); 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->radioStatistics.retransmits++;
q->iv->radio->sendCmdPacket(q->iv, cmd, 0x00, true); q->iv->radio->sendCmdPacket(q->iv, cmd, 0x00, true);

94
src/hm/Heuristic.h

@ -10,61 +10,79 @@
#include "hmInverter.h" #include "hmInverter.h"
#include "HeuristicInv.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 { class Heuristic {
public: public:
uint8_t getTxCh(Inverter<> *iv) { uint8_t getTxCh(Inverter<> *iv) {
if((IV_HMS == iv->ivGen) || (IV_HMT == iv->ivGen)) if((IV_HMS == iv->ivGen) || (IV_HMT == iv->ivGen))
return 0; // not used for these inverter types return 0; // not used for these inverter types
uint8_t bestId = 0; HeuristicInv *ih = &iv->heuristics;
int8_t bestQuality = -6;
for(uint8_t i = 0; i < RF_MAX_CHANNEL_ID; i++) { // start with the next index: round robbin in case of same 'best' quality
if(iv->heuristics.txRfQuality[i] > bestQuality) { uint8_t curId = (ih->txRfChId + 1) % RF_MAX_CHANNEL_ID;
bestQuality = iv->heuristics.txRfQuality[i]; uint8_t lastBestId = ih->txRfChId;
bestId = i; 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) { if(ih->testPeriodSendCnt < 0xff)
DPRINTLN(DBG_INFO, F("heuristic test mode")); ih->testPeriodSendCnt++;
iv->heuristics.testIdx = (iv->heuristics.testIdx + 1) % RF_MAX_CHANNEL_ID;
if (iv->heuristics.testIdx == bestId) if((ih->txRfChId == lastBestId) && (ih->testPeriodSendCnt >= RF_TEST_PERIOD_MAX_SEND_CNT)) {
iv->heuristics.testIdx = (iv->heuristics.testIdx + 1) % RF_MAX_CHANNEL_ID; 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') // give it a fair chance but remember old status in case of immediate fail
iv->heuristics.storedIdx = iv->heuristics.txRfQuality[iv->heuristics.testIdx]; ih->txRfChId = ih->testChId;
iv->heuristics.txRfQuality[iv->heuristics.testIdx] = bestQuality; 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; // start new test period
} else ih->testPeriodSendCnt = 0;
iv->heuristics.txRfChId = bestId; 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) { void setGotAll(Inverter<> *iv) {
updateQuality(iv, 2); // GOOD updateQuality(iv, 2); // GOOD
iv->heuristics.testEn = false;
} }
void setGotFragment(Inverter<> *iv) { void setGotFragment(Inverter<> *iv) {
updateQuality(iv, 1); // OK updateQuality(iv, 1); // OK
iv->heuristics.testEn = false;
} }
void setGotNothing(Inverter<> *iv) { void setGotNothing(Inverter<> *iv) {
if(RF_NA != iv->heuristics.storedIdx) { HeuristicInv *ih = &iv->heuristics;
// 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; if(RF_TX_TEST_CHAN_1ST_USE == ih->testChId) {
iv->heuristics.storedIdx = RF_NA; // immediate fail
ih->testChId = ih->txRfChId; // reset to best
return;
} }
if(!iv->heuristics.testEn) { if(ih->testPeriodFailCnt < 0xff)
updateQuality(iv, -2); // BAD ih->testPeriodFailCnt++;
iv->heuristics.testEn = true;
} else updateQuality(iv, -2); // BAD
iv->heuristics.testEn = false;
} }
void printStatus(Inverter<> *iv) { void printStatus(Inverter<> *iv) {
@ -86,17 +104,15 @@ class Heuristic {
DBGPRINTLN(String(iv->config->powerLevel)); DBGPRINTLN(String(iv->config->powerLevel));
} }
bool getTestModeEnabled(Inverter<> *iv) {
return iv->heuristics.testEn;
}
private: private:
void updateQuality(Inverter<> *iv, uint8_t quality) { void updateQuality(Inverter<> *iv, uint8_t quality) {
iv->heuristics.txRfQuality[iv->heuristics.txRfChId] += quality; HeuristicInv *ih = &iv->heuristics;
if(iv->heuristics.txRfQuality[iv->heuristics.txRfChId] > RF_MAX_QUALITY)
iv->heuristics.txRfQuality[iv->heuristics.txRfChId] = RF_MAX_QUALITY; ih->txRfQuality[ih->txRfChId] += quality;
else if(iv->heuristics.txRfQuality[iv->heuristics.txRfChId] < RF_MIN_QUALTIY) if(ih->txRfQuality[ih->txRfChId] > RF_MAX_QUALITY)
iv->heuristics.txRfQuality[iv->heuristics.txRfChId] = RF_MIN_QUALTIY; 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) { inline uint8_t id2Ch(uint8_t id) {

15
src/hm/HeuristicInv.h

@ -13,12 +13,17 @@
class HeuristicInv { class HeuristicInv {
public: public:
int8_t txRfQuality[5]; // heuristics tx quality (check 'Heuristics.h') HeuristicInv() {
uint8_t txRfChId; // RF TX channel id memset(txRfQuality, -6, RF_MAX_CHANNEL_ID);
}
bool testEn = false; public:
uint8_t testIdx = 0; int8_t txRfQuality[RF_MAX_CHANNEL_ID]; // heuristics tx quality (check 'Heuristics.h')
int8_t storedIdx = RF_NA; uint8_t txRfChId = 0; // RF TX channel id
uint8_t testPeriodSendCnt = 0;
uint8_t testPeriodFailCnt = 0;
uint8_t testChId = 0;
}; };
#endif /*__HEURISTIC_INV_H__*/ #endif /*__HEURISTIC_INV_H__*/

4
src/hm/hmRadio.h

@ -35,7 +35,11 @@ class HmRadio : public Radio {
HmRadio() { HmRadio() {
mDtuSn = DTU_SN; mDtuSn = DTU_SN;
mIrqRcvd = false; 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)); mNrf24.reset(new RF24(CE_PIN, CS_PIN, SPI_SPEED));
#endif
} }
~HmRadio() {} ~HmRadio() {}

Loading…
Cancel
Save