Browse Source

improved HMS and CMT configuration

reconnect on timeout (30s)
introduced frequency ranges for EU
pull/935/head
lumapu 2 years ago
parent
commit
c4e20b6395
  1. 162
      src/hms/cmt2300a.h
  2. 14
      src/hms/hmsPayload.h
  3. 71
      src/hms/hmsRadio.h

162
src/hms/cmt2300a.h

@ -8,6 +8,15 @@
#include "esp32_3wSpi.h" #include "esp32_3wSpi.h"
#define WORK_FREQ_KHZ 865000 // disired work frequency between DTU and
// inverter in kHz
#define HOY_BASE_FREQ_KHZ 860000 // in kHz
#define HOY_MAX_FREQ_KHZ 923500 // 0xFE * 250kHz + Base_freq
#define HOY_BOOT_FREQ_KHZ 868000 // Hoymiles boot/init frequency after power up inverter
#define FREQ_STEP_KHZ 250 // channel step size in kHz
#define FREQ_WARN_MIN_KHZ 863000 // for EU 863 - 870 MHz is allowed
#define FREQ_WARN_MAX_KHZ 870000 // for EU 863 - 870 MHz is allowed
// detailed register infos from AN142_CMT2300AW_Quick_Start_Guide-Rev0.8.pdf // detailed register infos from AN142_CMT2300AW_Quick_Start_Guide-Rev0.8.pdf
#define CMT2300A_MASK_CFG_RETAIN 0x10 #define CMT2300A_MASK_CFG_RETAIN 0x10
@ -144,24 +153,24 @@
// default CMT paramters // default CMT paramters
static uint8_t cmtConfig[0x60] PROGMEM { static uint8_t cmtConfig[0x60] PROGMEM {
// 0x00 - 0x0f // 0x00 - 0x0f -- RSSI offset +- 0 and 13dBm
0x00, 0x66, 0xEC, 0x1D, 0x70, 0x80, 0x14, 0x08, 0x00, 0x66, 0xEC, 0x1C, 0x70, 0x80, 0x14, 0x08,
0x91, 0x02, 0x02, 0xD0, 0xAE, 0xE0, 0x35, 0x00, 0x11, 0x02, 0x02, 0x00, 0xAE, 0xE0, 0x35, 0x00,
// 0x10 - 0x1f // 0x10 - 0x1f
0x00, 0xF4, 0x10, 0xE2, 0x42, 0x20, 0x0C, 0x81, 0x00, 0xF4, 0x10, 0xE2, 0x42, 0x20, 0x0C, 0x81,
0x42, 0x6D, 0x80, 0x86, 0x42, 0x62, 0x27, 0x16, // 0x42, 0xCF, 0xA7, 0x8C, 0x42, 0xC4, 0x4E, 0x1C, 0x42, 0x32, 0xCF, 0x82, 0x42, 0x27, 0x76, 0x12, // 860MHz as default
// 0x20 - 0x2f // 0x20 - 0x2f
0xA6, 0xC9, 0x20, 0x20, 0xD2, 0x35, 0x0C, 0x0A, 0xA6, 0xC9, 0x20, 0x20, 0xD2, 0x35, 0x0C, 0x0A,
0x9F, 0x4B, 0x0A, 0x29, 0xC0, 0x14, 0x05, 0x53, // 0x9F, 0x4B, 0x29, 0x29, 0xC0, 0x14, 0x05, 0x53, 0x9F, 0x4B, 0x29, 0x29, 0xC0, 0x14, 0x05, 0x53,
// 0x30 - 0x3f // 0x30 - 0x3f
0x10, 0x00, 0xB4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0xB4, 0x00, 0x00, 0x01, 0x00, 0x00,
0x12, 0x1E, 0x00, 0xAA, 0x06, 0x00, 0x00, 0x00, 0x12, 0x1E, 0x00, 0xAA, 0x06, 0x00, 0x00, 0x00,
// 0x40 - 0x4f // 0x40 - 0x4f
0x00, 0x48, 0x5A, 0x48, 0x4D, 0x01, 0x1D, 0x00, // 0x00, 0xD6, 0xD5, 0xD4, 0x2D, 0x01, 0x1D, 0x00, 0x00, 0x48, 0x5A, 0x48, 0x4D, 0x01, 0x1D, 0x00,
0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x60,
// 0x50 - 0x5f // 0x50 - 0x5f - TX 13dBm
0xFF, 0x00, 0x00, 0x1F, 0x10, 0x70, 0x4D, 0x06, 0xFF, 0x00, 0x00, 0x1F, 0x10, 0x70, 0x4D, 0x06,
0x00, 0x07, 0x50, 0x00, 0x8A, 0x18, 0x3F, 0x7F 0x00, 0x07, 0x50, 0x00, 0x42, 0x0C, 0x3F, 0x7F
}; };
enum {CMT_SUCCESS = 0, CMT_ERR_SWITCH_STATE, CMT_ERR_TX_PENDING, CMT_FIFO_EMPTY, CMT_ERR_RX_IN_FIFO}; enum {CMT_SUCCESS = 0, CMT_ERR_SWITCH_STATE, CMT_ERR_TX_PENDING, CMT_FIFO_EMPTY, CMT_ERR_RX_IN_FIFO};
@ -215,10 +224,7 @@ class Cmt2300a {
else else
mSpi.writeReg(CMT2300A_CUS_INT_CLR2, 0x00); mSpi.writeReg(CMT2300A_CUS_INT_CLR2, 0x00);
//mSpi.readReg(CMT2300A_CUS_FIFO_CTL); // necessary? -> if 0x02 last was read
// 0x07 last was write
mSpi.writeReg(CMT2300A_CUS_FIFO_CTL, 0x02); mSpi.writeReg(CMT2300A_CUS_FIFO_CTL, 0x02);
mSpi.writeReg(CMT2300A_CUS_FIFO_CLR, 0x02); mSpi.writeReg(CMT2300A_CUS_FIFO_CLR, 0x02);
mSpi.writeReg(0x16, 0x0C); // [4:3]: RSSI_DET_SEL, [2:0]: RSSI_AVG_MODE mSpi.writeReg(0x16, 0x0C); // [4:3]: RSSI_DET_SEL, [2:0]: RSSI_AVG_MODE
@ -272,33 +278,28 @@ class Cmt2300a {
mSpi.writeReg(CMT2300A_CUS_INT1_CTL, CMT2300A_INT_SEL_TX_DONE); mSpi.writeReg(CMT2300A_CUS_INT1_CTL, CMT2300A_INT_SEL_TX_DONE);
//mCusIntFlag == mSpi.readReg(CMT2300A_CUS_INT_FLAG); // no data received
//if(0x00 == mCusIntFlag) { mSpi.readReg(CMT2300A_CUS_INT_CLR1);
// no data received mSpi.writeReg(CMT2300A_CUS_INT_CLR1, 0x00);
mSpi.readReg(CMT2300A_CUS_INT_CLR1); mSpi.writeReg(CMT2300A_CUS_INT_CLR2, 0x00);
mSpi.writeReg(CMT2300A_CUS_INT_CLR1, 0x00);
mSpi.writeReg(CMT2300A_CUS_INT_CLR2, 0x00);
//mSpi.readReg(CMT2300A_CUS_FIFO_CTL); // necessary? //mSpi.readReg(CMT2300A_CUS_FIFO_CTL); // necessary?
mSpi.writeReg(CMT2300A_CUS_FIFO_CTL, 0x07); mSpi.writeReg(CMT2300A_CUS_FIFO_CTL, 0x07);
mSpi.writeReg(CMT2300A_CUS_FIFO_CLR, 0x01); mSpi.writeReg(CMT2300A_CUS_FIFO_CLR, 0x01);
mSpi.writeReg(0x45, 0x01); mSpi.writeReg(0x45, 0x01);
mSpi.writeReg(0x46, len); // payload length mSpi.writeReg(0x46, len); // payload length
mSpi.writeFifo(buf, len); mSpi.writeFifo(buf, len);
// send only on base frequency: here 863.0 MHz // send only on base frequency: here 863.0 MHz
swichChannel((len != 15)); //switchChannel((len != 15));
if(!cmtSwitchStatus(CMT2300A_GO_TX, CMT2300A_STA_TX)) if(!cmtSwitchStatus(CMT2300A_GO_TX, CMT2300A_STA_TX))
return CMT_ERR_SWITCH_STATE; return CMT_ERR_SWITCH_STATE;
// wait for tx done // wait for tx done
mTxPending = true; mTxPending = true;
//}
//else
// return CMT_ERR_RX_IN_FIFO;
return CMT_SUCCESS; return CMT_SUCCESS;
} }
@ -311,25 +312,13 @@ class Cmt2300a {
if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY))
return false; return false;
//if(0xAA != mSpi.readReg(0x48)) mSpi.writeReg(CMT2300A_CUS_MODE_STA, 0x52);
// mSpi.writeReg(0x48, 0xAA); mSpi.writeReg(0x62, 0x20);
//mSpi.readReg(0x48);
//mSpi.writeReg(0x4c, 0x00);
//if(0x52 != mSpi.readReg(CMT2300A_CUS_MODE_STA))
mSpi.writeReg(CMT2300A_CUS_MODE_STA, 0x52);
//if(0x20 != mSpi.readReg(0x62))
mSpi.writeReg(0x62, 0x20);
//mSpi.readReg(0x0D);
//mSpi.writeReg(0x0F, 0x00);
for(uint8_t i = 0; i < 0x60; i++) { for(uint8_t i = 0; i < 0x60; i++) {
mSpi.writeReg(i, cmtConfig[i]); mSpi.writeReg(i, cmtConfig[i]);
} }
//if(0x02 != mSpi.readReg(0x09))
// mSpi.writeReg(0x09, 0x02);
mSpi.writeReg(CMT2300A_CUS_IO_SEL, 0x20); // -> GPIO3_SEL[1:0] = 0x02 mSpi.writeReg(CMT2300A_CUS_IO_SEL, 0x20); // -> GPIO3_SEL[1:0] = 0x02
// interrupt 1 control selection to TX DONE // interrupt 1 control selection to TX DONE
@ -343,10 +332,6 @@ class Cmt2300a {
// interrupt enable (TX_DONE, PREAM_OK, SYNC_OK, CRC_OK, PKT_DONE) // interrupt enable (TX_DONE, PREAM_OK, SYNC_OK, CRC_OK, PKT_DONE)
mSpi.writeReg(CMT2300A_CUS_INT_EN, 0x3B); mSpi.writeReg(CMT2300A_CUS_INT_EN, 0x3B);
/*mSpi.writeReg(0x41, 0x48);
mSpi.writeReg(0x42, 0x5A);
mSpi.writeReg(0x43, 0x48);
mSpi.writeReg(0x44, 0x4D);*/
mSpi.writeReg(0x64, 0x64); mSpi.writeReg(0x64, 0x64);
if(0x00 == mSpi.readReg(CMT2300A_CUS_FIFO_CTL)) if(0x00 == mSpi.readReg(CMT2300A_CUS_FIFO_CTL))
@ -357,43 +342,44 @@ class Cmt2300a {
delayMicroseconds(95); delayMicroseconds(95);
// base frequency 863MHz; with value of CMT2300A_CUS_FREQ_CHNL
// the frequency can be increased in a step size of ~0.24Hz
/*mSpi.writeReg(0x18, 0x42);
mSpi.writeReg(0x19, 0x6D);
mSpi.writeReg(0x1A, 0x80);
mSpi.writeReg(0x1B, 0x86);
mSpi.writeReg(0x1C, 0x42);
mSpi.writeReg(0x1D, 0x62);
mSpi.writeReg(0x1E, 0x27);
mSpi.writeReg(0x1F, 0x16);*/
/*mSpi.writeReg(0x22, 0x20);
mSpi.writeReg(0x23, 0x20);
mSpi.writeReg(0x24, 0xD2);
mSpi.writeReg(0x25, 0x35);
mSpi.writeReg(0x26, 0x0C);
mSpi.writeReg(0x27, 0x0A);
mSpi.writeReg(0x28, 0x9F);
mSpi.writeReg(0x29, 0x4B);
mSpi.writeReg(0x27, 0x0A);*/
if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY))
return false; return false;
/*mSpi.writeReg(0x03, 0x1D);
mSpi.writeReg(0x5C, 0x8A);
mSpi.writeReg(0x5D, 0x18);*/
if(!cmtSwitchStatus(CMT2300A_GO_SLEEP, CMT2300A_STA_SLEEP)) if(!cmtSwitchStatus(CMT2300A_GO_SLEEP, CMT2300A_STA_SLEEP))
return false; return false;
if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY))
return false; return false;
switchDtuFreq(WORK_FREQ_KHZ);
return true; return true;
} }
inline uint8_t freq2Chan(const uint32_t freqKhz) {
if((freqKhz % FREQ_STEP_KHZ) != 0) {
DPRINT(DBG_WARN, F("swtich frequency to "));
DBGPRINT(String(freqKhz));
DBGPRINT(F("kHz not possible!"));
return 0xff; // error
// apply the nearest frequency
//freqKhz = (freqKhz + FREQ_STEP_KHZ/2) / FREQ_STEP_KHZ;
//freqKhz *= FREQ_STEP_KHZ;
}
if((freqKhz < HOY_BASE_FREQ_KHZ) || (freqKhz > HOY_MAX_FREQ_KHZ))
return 0xff; // error
if((freqKhz < FREQ_WARN_MIN_KHZ) || (freqKhz > FREQ_WARN_MAX_KHZ))
DPRINTLN(DBG_WARN, F("Disired frequency is out of EU legal range! (863 - 870MHz)"));
return (freqKhz - HOY_BASE_FREQ_KHZ) / FREQ_STEP_KHZ;
}
inline void switchChannel(uint8_t ch) {
mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, ch);
}
private: private:
void init() { void init() {
mTxPending = false; mTxPending = false;
@ -415,23 +401,14 @@ class Cmt2300a {
return false; return false;
} }
inline void swichChannel(bool def = true, uint8_t start = 0x00, uint8_t end = 0x22) { inline bool switchDtuFreq(const uint32_t freqKhz) {
if(!def) { uint8_t toCh = freq2Chan(freqKhz);
if(++mCnt > 2) { if(0xff == toCh)
if(++mRxTxCh > end) return false;
mRxTxCh = start;
mCnt = 0; switchChannel(toCh);
}
} return true;
// 0: 868.00MHz
// 1: 868.23MHz
// 2: 868.46MHz
// 3: 868.72MHz
// 4: 868.97MHz
if(!def)
mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, mRxTxCh);
else
mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, 0x00);
} }
inline uint8_t getChipStatus(void) { inline uint8_t getChipStatus(void) {
@ -441,7 +418,6 @@ class Cmt2300a {
SpiType mSpi; SpiType mSpi;
uint8_t mCnt; uint8_t mCnt;
bool mTxPending; bool mTxPending;
uint8_t mRxTxCh;
bool mInRxMode; bool mInRxMode;
uint8_t mCusIntFlag; uint8_t mCusIntFlag;
}; };

14
src/hms/hmsPayload.h

@ -11,6 +11,8 @@
#include "../config/config.h" #include "../config/config.h"
#include <Arduino.h> #include <Arduino.h>
#define HMS_TIMEOUT_MS 30000 // 30s * 1000
typedef struct { typedef struct {
uint8_t txCmd; uint8_t txCmd;
uint8_t txId; uint8_t txId;
@ -50,7 +52,7 @@ class HmsPayload {
//mHighPrioIv = NULL; //mHighPrioIv = NULL;
mCbAlarm = NULL; mCbAlarm = NULL;
mCbPayload = NULL; mCbPayload = NULL;
mFirst = true; mLastRx = 0;
} }
void enableSerialDebug(bool enable) { void enableSerialDebug(bool enable) {
@ -137,9 +139,10 @@ class HmsPayload {
mRadio->prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false); mRadio->prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false);
mPayload[iv->id].txCmd = cmd; mPayload[iv->id].txCmd = cmd;
}*/ }*/
if(mFirst) { DPRINT(DBG_INFO, "LastRx: ");
mFirst = false; DBGPRINTLN(String(mLastRx));
mRadio->setIvBackChannel(&iv->radioId.u64); if((mLastRx + HMS_TIMEOUT_MS) < millis()) {
mRadio->switchFrequency(&iv->radioId.u64, HOY_BOOT_FREQ_KHZ, WORK_FREQ_KHZ);
} else { } else {
uint8_t cmd = iv->getQueuedCmd(); uint8_t cmd = iv->getQueuedCmd();
DPRINT(DBG_INFO, F("(#")); DPRINT(DBG_INFO, F("(#"));
@ -151,6 +154,7 @@ class HmsPayload {
} }
void add(Inverter<> *iv, hmsPacket_t *p) { void add(Inverter<> *iv, hmsPacket_t *p) {
mLastRx = millis();
if (p->data[1] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command if (p->data[1] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command
mPayload[iv->id].txId = p->data[1]; mPayload[iv->id].txId = p->data[1];
DPRINTLN(DBG_DEBUG, F("Response from info request received")); DPRINTLN(DBG_DEBUG, F("Response from info request received"));
@ -398,10 +402,10 @@ class HmsPayload {
statistics_t *mStat; statistics_t *mStat;
uint8_t mMaxRetrans; uint8_t mMaxRetrans;
uint32_t *mTimestamp; uint32_t *mTimestamp;
uint32_t mLastRx;
hmsPayload_t mPayload[MAX_NUM_INVERTERS]; hmsPayload_t mPayload[MAX_NUM_INVERTERS];
bool mSerialDebug; bool mSerialDebug;
Inverter<> *mHighPrioIv; Inverter<> *mHighPrioIv;
bool mFirst;
alarmListenerType mCbAlarm; alarmListenerType mCbAlarm;
payloadListenerType mCbPayload; payloadListenerType mCbPayload;

71
src/hms/hmsRadio.h

@ -41,12 +41,6 @@ class CmtRadio {
bool loop() { bool loop() {
mCmt.loop(); mCmt.loop();
if(++mCnt > 30000) {
mCnt = 0;
if(NULL != mIvIdChannelSet)
prepareSwitchChannelCmd(mIvIdChannelSet);
}
if(!mIrqRcvd) if(!mIrqRcvd)
return false; return false;
mIrqRcvd = false; mIrqRcvd = false;
@ -66,14 +60,17 @@ class CmtRadio {
mSerialDebug = true; mSerialDebug = true;
} }
void setIvBackChannel(const uint64_t *ivId) { bool switchFrequency(const uint64_t *ivId, uint32_t fromkHz, uint32_t tokHz) {
mIvIdChannelSet = ivId; uint8_t fromCh = mCmt.freq2Chan(fromkHz);
Serial.println("Byte 3 " + String(U32_B3((*mIvIdChannelSet) >> 8), HEX)); uint8_t toCh = mCmt.freq2Chan(tokHz);
Serial.println("Byte 2 " + String(U32_B2((*mIvIdChannelSet) >> 8), HEX));
Serial.println("Byte 1 " + String(U32_B1((*mIvIdChannelSet) >> 8), HEX));
Serial.println("Byte 0 " + String(U32_B0((*mIvIdChannelSet) >> 8), HEX));
prepareSwitchChannelCmd(mIvIdChannelSet);
if((0xff == fromCh) || (0xff == toCh))
return false;
mCmt.switchChannel(fromCh);
sendSwitchChCmd(ivId, toCh);
mCmt.switchChannel(toCh);
return true;
} }
void prepareDevInformCmd(const uint64_t *ivId, uint8_t cmd, uint32_t ts, uint16_t alarmMesId, bool isRetransmit, uint8_t reqfld=TX_REQ_INFO) { // might not be necessary to add additional arg. void prepareDevInformCmd(const uint64_t *ivId, uint8_t cmd, uint32_t ts, uint16_t alarmMesId, bool isRetransmit, uint8_t reqfld=TX_REQ_INFO) { // might not be necessary to add additional arg.
@ -87,22 +84,6 @@ class CmtRadio {
sendPacket(24, isRetransmit); sendPacket(24, isRetransmit);
} }
inline void prepareSwitchChannelCmd(const uint64_t *ivId, uint8_t freqSel = 0x0c) {
/** freqSel:
* 0x0c: 863.00 MHz
* 0x0d: 863.24 MHz
* 0x0e: 863.48 MHz
* 0x0f: 863.72 MHz
* 0x10: 863.96 MHz
* */
initPacket(ivId, 0x56, 0x02);
mTxBuf[10] = 0x15;
mTxBuf[11] = 0x21;
mTxBuf[12] = freqSel;
mTxBuf[13] = 0x14;
sendPacket(14, false);
}
void sendPacket(uint8_t len, bool isRetransmit) { void sendPacket(uint8_t len, bool isRetransmit) {
if (len > 14) { if (len > 14) {
uint16_t crc = ah::crc16(&mTxBuf[10], len - 10); uint16_t crc = ah::crc16(&mTxBuf[10], len - 10);
@ -149,9 +130,23 @@ class CmtRadio {
mSendCnt = 0; mSendCnt = 0;
mRetransmits = 0; mRetransmits = 0;
mSerialDebug = false; mSerialDebug = false;
mIvIdChannelSet = NULL;
mIrqRcvd = false; mIrqRcvd = false;
mCnt = 0; }
inline void sendSwitchChCmd(const uint64_t *ivId, uint8_t ch) {
/** ch:
* 0x0c: 863.00 MHz
* 0x0d: 863.24 MHz
* 0x0e: 863.48 MHz
* 0x0f: 863.72 MHz
* 0x10: 863.96 MHz
* */
initPacket(ivId, 0x56, 0x02);
mTxBuf[10] = 0x15;
mTxBuf[11] = 0x21;
mTxBuf[12] = ch;
mTxBuf[13] = 0x14;
sendPacket(14, false);
} }
void initPacket(const uint64_t *ivId, uint8_t mid, uint8_t pid) { void initPacket(const uint64_t *ivId, uint8_t mid, uint8_t pid) {
@ -180,27 +175,13 @@ class CmtRadio {
uint8_t status = mCmt.getRx(p.data, 28, &p.rssi); uint8_t status = mCmt.getRx(p.data, 28, &p.rssi);
if(CMT_SUCCESS == status) if(CMT_SUCCESS == status)
mBufCtrl.push(p); mBufCtrl.push(p);
if(NULL != mIvIdChannelSet) {
if(U32_B3((*mIvIdChannelSet) >> 8) != p.data[5])
return;
if(U32_B2((*mIvIdChannelSet) >> 8) != p.data[4])
return;
if(U32_B1((*mIvIdChannelSet) >> 8) != p.data[3])
return;
if(U32_B0((*mIvIdChannelSet) >> 8) != p.data[2])
return;
mIvIdChannelSet = NULL;
}
} }
CmtType mCmt; CmtType mCmt;
uint32_t mDtuSn; uint32_t mDtuSn;
uint8_t mTxBuf[27]; uint8_t mTxBuf[27];
bool mSerialDebug; bool mSerialDebug;
const uint64_t *mIvIdChannelSet;
bool mIrqRcvd; bool mIrqRcvd;
uint16_t mCnt;
}; };
#endif /*__HMS_RADIO_H__*/ #endif /*__HMS_RADIO_H__*/

Loading…
Cancel
Save