Browse Source

simplify rxOffset logic

- Code cleanup
- fix "nRF CE keep high" code (missing argument)
pull/1417/head
rejoe2 11 months ago
committed by GitHub
parent
commit
d15e75dbab
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 91
      src/hm/Communication.h
  2. 2
      src/hm/hmDefines.h
  3. 1
      src/hm/hmInverter.h
  4. 42
      src/hm/hmRadio.h
  5. 10
      src/hm/hmSystem.h

91
src/hm/Communication.h

@ -13,7 +13,7 @@
#include "../utils/timemonitor.h"
#include "Heuristic.h"
#define MAX_BUFFER 250
#define MAX_BUFFER 200
typedef std::function<void(uint8_t, Inverter<> *)> payloadListenerType;
typedef std::function<void(Inverter<> *)> powerLimitAckListenerType;
@ -92,6 +92,8 @@ class Communication : public CommQueue<> {
q->iv->mIsSingleframeReq = false;
mFramesExpected = getFramesExpected(q); // function to get expected frame count.
mTimeout = DURATION_TXFRAME + mFramesExpected*DURATION_ONEFRAME + duration_reserve[q->iv->ivRadioType];
if((q->iv->ivGen == IV_MI) && ((q->cmd == MI_REQ_CH1) || (q->cmd == MI_REQ_4CH)))
incrAttempt(q->iv->channels); // 2 more attempts for 2ch, 4 more for 4ch
mState = States::START;
break;
@ -209,7 +211,7 @@ class Communication : public CommQueue<> {
} else {
if(q->iv->miMultiParts < 6) {
mState = States::WAIT;
if((q->iv->radio->mRadioWaitTime.isTimeout() && mIsRetransmit) || !mIsRetransmit) {
if(q->iv->radio->mRadioWaitTime.isTimeout() && q->attempts) {
miRepeatRequest(q);
return;
}
@ -220,6 +222,10 @@ class Communication : public CommQueue<> {
|| ((q->cmd == MI_REQ_CH1) && (q->iv->type == INV_TYPE_1CH))) {
miComplete(q->iv);
}
if(*mSerialDebug) {
DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINTLN(F("Payload (MI got all)"));
}
closeRequest(q, true);
}
}
@ -443,9 +449,8 @@ class Communication : public CommQueue<> {
|| (p->packet[0] == MI_REQ_CH2 + ALL_FRAMES)
|| ((p->packet[0] >= (MI_REQ_4CH + ALL_FRAMES))
&& (p->packet[0] < (0x39 + SINGLE_FRAME))
)) { //&& (p->packet[0] != (0x0f + ALL_FRAMES)))) {
)) {
// small MI or MI 1500 data responses to 0x09, 0x11, 0x36, 0x37, 0x38 and 0x39
//mPayload[iv->id].txId = p->packet[0];
miDataDecode(p, q);
} else if (p->packet[0] == (0x0f + ALL_FRAMES)) {
miHwDecode(p, q);
@ -541,14 +546,16 @@ class Communication : public CommQueue<> {
len -= 2;
DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F("Payload ("));
DBGPRINT(String(len));
if(*mPrintWholeTrace) {
DBGPRINT(F("): "));
ah::dumpBuf(mPayload.data(), len);
} else
DBGPRINTLN(F(")"));
if(*mSerialDebug) {
DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F("Payload ("));
DBGPRINT(String(len));
if(*mPrintWholeTrace) {
DBGPRINT(F("): "));
ah::dumpBuf(mPayload.data(), len);
} else
DBGPRINTLN(F(")"));
}
if(GridOnProFilePara == q->cmd) {
q->iv->addGridProfile(mPayload.data(), len);
@ -813,35 +820,21 @@ class Communication : public CommQueue<> {
miStsConsolidate(q, datachan, rec, p->packet[23], p->packet[24]);
if (p->packet[0] < (0x39 + ALL_FRAMES) ) {
mHeu.evalTxChQuality(q->iv, true, (q->attemptsMax - 1 - q->attempts), 1);
miNextRequest((p->packet[0] - ALL_FRAMES + 1), q);
} else {
q->iv->miMultiParts = 7; // indicate we are ready
}
} else if((p->packet[0] == (MI_REQ_CH1 + ALL_FRAMES)) && (q->iv->type == INV_TYPE_2CH)) {
//addImportant(q->iv, MI_REQ_CH2);
miNextRequest(MI_REQ_CH2, q);
mHeu.evalTxChQuality(q->iv, true, (q->attemptsMax - 1 - q->attempts), q->iv->curFrmCnt);
q->iv->mIvRxCnt++; // statistics workaround...
q->iv->mIvRxCnt++; // statistics workaround...
} else { // first data msg for 1ch, 2nd for 2ch
} else // first data msg for 1ch, 2nd for 2ch
q->iv->miMultiParts += 6; // indicate we are ready
}
}
void miNextRequest(uint8_t cmd, const queue_s *q) {
incrAttempt(); // if function is called, we got something, and we necessarily need more transmissions for MI types...
if(*mSerialDebug) {
DPRINT_IVID(DBG_WARN, q->iv->id);
DBGPRINT(F("next request ("));
DBGPRINT(String(q->attempts));
DBGPRINT(F(" attempts left): 0x"));
DBGHEXLN(cmd);
}
/*if(q->iv->miMultiParts > 5) //if(q->iv->miMultiParts == 7)
q->iv->radioStatistics.rxSuccess++;*/
mHeu.evalTxChQuality(q->iv, true, (q->attemptsMax - 1 - q->attempts), q->iv->curFrmCnt);
mHeu.getTxCh(q->iv);
q->iv->radioStatistics.ivSent++;
mFramesExpected = getFramesExpected(q);
@ -851,6 +844,13 @@ class Communication : public CommQueue<> {
q->iv->radio->mRadioWaitTime.startTimeMonitor(DURATION_TXFRAME + DURATION_ONEFRAME + duration_reserve[q->iv->ivRadioType]);
q->iv->miMultiParts = 0;
q->iv->mGotFragment = 0;
if(*mSerialDebug) {
DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F("next: ("));
DBGPRINT(String(q->attempts));
DBGPRINT(F(" attempts left): 0x"));
DBGHEXLN(cmd);
}
mIsRetransmit = true;
chgCmd(cmd);
//mState = States::WAIT;
@ -858,19 +858,17 @@ class Communication : public CommQueue<> {
void miRepeatRequest(const queue_s *q) {
setAttempt(); // if function is called, we got something, and we necessarily need more transmissions for MI types...
q->iv->radio->sendCmdPacket(q->iv, q->cmd, 0x00, true);
q->iv->radioStatistics.retransmits++;
q->iv->radio->mRadioWaitTime.startTimeMonitor(DURATION_TXFRAME + DURATION_ONEFRAME + duration_reserve[q->iv->ivRadioType]);
if(*mSerialDebug) {
DPRINT_IVID(DBG_WARN, q->iv->id);
DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F("resend request ("));
DBGPRINT(String(q->attempts));
DBGPRINT(F(" attempts left): 0x"));
DBGHEXLN(q->cmd);
}
q->iv->radio->sendCmdPacket(q->iv, q->cmd, 0x00, true);
q->iv->radioStatistics.retransmits++;
q->iv->radio->mRadioWaitTime.startTimeMonitor(DURATION_TXFRAME + DURATION_ONEFRAME + duration_reserve[q->iv->ivRadioType]);
mIsRetransmit = false;
//mIsRetransmit = false;
}
void miStsConsolidate(const queue_s *q, uint8_t stschan, record_t<> *rec, uint8_t uState, uint8_t uEnum, uint8_t lState = 0, uint8_t lEnum = 0) {
@ -953,11 +951,6 @@ class Communication : public CommQueue<> {
void miComplete(Inverter<> *iv) {
if (*mSerialDebug) {
DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINTLN(F("got all data msgs"));
}
if (iv->mGetLossInterval >= AHOY_GET_LOSS_INTERVAL) { // initially mIvRxCnt = mIvTxCnt = 0
iv->mGetLossInterval = 1;
iv->radioStatistics.ivSent = iv->mIvRxCnt + iv->mDtuTxCnt; // iv->mIvRxCnt is the nr. of additional answer frames, default we expect one frame per request
@ -966,10 +959,16 @@ class Communication : public CommQueue<> {
iv->radioStatistics.dtuSent = iv->mDtuTxCnt;
if (*mSerialDebug) {
DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINTLN("DTU loss: " +
String (iv->radioStatistics.ivLoss) + "/" +
String (iv->radioStatistics.ivSent) + " frames for " +
String (iv->radioStatistics.dtuSent) + " requests");
DBGPRINT(F("DTU loss: ") +
String (iv->radioStatistics.ivLoss) + F("/") +
String (iv->radioStatistics.ivSent) + F(" frames for ") +
String (iv->radioStatistics.dtuSent) + F(" requests"));
if(iv->mAckCount) {
DBGPRINT(F(". ACKs: "));
DBGPRINTLN(String(iv->mAckCount));
iv->mAckCount = 0;
} else
DBGPRINTLN(F(""));
}
iv->mIvRxCnt = 0; // start new interval, iVRxCnt is abused to collect additional possible frames
iv->mIvTxCnt = 0; // start new interval, iVTxCnt is abused to collect nr. of unanswered requests

2
src/hm/hmDefines.h

@ -89,7 +89,7 @@ const uint8_t duration_reserve[2] = {65, 115};
#define LIMIT_FAST_IV 85 // time limit to qualify an inverter as very fast answering inverter
#define LIMIT_VERYFAST_IV 70 // time limit to qualify an inverter as very fast answering inverter
#define LIMIT_FAST_IV_MI 35 // time limit to qualify a MI type inverter as fast answering inverter
#define LIMIT_VERYFAST_IV_MI 22 // time limit to qualify a MI type inverter as very fast answering inverter
#define LIMIT_VERYFAST_IV_MI 25 // time limit to qualify a MI type inverter as very fast answering inverter
#define RETRIES_FAST_IV 12 // how often shall a message be automatically retransmitted by the nRF (fast answering inverter)
#define RETRIES_VERYFAST_IV 9 // how often shall a message be automatically retransmitted by the nRF (very fast answering inverter)

1
src/hm/hmInverter.h

@ -132,7 +132,6 @@ class Inverter {
record_t<REC_TYP> recordAlarm; // structure for alarm values
InverterStatus status = InverterStatus::OFF; // indicates the current inverter status
std::array<alarm_t, 10> lastAlarm; // holds last 10 alarms
uint8_t rxOffset = 0; // holds the default channel offset between tx and rx channel (nRF only)
int8_t rssi = 0; // RSSI
uint16_t alarmCnt = 0; // counts the total number of occurred alarms
uint16_t alarmLastId = 0; // lastId which was received

42
src/hm/hmRadio.h

@ -152,31 +152,22 @@ class HmRadio : public Radio {
if(tx_ok)
mLastIv->mAckCount++;
//#ifdef DYNAMIC_OFFSET
mRxChIdx = (mTxChIdx + mLastIv->rxOffset) % RF_CHANNELS;
/*#else
mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS;
#endif*/
rxOffset = mLastIv->ivGen == IV_HM ? 3 : 2; // holds the default channel offset between tx and rx channel (nRF only)
mRxChIdx = (mTxChIdx + rxOffset) % RF_CHANNELS;
mNrf24->setChannel(mRfChLst[mRxChIdx]);
mNrf24->startListening();
mTimeslotStart = millis();
tempRxChIdx = mRxChIdx; // might be better to start off with one channel less?
mRxPendular = false;
mNRFloopChannels = (mLastIv->ivGen == IV_MI);
//innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_TXFRAME : DURATION_ONEFRAME;
//innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_LISTEN_MIN : 4;
//innerLoopTimeout = (mLastIv->mIsSingleframeReq || mLastIv->ivGen == IV_MI) ? DURATION_LISTEN_MIN : DURATION_TXFRAME;
mNRFloopChannels = (mLastIv->mCmd == MI_REQ_CH1 || mLastIv->mCmd == MI_REQ_CH1);
innerLoopTimeout = DURATION_LISTEN_MIN;
}
if(rx_ready) {
if (getReceived()) { // check what we got, returns true for last package or success for single frame request
mNRFisInRX = false;
rx_ready = false;
mRadioWaitTime.startTimeMonitor(DURATION_PAUSE_LASTFR); // let the inverter first end his transmissions
mNrf24->stopListening();
return false;
} else {
innerLoopTimeout = DURATION_LISTEN_MIN;
mTimeslotStart = millis();
@ -188,7 +179,6 @@ class HmRadio : public Radio {
} else
mRxChIdx = tempRxChIdx;
}
return true;
}
rx_ready = false; // reset
return mNRFisInRX;
@ -317,9 +307,11 @@ class HmRadio : public Radio {
if (p.packet[0] != 0x00) {
if(!checkIvSerial(p.packet, mLastIv)) {
DPRINT(DBG_WARN, "RX other inverter ");
DPRINT(DBG_WARN, F("RX other inverter "));
if(!*mPrivacyMode)
ah::dumpBuf(p.packet, p.len);
else
DBGPRINTLN(F(""));
} else {
mLastIv->mGotFragment = true;
mBufCtrl.push(p);
@ -331,14 +323,6 @@ class HmRadio : public Radio {
if(isLastPackage)
setExpectedFrames(p.packet[9] - ALL_FRAMES);
#ifdef DYNAMIC_OFFSET
if((p.packet[9] == 1) && (p.millis < DURATION_ONEFRAME))
mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx + 1) % RF_CHANNELS;
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
mNRFloopChannels = false;
}
#endif
}
if(IV_MI == mLastIv->ivGen) {
@ -346,10 +330,6 @@ class HmRadio : public Radio {
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 &&
isLastPackage = true; // response from dev control command
#ifdef DYNAMIC_OFFSET
if((p.packet[9] == 0x00) && (p.millis < DURATION_ONEFRAME))
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
}
@ -385,14 +365,7 @@ class HmRadio : public Radio {
DBGPRINT(String(mRfChLst[mTxChIdx]));
DBGPRINT(F(", "));
DBGPRINT(String(mTxRetriesNext));
//DBGPRINT(F(" retries | "));
//#ifdef DYNAMIC_OFFSET
DBGPRINT(F(" ret., rx offset: "));
DBGPRINT(String(iv->rxOffset));
DBGPRINT(F(" | "));
/*#else
DBGPRINT(F(" ret. | "));
#endif*/
if(*mPrintWholeTrace) {
if(*mPrivacyMode)
ah::dumpBuf(mTxBuf.data(), len, 1, 4);
@ -415,7 +388,7 @@ class HmRadio : public Radio {
}
mNrf24->setChannel(mRfChLst[mTxChIdx]);
mNrf24->openWritingPipe(reinterpret_cast<uint8_t*>(&iv->radioId.u64));
mNrf24->startFastWrite(mTxBuf.data(), len, false); // false = request ACK response
mNrf24->startFastWrite(mTxBuf.data(), len, false, true); // false (3) = request ACK response; true (4) reset CE to high after transmission
mMillis = millis();
mLastIv = iv;
@ -455,6 +428,7 @@ class HmRadio : public Radio {
bool mRxPendular = false;
uint32_t innerLoopTimeout = DURATION_LISTEN_MIN;
uint8_t mTxRetries = 15; // memorize last setting for mNrf24->setRetries(3, 15);
uint8_t rxOffset = 3; // holds the channel offset between tx and rx channel used for actual inverter
std::unique_ptr<SPIClass> mSpi;
std::unique_ptr<RF24> mNrf24;

10
src/hm/hmSystem.h

@ -93,16 +93,8 @@ class HmSystem {
DBGPRINTLN(String(iv->config->serial.u64, HEX));
if((iv->config->serial.b[5] == 0x10) && ((iv->config->serial.b[4] & 0x03) == 0x01))
if(IV_MI == iv->ivGen)
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;
iv->rxOffset = (iv->ivGen == IV_HM) ? 3 : 2;
#endif
cb(iv);
}

Loading…
Cancel
Save