Browse Source

different tx-offests for 4ch HM

* discord 0.8.6803
* tx+3 for 4ch-HM, tx+2 for other Inverters
pull/1394/head
rejoe2 12 months ago
committed by GitHub
parent
commit
bba82d8b3a
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      src/hm/CommQueue.h
  2. 9
      src/hm/Communication.h
  3. 15
      src/hm/HeuristicInv.h
  4. 21
      src/hm/hmInverter.h
  5. 43
      src/hm/hmRadio.h
  6. 7
      src/hm/hmSystem.h
  7. 6
      src/hms/cmt2300a.h

2
src/hm/CommQueue.h

@ -12,7 +12,7 @@
#include "../utils/dbg.h" #include "../utils/dbg.h"
#define DEFAULT_ATTEMPS 5 #define DEFAULT_ATTEMPS 5
#define MORE_ATTEMPS_ALARMDATA 0 // 8 #define MORE_ATTEMPS_ALARMDATA 3 // 8
#define MORE_ATTEMPS_GRIDONPROFILEPARA 0 // 5 #define MORE_ATTEMPS_GRIDONPROFILEPARA 0 // 5
template <uint8_t N=100> template <uint8_t N=100>

9
src/hm/Communication.h

@ -140,7 +140,10 @@ class Communication : public CommQueue<> {
if(!q->iv->mGotFragment) { if(!q->iv->mGotFragment) {
if(INV_RADIO_TYPE_CMT == q->iv->ivRadioType) { if(INV_RADIO_TYPE_CMT == q->iv->ivRadioType) {
#if defined(ESP32) #if defined(ESP32)
q->iv->radio->switchFrequency(q->iv, q->iv->radio->getBootFreqMhz() * 1000, (q->iv->config->frequency*FREQ_STEP_KHZ + q->iv->radio->getBaseFreqMhz() * 1000)); if(!q->iv->radio->switchFrequency(q->iv, q->iv->radio->getBootFreqMhz() * 1000, (q->iv->config->frequency*FREQ_STEP_KHZ + q->iv->radio->getBaseFreqMhz() * 1000))) {
DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINTLN(F("switch frequency failed!"));
}
mWaitTime.startTimeMonitor(1000); mWaitTime.startTimeMonitor(1000);
#endif #endif
} else { } else {
@ -418,8 +421,8 @@ class Communication : public CommQueue<> {
if((*frameId & ALL_FRAMES) == ALL_FRAMES) { if((*frameId & ALL_FRAMES) == ALL_FRAMES) {
mMaxFrameId = (*frameId & 0x7f); mMaxFrameId = (*frameId & 0x7f);
/*if(mMaxFrameId > 8) // large payloads, e.g. AlarmData if(mMaxFrameId > 8) // large payloads, e.g. AlarmData
incrAttempt(mMaxFrameId - 6);*/ incrAttempt(mMaxFrameId - 6);
} }
frame_t *f = &mLocalBuf[(*frameId & 0x7f) - 1]; frame_t *f = &mLocalBuf[(*frameId & 0x7f) - 1];

15
src/hm/HeuristicInv.h

@ -14,7 +14,22 @@
class HeuristicInv { class HeuristicInv {
public: public:
HeuristicInv() { HeuristicInv() {
clear();
}
void clear() {
memset(txRfQuality, 0, RF_MAX_CHANNEL_ID); memset(txRfQuality, 0, RF_MAX_CHANNEL_ID);
txRfChId = 0;
lastBestTxChId = 0;
testPeriodSendCnt = 0;
testPeriodFailCnt = 0;
testChId = 0;
saveOldTestQuality = -6;
lastRxFragments = 0;
}
bool isTxAtMax(void) const {
return (RF_MAX_QUALITY == txRfQuality[txRfChId]);
} }
public: public:

21
src/hm/hmInverter.h

@ -193,6 +193,14 @@ class Inverter {
if(mNextLive) if(mNextLive)
cb(RealTimeRunData_Debug, false); // get live data cb(RealTimeRunData_Debug, false); // get live data
else { else {
if(INV_RADIO_TYPE_NRF == ivRadioType) {
// get live data until quality reaches maximum
if(!heuristics.isTxAtMax()) {
cb(RealTimeRunData_Debug, false); // get live data
return;
}
}
if(actPowerLimit == 0xffff) { if(actPowerLimit == 0xffff) {
cb(SystemConfigPara, false); // power limit info cb(SystemConfigPara, false); // power limit info
cb(RealTimeRunData_Debug, false); cb(RealTimeRunData_Debug, false);
@ -201,17 +209,18 @@ class Inverter {
devControlCmd = InitDataState; devControlCmd = InitDataState;
mGetLossInterval = 1; mGetLossInterval = 1;
} else if(0 == getFwVersion()) { } else if(0 == getFwVersion()) {
cb(RealTimeRunData_Debug, false); // get live data
cb(InverterDevInform_All, false); // get firmware version cb(InverterDevInform_All, false); // get firmware version
cb(RealTimeRunData_Debug, false); // get live data
} }
else if(0 == getHwVersion()) { else if(0 == getHwVersion()) {
cb(RealTimeRunData_Debug, false); // get live data
cb(InverterDevInform_Simple, false); // get hardware version cb(InverterDevInform_Simple, false); // get hardware version
} else if((alarmLastId != alarmMesIndex) && (alarmMesIndex != 0)) {
cb(RealTimeRunData_Debug, false); // get live data cb(RealTimeRunData_Debug, false); // get live data
} else if((alarmLastId != alarmMesIndex) && (alarmMesIndex != 0)) {
cb(AlarmData, false); // get last alarms cb(AlarmData, false); // get last alarms
cb(RealTimeRunData_Debug, false); // get live data
} else if((0 == mGridLen) && generalConfig->readGrid) { // read grid profile } else if((0 == mGridLen) && generalConfig->readGrid) { // read grid profile
cb(GridOnProFilePara, false); cb(GridOnProFilePara, false);
cb(RealTimeRunData_Debug, false); // get live data
} else if (mGetLossInterval > AHOY_GET_LOSS_INTERVAL) { // get loss rate } else if (mGetLossInterval > AHOY_GET_LOSS_INTERVAL) { // get loss rate
mGetLossInterval = 1; mGetLossInterval = 1;
cb(RealTimeRunData_Debug, false); // get live data cb(RealTimeRunData_Debug, false); // get live data
@ -455,6 +464,12 @@ class Inverter {
status = InverterStatus::OFF; status = InverterStatus::OFF;
actPowerLimit = 0xffff; // power limit will be read once inverter becomes available actPowerLimit = 0xffff; // power limit will be read once inverter becomes available
alarmMesIndex = 0; alarmMesIndex = 0;
if(ivRadioType == INV_RADIO_TYPE_NRF) {
heuristics.clear();
#ifdef DYNAMIC_OFFSET
rxOffset = ivGen == IV_HM ? 13 : 12; // effective 3 (or 2), but can easily be recognized as default setting
#endif
}
} }
else else
status = InverterStatus::WAS_ON; status = InverterStatus::WAS_ON;

43
src/hm/hmRadio.h

@ -121,14 +121,14 @@ class HmRadio : public Radio {
if(!mNRFloopChannels && ((mTimeslotStart - mLastIrqTime) > (DURATION_TXFRAME))) //(DURATION_TXFRAME+DURATION_ONEFRAME))) if(!mNRFloopChannels && ((mTimeslotStart - mLastIrqTime) > (DURATION_TXFRAME))) //(DURATION_TXFRAME+DURATION_ONEFRAME)))
mNRFloopChannels = true; mNRFloopChannels = true;
rxPendular = !rxPendular; mRxPendular = !mRxPendular;
//innerLoopTimeout = (rxPendular ? 1 : 2)*DURATION_LISTEN_MIN; //innerLoopTimeout = (rxPendular ? 1 : 2)*DURATION_LISTEN_MIN;
//innerLoopTimeout = DURATION_LISTEN_MIN; innerLoopTimeout = DURATION_LISTEN_MIN;
if(mNRFloopChannels) if(mNRFloopChannels)
tempRxChIdx = (tempRxChIdx + 4) % RF_CHANNELS; tempRxChIdx = (tempRxChIdx + 4) % RF_CHANNELS;
else else
tempRxChIdx = (mRxChIdx + rxPendular*4) % RF_CHANNELS; tempRxChIdx = (mRxChIdx + mRxPendular*4) % RF_CHANNELS;
mNrf24->setChannel(mRfChLst[tempRxChIdx]); mNrf24->setChannel(mRfChLst[tempRxChIdx]);
isRxInit = false; isRxInit = false;
@ -142,7 +142,7 @@ class HmRadio : public Radio {
if(tx_ok || tx_fail) { // tx related interrupt, basically we should start listening if(tx_ok || tx_fail) { // tx related interrupt, basically we should start listening
mNrf24->flush_tx(); // empty TX FIFO mNrf24->flush_tx(); // empty TX FIFO
mTxSetupTime = millis() - mMillis; //mTxSetupTime = millis() - mMillis;
if(mNRFisInRX) { if(mNRFisInRX) {
DPRINTLN(DBG_WARN, F("unexpected tx irq!")); DPRINTLN(DBG_WARN, F("unexpected tx irq!"));
@ -153,17 +153,21 @@ class HmRadio : public Radio {
if(tx_ok) if(tx_ok)
mLastIv->mAckCount++; mLastIv->mAckCount++;
//mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS; //#ifdef DYNAMIC_OFFSET
mRxChIdx = (mTxChIdx + mLastIv->rxOffset) % RF_CHANNELS; mRxChIdx = (mTxChIdx + mLastIv->rxOffset) % RF_CHANNELS;
/*#else
mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS;
#endif*/
mNrf24->setChannel(mRfChLst[mRxChIdx]); mNrf24->setChannel(mRfChLst[mRxChIdx]);
mNrf24->startListening(); mNrf24->startListening();
mTimeslotStart = millis(); mTimeslotStart = millis();
tempRxChIdx = mRxChIdx; // might be better to start off with one channel less? tempRxChIdx = mRxChIdx; // might be better to start off with one channel less?
rxPendular = false; mRxPendular = false;
mNRFloopChannels = (mLastIv->ivGen == IV_MI); mNRFloopChannels = (mLastIv->ivGen == IV_MI);
//innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_TXFRAME : DURATION_ONEFRAME; //innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_TXFRAME : DURATION_ONEFRAME;
innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_LISTEN_MIN : 4; //innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_LISTEN_MIN : 4;
innerLoopTimeout = (mLastIv->mIsSingleframeReq || mLastIv->ivGen == IV_MI) ? DURATION_LISTEN_MIN : DURATION_TXFRAME;
} }
if(rx_ready) { if(rx_ready) {
@ -176,7 +180,7 @@ class HmRadio : public Radio {
innerLoopTimeout = DURATION_LISTEN_MIN; innerLoopTimeout = DURATION_LISTEN_MIN;
mTimeslotStart = millis(); mTimeslotStart = millis();
if (!mNRFloopChannels) { if (!mNRFloopChannels) {
//rxPendular = true; // stay longer on the next rx channel //mRxPendular = true; // stay longer on the next rx channel
if (isRxInit) { if (isRxInit) {
isRxInit = false; isRxInit = false;
tempRxChIdx = (mRxChIdx + 4) % RF_CHANNELS; tempRxChIdx = (mRxChIdx + 4) % RF_CHANNELS;
@ -325,12 +329,14 @@ class HmRadio : public Radio {
isRetransmitAnswer = true; isRetransmitAnswer = true;
if(isLastPackage) if(isLastPackage)
setExpectedFrames(p.packet[9] - ALL_FRAMES); setExpectedFrames(p.packet[9] - ALL_FRAMES);
#ifdef DYNAMIC_OFFSET
if(p.packet[9] == 1 && p.millis < DURATION_ONEFRAME) if(p.packet[9] == 1 && p.millis < DURATION_ONEFRAME)
mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx + 1) % RF_CHANNELS; mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx + 1) % RF_CHANNELS;
else if(mNRFloopChannels && mLastIv->rxOffset > RF_CHANNELS) { // unsure setting? else if(mNRFloopChannels && mLastIv->rxOffset > RF_CHANNELS) { // unsure setting?
mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx + (isLastPackage ? mFramesExpected : p.packet[9])); // make clear it's not sure, start with one more offset mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx + (isLastPackage ? mFramesExpected : p.packet[9])); // make clear it's not sure, start with one more offset
mNRFloopChannels = false; mNRFloopChannels = false;
} }
#endif
} }
if(IV_MI == mLastIv->ivGen) { if(IV_MI == mLastIv->ivGen) {
@ -338,8 +344,10 @@ class HmRadio : public Radio {
isLastPackage = (p.packet[9] > 0x10); // > 0x10 indicates last packet received isLastPackage = (p.packet[9] > 0x10); // > 0x10 indicates last packet received
else if ((p.packet[0] != 0x88) && (p.packet[0] != 0x92)) // ignore MI status messages //#0 was p.packet[0] != 0x00 && else if ((p.packet[0] != 0x88) && (p.packet[0] != 0x92)) // ignore MI status messages //#0 was p.packet[0] != 0x00 &&
isLastPackage = true; // response from dev control command isLastPackage = true; // response from dev control command
#ifdef DYNAMIC_OFFSET
if(p.packet[9] == 0x00 && p.millis < DURATION_ONEFRAME) if(p.packet[9] == 0x00 && p.millis < DURATION_ONEFRAME)
mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx - 1) % RF_CHANNELS; mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx - 1) % RF_CHANNELS;
#endif
} }
rx_ready = true; //reset in case we first read messages from other inverter or ACK zero payloads rx_ready = true; //reset in case we first read messages from other inverter or ACK zero payloads
} }
@ -347,9 +355,8 @@ class HmRadio : public Radio {
} }
yield(); yield();
} }
if(isLastPackage) { if(isLastPackage)
mLastIv->mGotLastMsg = true; mLastIv->mGotLastMsg = true;
}
return isLastPackage || isRetransmitAnswer; return isLastPackage || isRetransmitAnswer;
} }
@ -361,10 +368,7 @@ class HmRadio : public Radio {
mTxChIdx = iv->heuristics.txRfChId; mTxChIdx = iv->heuristics.txRfChId;
if(*mSerialDebug) { if(*mSerialDebug) {
/* remark rejoe2: imo this has no added value here. /*if(!isRetransmit) {
As this belongs to the last tx cycle, we should print that info
directly when switching from tx to rx. Otherwise we might confuse users.
if(!isRetransmit) {
DPRINT(DBG_INFO, "last tx setup: "); DPRINT(DBG_INFO, "last tx setup: ");
DBGPRINT(String(mTxSetupTime)); DBGPRINT(String(mTxSetupTime));
DBGPRINTLN("ms"); DBGPRINTLN("ms");
@ -374,13 +378,19 @@ class HmRadio : public Radio {
DBGPRINT(F("TX ")); DBGPRINT(F("TX "));
DBGPRINT(String(len)); DBGPRINT(String(len));
DBGPRINT(" CH"); DBGPRINT(" CH");
if(mTxChIdx == 0)
DBGPRINT("0");
DBGPRINT(String(mRfChLst[mTxChIdx])); DBGPRINT(String(mRfChLst[mTxChIdx]));
DBGPRINT(F(", ")); DBGPRINT(F(", "));
DBGPRINT(String(mTxRetriesNext)); DBGPRINT(String(mTxRetriesNext));
//DBGPRINT(F(" retries | ")); //DBGPRINT(F(" retries | "));
//#ifdef DYNAMIC_OFFSET
DBGPRINT(F(" ret., rx offset: ")); DBGPRINT(F(" ret., rx offset: "));
DBGPRINT(String(iv->rxOffset)); DBGPRINT(String(iv->rxOffset));
DBGPRINT(F(" | ")); DBGPRINT(F(" | "));
/*#else
DBGPRINT(F(" ret. | "));
#endif*/
if(*mPrintWholeTrace) { if(*mPrintWholeTrace) {
if(*mPrivacyMode) if(*mPrivacyMode)
ah::dumpBuf(mTxBuf, len, 1, 4); ah::dumpBuf(mTxBuf, len, 1, 4);
@ -396,6 +406,7 @@ class HmRadio : public Radio {
} }
mNrf24->stopListening(); mNrf24->stopListening();
mNrf24->flush_rx();
if(!isRetransmit && mTxRetries != mTxRetriesNext) { if(!isRetransmit && mTxRetries != mTxRetriesNext) {
mNrf24->setRetries(3, mTxRetriesNext); mNrf24->setRetries(3, mTxRetriesNext);
mTxRetries = mTxRetriesNext; mTxRetries = mTxRetriesNext;
@ -439,9 +450,9 @@ class HmRadio : public Radio {
bool mNRFloopChannels = false; bool mNRFloopChannels = false;
bool mNRFisInRX = false; bool mNRFisInRX = false;
bool isRxInit = true; bool isRxInit = true;
bool rxPendular = false; bool mRxPendular = false;
uint32_t innerLoopTimeout = DURATION_LISTEN_MIN; uint32_t innerLoopTimeout = DURATION_LISTEN_MIN;
uint8_t mTxSetupTime = 0; //uint8_t mTxSetupTime = 0;
uint8_t mTxRetries = 15; // memorize last setting for mNrf24->setRetries(3, 15); uint8_t mTxRetries = 15; // memorize last setting for mNrf24->setRetries(3, 15);
std::unique_ptr<SPIClass> mSpi; std::unique_ptr<SPIClass> mSpi;

7
src/hm/hmSystem.h

@ -28,7 +28,6 @@ class HmSystem {
iv->config = &mInverter[0].generalConfig->iv[id]; iv->config = &mInverter[0].generalConfig->iv[id];
DPRINT(DBG_VERBOSE, "SERIAL: " + String(iv->config->serial.b[5], HEX)); DPRINT(DBG_VERBOSE, "SERIAL: " + String(iv->config->serial.b[5], HEX));
DPRINTLN(DBG_VERBOSE, " " + String(iv->config->serial.b[4], HEX)); DPRINTLN(DBG_VERBOSE, " " + String(iv->config->serial.b[4], HEX));
iv->rxOffset = 13; // effective 3, but can easily be recognized as default setting
if((iv->config->serial.b[5] == 0x11) || (iv->config->serial.b[5] == 0x10)) { if((iv->config->serial.b[5] == 0x11) || (iv->config->serial.b[5] == 0x10)) {
switch(iv->config->serial.b[4]) { switch(iv->config->serial.b[4]) {
case 0x24: // HMS-500 case 0x24: // HMS-500
@ -96,6 +95,12 @@ class HmSystem {
if((iv->config->serial.b[5] == 0x10) && ((iv->config->serial.b[4] & 0x03) == 0x01)) if((iv->config->serial.b[5] == 0x10) && ((iv->config->serial.b[4] & 0x03) == 0x01))
DPRINTLN(DBG_WARN, F("MI Inverter, has some restrictions!")); DPRINTLN(DBG_WARN, F("MI Inverter, has some restrictions!"));
#ifdef DYNAMIC_OFFSET
iv->rxOffset = iv->ivGen == IV_HM ? 13 : 12; // effective 3 (or 2), but can easily be recognized as default setting
#else
iv->rxOffset = (iv->ivGen == IV_HM && iv->type == INV_TYPE_4CH) ? 3 : 2; // effective 3 (or 2), but can easily be recognized as default setting
#endif
cb(iv); cb(iv);
} }

6
src/hms/cmt2300a.h

@ -356,11 +356,11 @@ class Cmt2300a {
if((freqKhz % FREQ_STEP_KHZ) != 0) if((freqKhz % FREQ_STEP_KHZ) != 0)
return 0xff; // error return 0xff; // error
std::pair<uint8_t, uint8_t> range = getFreqRangeMhz(); std::pair<uint16_t, uint16_t> range = getFreqRangeMhz();
if((freqKhz < range.first) || (freqKhz > range.second)) if((freqKhz < (range.first * 1000)) || (freqKhz > (range.second * 1000)))
return 0xff; // error return 0xff; // error
return (freqKhz - getBaseFreqMhz() * 1000) / FREQ_STEP_KHZ; return (freqKhz - (getBaseFreqMhz() * 1000)) / FREQ_STEP_KHZ;
} }
inline void switchChannel(uint8_t ch) { inline void switchChannel(uint8_t ch) {

Loading…
Cancel
Save