Browse Source

refacturing rx loop - second version

- less impact out of nRF, less variables
- tested on single HM-1500, rock solid, but timings need to be reviewed 

Known bug:
Any limitation command will be endlessly executed, still after success...
pull/1284/head
rejoe2 2 years ago
committed by GitHub
parent
commit
c02c59d7a2
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      src/defines.h
  2. 43
      src/hm/Communication.h
  3. 36
      src/hm/hmInverter.h
  4. 98
      src/hm/hmRadio.h
  5. 1
      src/hm/radio.h
  6. 4
      src/hms/cmt2300a.h
  7. 4
      src/hms/hmsRadio.h

2
src/defines.h

@ -13,7 +13,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 8
#define VERSION_PATCH 2304
#define VERSION_PATCH 2601
//-------------------------------------
typedef struct {

43
src/hm/Communication.h

@ -87,7 +87,10 @@ class Communication : public CommQueue<> {
cmdDone(true); // can't communicate while radio is not defined!
mState = States::START;
q->iv->radio->prepareReceive(q->iv, q->cmd, false);
q->iv->mCmd = q->cmd;
q->iv->mIsSingleframeReq = false;
//prepareReceive(q->iv, q->cmd, false);
break;
@ -212,11 +215,12 @@ class Communication : public CommQueue<> {
}
closeRequest(q, true);
if(fastNext) {
DPRINTLN(DBG_INFO, F("we should enqueue sth immediately...."));
// immediately send out regular production data request
// and reset mWaitTimeout
mWaitTimeout = mWaitTimeout - *mInverterGap;
chgCmd((q->iv->type == INV_TYPE_4CH) ? MI_REQ_4CH : MI_REQ_CH1);
mState = States::RESET;
//mWaitTimeout = mWaitTimeout - *mInverterGap;
//chgCmd((q->iv->type == INV_TYPE_4CH) ? MI_REQ_4CH : MI_REQ_CH1);
//mState = States::RESET;
}
}
@ -260,7 +264,9 @@ class Communication : public CommQueue<> {
DBGPRINTLN(F(" attempts left)"));
}
if (!mIsRetransmit)
q->iv->radio->prepareReceive(q->iv, q->cmd, true);
q->iv->mIsSingleframeReq = true;
//prepareReceive(q->iv, q->cmd, true);
sendRetransmit(q, (framnr-1));
mIsRetransmit = true;
@ -270,23 +276,10 @@ class Communication : public CommQueue<> {
compilePayload(q);
if(NULL != mCbPayload)
if((NULL != mCbPayload) && (GridOnProFilePara != q->cmd))
(mCbPayload)(q->cmd, q->iv);
bool fastNext = false;
if ((q->cmd < 11) || (q->cmd > 18))
fastNext = true;
closeRequest(q, true);
if(fastNext) {
// immediately send out regular production data request
// and reset mWaitTimeout
mWaitTimeout = mWaitTimeout - *mInverterGap;
chgCmd(RealTimeRunData_Debug);
mState = States::RESET;
}
break;
}
});
@ -318,7 +311,9 @@ class Communication : public CommQueue<> {
else
ah::dumpBuf(p->packet, p->len);
} else {
DBGPRINT(F("| "));
DBGPRINT(F("| 0x"));
DHEX(p->packet[0]);
DBGPRINT(F(" "));
DBGHEXLN(p->packet[9]);
}
}
@ -401,7 +396,7 @@ class Communication : public CommQueue<> {
accepted = false;
DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F(" has "));
DBGPRINT(F("has "));
if(!accepted) DBGPRINT(F("not "));
DBGPRINT(F("accepted power limit set point "));
DBGPRINT(String(q->iv->powerLimit[0]));
@ -469,9 +464,15 @@ class Communication : public CommQueue<> {
} else
DBGPRINTLN(F(")"));
if(GridOnProFilePara == q->cmd) {
q->iv->addGridProfile(mPayload, len);
return;
}
record_t<> *rec = q->iv->getRecordStruct(q->cmd);
if(NULL == rec) {
DPRINTLN(DBG_ERROR, F("record is NULL!"));
closeRequest(q, false);
return;
}
if((rec->pyldLen != len) && (0 != rec->pyldLen)) {

36
src/hm/hmInverter.h

@ -11,6 +11,8 @@
#define F(sl) (sl)
#endif
#define MAX_GRID_LENGTH 150
#include "hmDefines.h"
#include "HeuristicInv.h"
#include "../hms/hmsDefines.h"
@ -131,14 +133,11 @@ class Inverter {
bool mGotFragment; // shows if inverter has sent at least one fragment
uint8_t curFrmCnt; // count received frames in current loop
bool mGotLastMsg; // shows if inverter has already finished transmission cycle
uint8_t mRxChannels; // number of rx channels to listen to, defaults to 3;
uint32_t mRxTmoOuterLoop; // timeout for entire listening loop after sending, defaults to 400 (ms);
uint32_t mRxTmoInnerLoop; // timeout for each listening channel, defaults to 5110 (us)
uint8_t lastCmd; // holds the last sent command, defaults to 0xFF
uint8_t mCmd; // holds the command to send
bool mIsSingleframeReq; // indicates this is a missing single frame request
Radio *radio; // pointer to associated radio class
statistics_t radioStatistics; // information about transmitted, failed, ... packets
HeuristicInv heuristics;
HeuristicInv heuristics; // heuristic information / logic
uint8_t curCmtFreq; // current used CMT frequency, used to check if freq. was changed during runtime
bool commEnabled; // 'pause night communication' sets this field to false
@ -161,11 +160,9 @@ class Inverter {
alarmLastId = 0;
rssi = -127;
miMultiParts = 0;
lastCmd = 0xFF;
mGotLastMsg = false;
mRxChannels = 3;
mRxTmoOuterLoop = 400;
mRxTmoInnerLoop = 5110;
mCmd = InitDataState;
mIsSingleframeReq = false;
radio = NULL;
commEnabled = true;
@ -192,6 +189,8 @@ class Inverter {
else if(InitDataState != devControlCmd) {
cb(devControlCmd, false); // custom command which was received by API
devControlCmd = InitDataState;
} else if((0 == mGridLen) && generalConfig->readGrid) { // read grid profile
cb(GridOnProFilePara, false);
} else
cb(RealTimeRunData_Debug, false); // get live data
} else {
@ -730,6 +729,21 @@ class Inverter {
}
}
void addGridProfile(uint8_t buf[], uint8_t length) {
mGridLen = (length > MAX_GRID_LENGTH) ? MAX_GRID_LENGTH : length;
std::copy(buf, &buf[mGridLen], mGridProfile);
}
String getGridProfile(void) {
char buf[MAX_GRID_LENGTH * 3];
memset(buf, 0, MAX_GRID_LENGTH);
for(uint8_t i = 0; i < mGridLen; i++) {
snprintf(&buf[i*3], 4, "%02X ", mGridProfile[i]);
}
buf[mGridLen*3] = 0;
return String(buf);
}
private:
inline void addAlarm(uint16_t code, uint32_t start, uint32_t end) {
lastAlarm[alarmNxtWrPos] = alarm_t(code, start, end);
@ -750,6 +764,8 @@ class Inverter {
private:
float mOffYD[6], mLastYD[6];
bool mDevControlRequest; // true if change needed
uint8_t mGridLen = 0;
uint8_t mGridProfile[MAX_GRID_LENGTH];
};
template <class REC_TYP>

98
src/hm/hmRadio.h

@ -104,50 +104,6 @@ class HmRadio : public Radio {
DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring"));
}
void prepareReceive(Inverter<> *iv, uint8_t cmd, bool singleframe = false) {
if (singleframe) {
iv->mRxTmoOuterLoop = 65; // SINGLEFR_TIMEOUT
iv->lastCmd = 0xFF;
//DPRINTLN(DBG_INFO, F("1 frm"));
return;
}
if ( (iv->lastCmd == cmd) || ((iv->ivGen == IV_MI) && (iv->lastCmd != 0xFF)) )
return; // nothing to be changed....
iv->lastCmd = cmd;
if (iv->ivGen != IV_MI) {
if (cmd == RealTimeRunData_Debug) {
if (iv->type == INV_TYPE_4CH) {
iv->mRxChannels = 3;
iv->mRxTmoOuterLoop = 300;
iv->mRxTmoInnerLoop = 5110;
//DPRINTLN(DBG_INFO, F("4ch data"));
} else if (iv->type == INV_TYPE_2CH) {
iv->mRxChannels = 2;
iv->mRxTmoOuterLoop = 250;
iv->mRxTmoInnerLoop = 10220;
//DPRINTLN(DBG_INFO, F("1/2ch data"));
} else { // INV_TYPE_1CH
iv->mRxChannels = 2;
iv->mRxTmoOuterLoop = 400;
iv->mRxTmoInnerLoop = 5110;
}
} else { //3rd gen defaults
iv->mRxChannels = 5;
iv->mRxTmoOuterLoop = 500;
iv->mRxTmoInnerLoop = 5110;
//DPRINTLN(DBG_INFO, F("3rd gen default"));
}
} else { // 2nd gen defaults
iv->mRxChannels = 2;
iv->mRxTmoOuterLoop = 250;
iv->mRxTmoInnerLoop = 5110;
//DPRINTLN(DBG_INFO, F("2nd gen default"));
}
}
void loop(void) {
if (!mIrqRcvd)
return; // nothing to do
@ -165,8 +121,9 @@ class HmRadio : public Radio {
uint32_t startMicros = micros();
uint32_t loopMillis = millis();
while ((millis() - loopMillis) < mLastIv->mRxTmoOuterLoop) {
while ((micros() - startMicros) < mLastIv->mRxTmoInnerLoop) { // listen (4088us or?) 5110us to each channel
mRxChIdx = (mTxChIdx + 3) % RF_MAX_CHANNEL_ID; // start with a fixed offset
while ((millis() - loopMillis) < mRxTmoOuterLoop) {
while ((micros() - startMicros) < mRxTmoInnerLoop) { // listen (4088us or?) 5110us to each channel
if (mIrqRcvd) {
mIrqRcvd = false;
@ -181,7 +138,7 @@ class HmRadio : public Radio {
mRxChIdx = 0;*/
//if(++mRxChIdx >= mLastIv->mRxChannels)
if(++mRxChIdx >= mLastIv->mRxChannels)
if(++mRxChIdx >= mRxChannels)
mRxChIdx = 0;
uint8_t nextRxCh = (mRxChIdx + mTxChIdx + 4) % RF_MAX_CHANNEL_ID; // let 3 channels in shifting out; might cause problems for tx channel 75, see Oberfritze remark to his array
@ -191,8 +148,8 @@ class HmRadio : public Radio {
startMicros = micros();
}
// not finished but time is over
//if(++mRxChIdx >= RF_CHANNELS) // rejoe2: for testing now always start with the first (relative) rx channel
mRxChIdx = 1;
//if(++mRxChIdx >= RF_CHANNELS)
// mRxChIdx = 0;
return;
}
@ -287,6 +244,41 @@ class HmRadio : public Radio {
sendPacket(iv, cnt, isRetransmit, (IV_MI != iv->ivGen));
}
void prepareReceive(Inverter<> *iv) {
if (iv->mIsSingleframeReq) {
mRxTmoOuterLoop = 65; // SINGLEFR_TIMEOUT
return;
}
if (iv->ivGen != IV_MI) {
if (iv->mCmd == RealTimeRunData_Debug) {
if (iv->type == INV_TYPE_4CH) {
mRxChannels = 3;
mRxTmoOuterLoop = 300;
mRxTmoInnerLoop = 5110;
} else if (iv->type == INV_TYPE_2CH) {
mRxChannels = 2;
mRxTmoOuterLoop = 250;
mRxTmoInnerLoop = 10220;
} else { // INV_TYPE_1CH
mRxChannels = 2;
mRxTmoOuterLoop = 200;
mRxTmoInnerLoop = 5110;
}
} else { //3rd gen defaults
mRxChannels = 3;
mRxTmoOuterLoop = iv->mCmd == AlarmData ? 600 : 400;
mRxTmoInnerLoop = 5110;
}
} else { // 2nd gen defaults
mRxChannels = 2;
mRxTmoOuterLoop = 250;
mRxTmoInnerLoop = 5110;
}
}
uint8_t getDataRate(void) {
if(!mNrf24->isChipConnected())
return 3; // unknown
@ -345,6 +337,7 @@ class HmRadio : public Radio {
// set TX and RX channels
mTxChIdx = mRfChLst[iv->heuristics.txRfChId];
prepareReceive(iv);
if(*mSerialDebug) {
DPRINT_IVID(DBG_INFO, iv->id);
@ -359,6 +352,9 @@ class HmRadio : public Radio {
else
ah::dumpBuf(mTxBuf, len);
} else
DBGPRINT(F("0x"));
DHEX(mTxBuf[0]);
DBGPRINT(F(" "));
DBGHEXLN(mTxBuf[9]);
}
@ -391,6 +387,10 @@ class HmRadio : public Radio {
uint8_t mRfChLst[RF_CHANNELS] = {03, 23, 40, 61, 75}; // channel List:2403, 2423, 2440, 2461, 2475MHz
uint8_t mTxChIdx = 0;
uint8_t mRxChIdx = 0;
uint8_t mRxChannels = 3; // number of rx channels to listen to, defaults to 3;
uint32_t mRxTmoOuterLoop = 400; // timeout for entire listening loop after sending, defaults to 400 (ms);
uint32_t mRxTmoInnerLoop = 5110; // timeout for each listening channel, defaults to 5110 (us)
uint8_t lastCmd = 0xFF; // holds the last sent command, defaults to 0xFF
bool mGotLastMsg = false;
uint32_t mMillis;

1
src/hm/radio.h

@ -22,7 +22,6 @@ class Inverter;
class Radio {
public:
virtual void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) = 0;
virtual void prepareReceive(Inverter<> *iv, uint8_t cmd, bool singleframe = false) = 0;
virtual bool switchFrequency(Inverter<> *iv, uint32_t fromkHz, uint32_t tokHz) { return true; }
virtual bool switchFrequencyCh(Inverter<> *iv, uint8_t fromCh, uint8_t toCh) { return true; }
virtual bool isChipConnected(void) { return false; }

4
src/hms/cmt2300a.h

@ -6,7 +6,7 @@
#ifndef __CMT2300A_H__
#define __CMT2300A_H__
#if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(ETHERNET)
#if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(SPI_HAL)
#include "cmtHal.h"
#else
#include "esp32_3wSpi.h"
@ -480,7 +480,7 @@ class Cmt2300a {
return mSpi.readReg(CMT2300A_CUS_MODE_STA) & CMT2300A_MASK_CHIP_MODE_STA;
}
#if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(ETHERNET)
#if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(SPI_HAL)
cmtHal mSpi;
#else
esp32_3wSpi mSpi;

4
src/hms/hmsRadio.h

@ -26,10 +26,6 @@ class CmtRadio : public Radio {
mPrintWholeTrace = printWholeTrace;
}
void prepareReceive(Inverter<> *iv, uint8_t cmd, bool singleframe = false) {
return; // only relevant for nRF type inverters
}
void loop() {
mCmt.loop();
if((!mIrqRcvd) && (!mRqstGetRx))

Loading…
Cancel
Save