Browse Source

0.8.61 - 2024-01-21

* add favicon to header
* improved NRF communication
pull/1385/head
lumapu 1 year ago
parent
commit
6cbcbbafc5
  1. 4
      src/CHANGES.md
  2. 7
      src/app.cpp
  3. 1
      src/app.h
  4. 2
      src/defines.h
  5. 15
      src/hm/Communication.h
  6. 90
      src/hm/hmRadio.h
  7. 4
      src/hm/radio.h
  8. 12
      src/hms/hmsRadio.h
  9. 13
      src/utils/timemonitor.h
  10. 1
      src/web/html/includes/header.html

4
src/CHANGES.md

@ -1,5 +1,9 @@
# Development Changes # Development Changes
## 0.8.61 - 2024-01-21
* add favicon to header
* improved NRF communication
## 0.8.60 - 2024-01-20 ## 0.8.60 - 2024-01-20
* merge PR: non blocking nRF loop #1371 * merge PR: non blocking nRF loop #1371
* merge PR: fixed millis in serial log #1373 * merge PR: fixed millis in serial log #1373

7
src/app.cpp

@ -143,10 +143,12 @@ void app::loop(void) {
esp_task_wdt_reset(); esp_task_wdt_reset();
if(mConfig->nrf.enabled) if(mConfig->nrf.enabled)
mNrfRadio.loop(); mNrfActive = mNrfRadio.loop();
if(!mNrfActive) {
#if defined(ESP32) #if defined(ESP32)
if(mConfig->cmt.enabled) if(mConfig->cmt.enabled)
mCmtRadio.loop(); mNrfActive = mCmtRadio.loop();
#endif #endif
ah::Scheduler::loop(); ah::Scheduler::loop();
@ -156,6 +158,7 @@ void app::loop(void) {
if (mMqttEnabled && mNetworkConnected) if (mMqttEnabled && mNetworkConnected)
mMqtt.loop(); mMqtt.loop();
#endif #endif
}
yield(); yield();
} }

1
src/app.h

@ -405,6 +405,7 @@ class app : public IApp, public ah::Scheduler {
uint8_t mSendLastIvId; uint8_t mSendLastIvId;
bool mSendFirst; bool mSendFirst;
bool mAllIvNotAvail; bool mAllIvNotAvail;
bool mNrfActive = false;
bool mNetworkConnected; bool mNetworkConnected;

2
src/defines.h

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

15
src/hm/Communication.h

@ -61,11 +61,12 @@ class Communication : public CommQueue<> {
mLastEmptyQueueMillis = millis(); mLastEmptyQueueMillis = millis();
mPrintSequenceDuration = true; mPrintSequenceDuration = true;
/*if(mDebugState != mState) { innerLoop(q);
DPRINT(DBG_INFO, F("State: ")); });
DBGHEXLN((uint8_t)(mState)); }
mDebugState = mState;
}*/ private:
inline void innerLoop(const queue_s *q) {
switch(mState) { switch(mState) {
case States::RESET: case States::RESET:
if (!mWaitTime.isTimeout()) if (!mWaitTime.isTimeout())
@ -272,10 +273,8 @@ class Communication : public CommQueue<> {
closeRequest(q, true); closeRequest(q, true);
break; break;
} }
});
} }
private:
inline void printRxInfo(const queue_s *q, packet_t *p) { inline void printRxInfo(const queue_s *q, packet_t *p) {
DPRINT_IVID(DBG_INFO, q->iv->id); DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F("RX ")); DBGPRINT(F("RX "));
@ -1006,8 +1005,6 @@ class Communication : public CommQueue<> {
Heuristic mHeu; Heuristic mHeu;
uint32_t mLastEmptyQueueMillis = 0; uint32_t mLastEmptyQueueMillis = 0;
bool mPrintSequenceDuration = false; bool mPrintSequenceDuration = false;
//States mDebugState = States::START;
}; };
#endif /*__COMMUNICATION_H__*/ #endif /*__COMMUNICATION_H__*/

90
src/hm/hmRadio.h

@ -78,7 +78,7 @@ class HmRadio : public Radio {
#else #else
mNrf24->begin(mSpi.get(), ce, cs); mNrf24->begin(mSpi.get(), ce, cs);
#endif #endif
mNrf24->setRetries(3, 15); // 3*250us + 250us and 15 loops -> 15ms mNrf24->setRetries(3, 15); // 3*250us + 250us and 16 loops -> 15.25ms
mNrf24->setChannel(mRfChLst[mRxChIdx]); mNrf24->setChannel(mRfChLst[mRxChIdx]);
mNrf24->startListening(); mNrf24->startListening();
@ -89,10 +89,7 @@ class HmRadio : public Radio {
mNrf24->setCRCLength(RF24_CRC_16); mNrf24->setCRCLength(RF24_CRC_16);
mNrf24->setAddressWidth(5); mNrf24->setAddressWidth(5);
mNrf24->openReadingPipe(1, reinterpret_cast<uint8_t*>(&DTU_RADIO_ID)); mNrf24->openReadingPipe(1, reinterpret_cast<uint8_t*>(&DTU_RADIO_ID));
mNrf24->maskIRQ(false, false, false); // enable all receiving interrupts
// enable all receiving interrupts
mNrf24->maskIRQ(false, false, false);
mNrf24->setPALevel(1); // low is default mNrf24->setPALevel(1); // low is default
if(mNrf24->isChipConnected()) { if(mNrf24->isChipConnected()) {
@ -104,25 +101,23 @@ class HmRadio : public Radio {
DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring")); DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring"));
} }
void loop(void) { // returns true if communication is active
bool loop(void) {
if (!mIrqRcvd && !mNRFisInRX) if (!mIrqRcvd && !mNRFisInRX)
return; // first quick check => nothing to do at all here return false; // first quick check => nothing to do at all here
if(NULL == mLastIv) // prevent reading on NULL object! if(NULL == mLastIv) // prevent reading on NULL object!
return; return false;
if(!mIrqRcvd) { // no news from nRF, check timers if(!mIrqRcvd) { // no news from nRF, check timers
if ((millis() - mTimeslotStart) < innerLoopTimeout)
return true; // nothing to do, still waiting
if (mRadioWaitTime.isTimeout()) { // timeout reached! if (mRadioWaitTime.isTimeout()) { // timeout reached!
mNRFisInRX = false; mNRFisInRX = false;
// add stop listening? return false;
return;
} }
yield();
if ((millis() - mTimeslotStart) < innerLoopTimeout)
return; // nothing to do
// otherwise switch to next RX channel // otherwise switch to next RX channel
mTimeslotStart = millis(); mTimeslotStart = millis();
if(!mNRFloopChannels && ((mTimeslotStart - mLastIrqTime) > (DURATION_TXFRAME+DURATION_ONEFRAME))) if(!mNRFloopChannels && ((mTimeslotStart - mLastIrqTime) > (DURATION_TXFRAME+DURATION_ONEFRAME)))
@ -140,21 +135,20 @@ class HmRadio : public Radio {
mNrf24->setChannel(mRfChLst[tempRxChIdx]); mNrf24->setChannel(mRfChLst[tempRxChIdx]);
isRxInit = false; isRxInit = false;
return; return true; // communicating, but changed RX channel
} } else {
// here we got news from the nRF // here we got news from the nRF
mNrf24->whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH
mIrqRcvd = false; mIrqRcvd = false;
mNrf24->whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH
mLastIrqTime = millis(); mLastIrqTime = millis();
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;
if(mNRFisInRX) { if(mNRFisInRX) {
DPRINTLN(DBG_WARN, F("unexpected tx irq!")); DPRINTLN(DBG_WARN, F("unexpected tx irq!"));
return; return false;
} }
mNRFisInRX = true; mNRFisInRX = true;
@ -162,13 +156,27 @@ class HmRadio : public Radio {
mLastIv->mAckCount++; mLastIv->mAckCount++;
// start listening // start listening
mRxChIdx = (mTxChIdx + 2 ) % RF_CHANNELS; if(!mIsRetransmit) {
if(mTxSetupTime < 30) {
mRxChIdx = (mTxChIdx + 4) % RF_CHANNELS;
mNrf24->setChannel(mRfChLst[mRxChIdx]);
mNrf24->startListening();
do {
yield();
} while((millis() - mMillis) < 37);
}
}
mIsRetransmit = false;
mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS;
mNrf24->setChannel(mRfChLst[mRxChIdx]); mNrf24->setChannel(mRfChLst[mRxChIdx]);
mNrf24->startListening(); mNrf24->startListening();
mTimeslotStart = millis(); mTimeslotStart = millis();
tempRxChIdx = mRxChIdx; tempRxChIdx = mRxChIdx;
rxPendular = false; rxPendular = false;
mNRFloopChannels = mLastIv->ivGen == IV_MI; mNRFloopChannels = (mLastIv->ivGen == IV_MI);
innerLoopTimeout = DURATION_TXFRAME; innerLoopTimeout = DURATION_TXFRAME;
} }
@ -191,9 +199,14 @@ class HmRadio : public Radio {
mRxChIdx = tempRxChIdx; mRxChIdx = tempRxChIdx;
} }
} }
return; return mNRFisInRX;
} /*else if(tx_fail) {
mNRFisInRX = false;
return false;
}*/
} }
return false;
} }
bool isChipConnected(void) { bool isChipConnected(void) {
@ -283,6 +296,7 @@ class HmRadio : public Radio {
} }
cnt++; cnt++;
} }
sendPacket(iv, cnt, isRetransmit, (IV_MI != iv->ivGen)); sendPacket(iv, cnt, isRetransmit, (IV_MI != iv->ivGen));
} }
@ -298,12 +312,12 @@ class HmRadio : public Radio {
private: private:
inline bool getReceived(void) { inline bool getReceived(void) {
bool isLastPackage = false; bool isLastPackage = false;
rx_ready = false; // reset for ACK case rx_ready = false; // reset for ACK case
while(mNrf24->available()) { while(mNrf24->available()) {
uint8_t len; uint8_t len = mNrf24->getDynamicPayloadSize(); // payload size > 32 -> corrupt payload
len = mNrf24->getDynamicPayloadSize(); // if payload size > 32, corrupt payload has been flushed
if (len > 0) { if (len > 0) {
packet_t p; packet_t p;
p.ch = mRfChLst[tempRxChIdx]; p.ch = mRfChLst[tempRxChIdx];
@ -311,23 +325,25 @@ class HmRadio : public Radio {
p.rssi = mNrf24->testRPD() ? -64 : -75; p.rssi = mNrf24->testRPD() ? -64 : -75;
p.millis = millis() - mMillis; p.millis = millis() - mMillis;
mNrf24->read(p.packet, p.len); mNrf24->read(p.packet, p.len);
if (p.packet[0] != 0x00) { if (p.packet[0] != 0x00) {
if(!checkIvSerial(p.packet, mLastIv)) { if(!checkIvSerial(p.packet, mLastIv)) {
DPRINT(DBG_WARN, "RX other inverter "); DPRINT(DBG_WARN, "RX other inverter ");
if(*mPrivacyMode) if(!*mPrivacyMode)
ah::dumpBuf(p.packet, p.len, 1, 4);
else
ah::dumpBuf(p.packet, p.len); ah::dumpBuf(p.packet, p.len);
//return false;
} else { } else {
mLastIv->mGotFragment = true; mLastIv->mGotFragment = true;
mBufCtrl.push(p); mBufCtrl.push(p);
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
isLastPackage = (p.packet[9] > ALL_FRAMES); // > ALL_FRAMES indicates last packet received isLastPackage = (p.packet[9] > ALL_FRAMES); // > ALL_FRAMES indicates last packet received
else if (p.packet[0] == ( 0x0f + ALL_FRAMES) ) // response from MI get information command
if(IV_MI == mLastIv->ivGen) {
if (p.packet[0] == (0x0f + ALL_FRAMES)) // response from MI get information command
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
}
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,6 +363,12 @@ class HmRadio : public Radio {
mTxChIdx = iv->heuristics.txRfChId; mTxChIdx = iv->heuristics.txRfChId;
if(*mSerialDebug) { if(*mSerialDebug) {
if(!isRetransmit) {
DPRINT(DBG_INFO, "last tx setup: ");
DBGPRINT(String(mTxSetupTime));
DBGPRINTLN("ms");
}
DPRINT_IVID(DBG_INFO, iv->id); DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINT(F("TX ")); DBGPRINT(F("TX "));
DBGPRINT(String(len)); DBGPRINT(String(len));
@ -376,7 +398,7 @@ class HmRadio : public Radio {
mLastIv = iv; mLastIv = iv;
iv->mDtuTxCnt++; iv->mDtuTxCnt++;
mNRFisInRX = false; mNRFisInRX = false;
mRqstGetRx = true; // preparation only mIsRetransmit = isRetransmit;
} }
uint64_t getIvId(Inverter<> *iv) { uint64_t getIvId(Inverter<> *iv) {
@ -410,6 +432,8 @@ class HmRadio : public Radio {
bool isRxInit = true; bool isRxInit = true;
bool rxPendular = false; bool rxPendular = false;
uint32_t innerLoopTimeout = DURATION_LISTEN_MIN; uint32_t innerLoopTimeout = DURATION_LISTEN_MIN;
uint8_t mTxSetupTime = 0;
bool mIsRetransmit = false;
std::unique_ptr<SPIClass> mSpi; std::unique_ptr<SPIClass> mSpi;
std::unique_ptr<RF24> mNrf24; std::unique_ptr<RF24> mNrf24;

4
src/hm/radio.h

@ -28,8 +28,7 @@ class Radio {
virtual bool switchFrequency(Inverter<> *iv, uint32_t fromkHz, uint32_t tokHz) { return true; } 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 switchFrequencyCh(Inverter<> *iv, uint8_t fromCh, uint8_t toCh) { return true; }
virtual bool isChipConnected(void) { return false; } virtual bool isChipConnected(void) { return false; }
virtual bool loop(void) = 0;
virtual void loop(void) {};
void handleIntr(void) { void handleIntr(void) {
mIrqRcvd = true; mIrqRcvd = true;
@ -126,7 +125,6 @@ class Radio {
uint32_t mDtuSn; uint32_t mDtuSn;
volatile bool mIrqRcvd; volatile bool mIrqRcvd;
bool mRqstGetRx;
bool *mSerialDebug, *mPrivacyMode, *mPrintWholeTrace; bool *mSerialDebug, *mPrivacyMode, *mPrintWholeTrace;
uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE]; uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE];
uint8_t mFramesExpected = 0x0c; uint8_t mFramesExpected = 0x0c;

12
src/hms/hmsRadio.h

@ -26,15 +26,16 @@ class CmtRadio : public Radio {
mPrintWholeTrace = printWholeTrace; mPrintWholeTrace = printWholeTrace;
} }
void loop() { bool loop() {
mCmt.loop(); mCmt.loop();
if((!mIrqRcvd) && (!mRqstGetRx)) if((!mIrqRcvd) && (!mRqstGetRx))
return; return false;
getRx(); getRx();
if(CMT_SUCCESS == mCmt.goRx()) { if(CMT_SUCCESS == mCmt.goRx()) {
mIrqRcvd = false; mIrqRcvd = false;
mRqstGetRx = false; mRqstGetRx = false;
} }
return false;
} }
bool isChipConnected(void) { bool isChipConnected(void) {
@ -163,11 +164,16 @@ class CmtRadio : public Radio {
uint8_t status = mCmt.getRx(p.packet, &p.len, 28, &p.rssi); uint8_t status = mCmt.getRx(p.packet, &p.len, 28, &p.rssi);
if(CMT_SUCCESS == status) if(CMT_SUCCESS == status)
mBufCtrl.push(p); mBufCtrl.push(p);
// this code completly stops communication!
//if(p.packet[9] > ALL_FRAMES) // indicates last frame
// mRadioWaitTime.stopTimeMonitor(); // we got everything we expected and can exit rx mode...
//optionally instead: mRadioWaitTime.startTimeMonitor(DURATION_PAUSE_LASTFR); // let the inverter first get back to rx mode?
} }
CmtType mCmt; CmtType mCmt;
//bool mRqstGetRx;
bool mCmtAvail; bool mCmtAvail;
bool mRqstGetRx = false;
uint32_t mMillis; uint32_t mMillis;
}; };

13
src/utils/timemonitor.h

@ -20,16 +20,14 @@
class TimeMonitor { class TimeMonitor {
public: public:
/** /**
* A constructor for initializing a TimeMonitor * A constructor for creating a TimeMonitor object
* @note TimeMonitor witch default constructor is stopped
*/ */
TimeMonitor(void) {} TimeMonitor(void) {}
/** /**
* A constructor for initializing a TimeMonitor * A constructor for initializing a TimeMonitor object
* @param timeout timeout in ms * @param timeout timeout in ms
* @param start (optional) if true, start TimeMonitor immediately * @param start (optional) if true, start TimeMonitor immediately
* @note TimeMonitor witch default constructor is stopped
*/ */
TimeMonitor(uint32_t timeout, bool start = false) { TimeMonitor(uint32_t timeout, bool start = false) {
if (start) if (start)
@ -50,7 +48,8 @@ class TimeMonitor {
/** /**
* Restart the TimeMonitor with already set timeout configuration * Restart the TimeMonitor with already set timeout configuration
* @note returns nothing * @note a timeout has to be set before, no need to call
* 'startTimeMonitor' before
*/ */
void reStartTimeMonitor(void) { void reStartTimeMonitor(void) {
mStartTime = millis(); mStartTime = millis();
@ -82,7 +81,7 @@ class TimeMonitor {
* false: TimeMonitor still in time or TimeMonitor was stopped * false: TimeMonitor still in time or TimeMonitor was stopped
*/ */
bool isTimeout(void) { bool isTimeout(void) {
if ((mStarted) && (millis() - mStartTime >= mTimeout)) if ((mStarted) && ((millis() - mStartTime) >= mTimeout))
return true; return true;
else else
return false; return false;
@ -104,7 +103,7 @@ class TimeMonitor {
*/ */
uint32_t getResidualTime(void) const { uint32_t getResidualTime(void) const {
uint32_t delayed = millis() - mStartTime; uint32_t delayed = millis() - mStartTime;
return(mStarted ? (delayed < mTimeout ? mTimeout - delayed : 0UL) : 0xFFFFFFFFUL); return(mStarted ? (delayed < mTimeout ? (mTimeout - delayed) : 0UL) : 0xFFFFFFFFUL);
} }
/** /**

1
src/web/html/includes/header.html

@ -4,3 +4,4 @@
<script type="text/javascript" src="api.js?v={#VERSION}"></script> <script type="text/javascript" src="api.js?v={#VERSION}"></script>
<link rel="stylesheet" type="text/css" href="colors.css?v={#VERSION}"/> <link rel="stylesheet" type="text/css" href="colors.css?v={#VERSION}"/>
<meta name="robots" content="noindex, nofollow" /> <meta name="robots" content="noindex, nofollow" />
<link rel="icon" type="image/x-icon" href="/favicon.ico">

Loading…
Cancel
Save