Browse Source

added MI additions / corrections from @rejoe2

pull/1219/head
lumapu 1 year ago
parent
commit
1b965d67a8
  1. 79
      src/hm/Communication.h
  2. 4
      src/hm/hmDefines.h
  3. 42
      src/hm/hmInverter.h
  4. 26
      src/hm/hmRadio.h
  5. 11
      src/hm/radio.h
  6. 6
      src/hms/hmsRadio.h

79
src/hm/Communication.h

@ -71,7 +71,8 @@ class Communication : public CommQueue<> {
case States::CHECK_FRAMES: {
if(!q->iv->radio->get()) { // radio buffer empty
cmdDone();
DPRINT(DBG_INFO, F("request timeout: "));
DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F("request timeout: "));
DBGPRINT(String(millis() - mWaitTimeout + 500));
DBGPRINTLN(F("ms"));
@ -90,11 +91,15 @@ class Communication : public CommQueue<> {
DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F("RX "));
if(p->millis < 100)
DBGPRINT(F("0"));
DBGPRINT(String(p->millis));
DBGPRINT(F("ms "));
DBGPRINT(String(p->len));
if(IV_HM == q->iv->ivGen) {
if((IV_HM == q->iv->ivGen) || (IV_MI == q->iv->ivGen)) {
DBGPRINT(F(" CH"));
if(3 == p->ch)
DBGPRINT(F("0"));
DBGPRINT(String(p->ch));
}
DBGPRINT(F(", "));
@ -111,6 +116,8 @@ class Communication : public CommQueue<> {
} else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) { // response from dev control command
parseDevCtrl(p, q);
cmdDone(true); // remove done request
} else if(IV_MI == q->iv->ivGen) {
parseMiFrame(p, q);
}
} else
DPRINTLN(DBG_WARN, F("Inverter serial does not match"));
@ -227,6 +234,74 @@ class Communication : public CommQueue<> {
f->rssi = p->rssi;
}
inline void parseMiFrame(packet_t *p, const queue_s *q) {
if ((p->packet[0] == MI_REQ_CH1 + ALL_FRAMES)
|| (p->packet[0] == MI_REQ_CH2 + ALL_FRAMES)
|| ((p->packet[0] >= (MI_REQ_4CH + ALL_FRAMES))
&& (p->packet[0] < (0x39 + SINGLE_FRAME))
&& (q->cmd != 0x0f))) {
// 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);
}
}
inline void miDataDecode(packet_t *p, const queue_s *q) {
record_t<> *rec = q->iv->getRecordStruct(RealTimeRunData_Debug); // choose the parser
//rec->ts = mPayload[iv->id].ts;
//mPayload[iv->id].gotFragment = true;
//mPayload[iv->id].multi_parts += 4;
uint8_t datachan = ( p->packet[0] == (MI_REQ_CH1 + ALL_FRAMES) || p->packet[0] == (MI_REQ_4CH + ALL_FRAMES) ) ? CH1 :
( p->packet[0] == (MI_REQ_CH2 + ALL_FRAMES) || p->packet[0] == (0x37 + ALL_FRAMES) ) ? CH2 :
p->packet[0] == (0x38 + ALL_FRAMES) ? CH3 :
CH4;
// count in RF_communication_protocol.xlsx is with offset = -1
q->iv->setValue(q->iv->getPosByChFld(datachan, FLD_UDC, rec), rec, (float)((p->packet[9] << 8) + p->packet[10])/10);
q->iv->setValue(q->iv->getPosByChFld(datachan, FLD_IDC, rec), rec, (float)((p->packet[11] << 8) + p->packet[12])/10);
q->iv->setValue(q->iv->getPosByChFld(0, FLD_UAC, rec), rec, (float)((p->packet[13] << 8) + p->packet[14])/10);
q->iv->setValue(q->iv->getPosByChFld(0, FLD_F, rec), rec, (float) ((p->packet[15] << 8) + p->packet[16])/100);
q->iv->setValue(q->iv->getPosByChFld(datachan, FLD_PDC, rec), rec, (float)((p->packet[17] << 8) + p->packet[18])/10);
q->iv->setValue(q->iv->getPosByChFld(datachan, FLD_YD, rec), rec, (float)((p->packet[19] << 8) + p->packet[20])/1);
q->iv->setValue(q->iv->getPosByChFld(0, FLD_T, rec), rec, (float) ((int16_t)(p->packet[21] << 8) + p->packet[22])/10);
q->iv->setValue(q->iv->getPosByChFld(0, FLD_IRR, rec), rec, (float) (calcIrradiation(q->iv, datachan)));
//mPayload[q->iv->id].rssi[(datachan-1)] = p->rssi;
/*if ( datachan < 3 ) {
mPayload[q->iv->id].dataAB[datachan] = true;
}
if ( !mPayload[iv->id].dataAB[CH0] && mPayload[iv->id].dataAB[CH1] && mPayload[iv->id].dataAB[CH2] ) {
mPayload[iv->id].dataAB[CH0] = true;
}*/
if (p->packet[0] >= (MI_REQ_4CH + ALL_FRAMES) ) {
/*For MI1500:
if (MI1500) {
STAT = (uint8_t)(p->packet[25] );
FCNT = (uint8_t)(p->packet[26]);
FCODE = (uint8_t)(p->packet[27]);
}*/
//miStsConsolidate(iv, datachan, rec, p->packet[23], p->packet[24]);
if (p->packet[0] < (0x39 + ALL_FRAMES) ) {
addImportant(q->iv, (q->cmd + 1));
//mPayload[iv->id].txCmd++;
//mPayload[iv->id].retransmits = 0; // reserve retransmissions for each response
//mPayload[iv->id].complete = false;
} else {
//miComplete(iv);
}
} else if((p->packet[0] == (MI_REQ_CH1 + ALL_FRAMES)) && q->iv->type == INV_TYPE_2CH ) {
addImportant(q->iv, MI_REQ_CH2);
}
}
inline void parseDevCtrl(packet_t *p, const queue_s *q) {
if((p->packet[12] != ActivePowerContr) || (p->packet[13] != 0x00))
return;

4
src/hm/hmDefines.h

@ -346,4 +346,8 @@ const devInfo_t devInfo[] = {
{ 0x103331, 2250 }
};
#define MI_REQ_CH1 0x09
#define MI_REQ_CH2 0x11
#define MI_REQ_4CH 0x36
#endif /*__HM_DEFINES_H__*/

42
src/hm/hmInverter.h

@ -182,19 +182,35 @@ class Inverter {
}
void tickSend(std::function<void(uint8_t cmd, bool isDevControl)> cb) {
if(mDevControlRequest) {
cb(devControlCmd, true);
mDevControlRequest = false;
} else if((alarmLastId != alarmMesIndex) && (alarmMesIndex != 0))
cb(AlarmData, false); // get last alarms
else if(0 == getFwVersion())
cb(InverterDevInform_All, false); // get firmware version
else if(0 == getHwVersion())
cb(InverterDevInform_Simple, false); // get hardware version
else if(actPowerLimit == 0xffff)
cb(SystemConfigPara, false); // power limit info
else
cb(RealTimeRunData_Debug, false); // get live data
if (IV_MI != ivGen) {
if(mDevControlRequest) {
cb(devControlCmd, true);
mDevControlRequest = false;
} else if((alarmLastId != alarmMesIndex) && (alarmMesIndex != 0))
cb(AlarmData, false); // get last alarms
else if(0 == getFwVersion())
cb(InverterDevInform_All, false); // get firmware version
else if(0 == getHwVersion())
cb(InverterDevInform_Simple, false); // get hardware version
else if(actPowerLimit == 0xffff)
cb(SystemConfigPara, false); // power limit info
else
cb(RealTimeRunData_Debug, false); // get live data
} else {
if(mDevControlRequest) {
cb(devControlCmd, true);
mDevControlRequest = false;
} else if(0 == getFwVersion())
cb(MI_REQ_CH1, false); // get firmware version
//cb(InverterDevInform_All, false); // get firmware version
else {
record_t<> *rec = getRecordStruct(InverterDevInform_Simple);
if (getChannelFieldValue(CH0, FLD_PART_NUM, rec) == 0)
cb(InverterDevInform_All, false); // hard- and firmware version for missing HW part nr, delivered by frame 1
else
cb(type == INV_TYPE_4CH ? MI_REQ_4CH : MI_REQ_CH1, false);
}
}
}
/*template <typename T>

26
src/hm/hmRadio.h

@ -117,24 +117,24 @@ class HmRadio : public Radio {
mNrf24.setChannel(mRfChLst[mRxChIdx]);
mNrf24.startListening();
uint32_t startMicros = micros();
uint32_t startMicros = micros() + 5110;
uint32_t loopMillis = millis() + 400;
while (millis() < loopMillis) {
while (micros()-startMicros < 5110) { // listen (4088us or?) 5110us to each channel
while (micros() < startMicros) { // listen (4088us or?) 5110us to each channel
if (mIrqRcvd) {
mIrqRcvd = false;
if (getReceived()) { // everything received
if (getReceived()) // everything received
return;
}
}
yield();
}
// switch to next RX channel
startMicros = micros();
if(++mRxChIdx >= RF_CHANNELS)
mRxChIdx = 0;
mNrf24.setChannel(mRfChLst[mRxChIdx]);
yield();
startMicros = micros() + 5000;
}
// not finished but time is over
return;
@ -145,12 +145,13 @@ class HmRadio : public Radio {
return mNrf24.isChipConnected();
}
void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit, bool isNoMI = true, uint16_t powerMax = 0) {
DPRINT(DBG_INFO, F("sendControlPacket cmd: 0x"));
void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) {
DPRINT_IVID(DBG_INFO, iv->id);
DBGPRINT(F("sendControlPacket cmd: 0x"));
DBGHEXLN(cmd);
initPacket(iv->radioId.u64, TX_REQ_DEVCONTROL, SINGLE_FRAME);
uint8_t cnt = 10;
if (isNoMI) {
if (IV_MI != iv->ivGen) {
mTxBuf[cnt++] = cmd; // cmd -> 0 on, 1 off, 2 restart, 11 active power, 12 reactive power, 13 power factor
mTxBuf[cnt++] = 0x00;
if(cmd >= ActivePowerContr && cmd <= PFSet) { // ActivePowerContr, ReactivePowerContr, PFSet
@ -160,6 +161,7 @@ class HmRadio : public Radio {
mTxBuf[cnt++] = ((data[1] ) ) & 0xff; // setting for persistens handling
}
} else { //MI 2nd gen. specific
uint16_t powerMax = ((iv->powerLimit[1] == RelativNonPersistent) ? 0 : iv->getMaxPower());
switch (cmd) {
case Restart:
case TurnOn:
@ -225,7 +227,7 @@ class HmRadio : public Radio {
}
cnt++;
}
sendPacket(iv, cnt, isRetransmit, isNoMI);
sendPacket(iv, cnt, isRetransmit, (IV_MI != iv->ivGen));
}
uint8_t getDataRate(void) {
@ -297,6 +299,10 @@ class HmRadio : public Radio {
return iv->radioId.u64;
}
uint8_t getIvGen(Inverter<> *iv) {
return iv->ivGen;
}
uint64_t DTU_RADIO_ID;
uint8_t mRfChLst[RF_CHANNELS];
uint8_t mTxChIdx;

11
src/hm/radio.h

@ -21,7 +21,7 @@ class Inverter;
// abstract radio interface
class Radio {
public:
virtual void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit, bool isNoMI = true, uint16_t powerMax = 0) = 0;
virtual void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) = 0;
virtual bool switchFrequency(Inverter<> *iv, uint32_t fromkHz, uint32_t tokHz) { return true; }
virtual void loop(void) {};
@ -43,6 +43,14 @@ class Radio {
}
void prepareDevInformCmd(Inverter<> *iv, 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.
if(IV_MI == getIvGen(iv)) {
DPRINT_IVID(DBG_INFO, getIvId(iv));
DBGPRINT(F("legacy cmd 0x"));
DBGHEXLN(cmd);
sendCmdPacket(iv, cmd, cmd, false, false);
return;
}
if(mSerialDebug) {
DPRINT(DBG_DEBUG, F("prepareDevInformCmd 0x"));
DPRINTLN(DBG_DEBUG,String(cmd, HEX));
@ -63,6 +71,7 @@ class Radio {
protected:
virtual void sendPacket(Inverter<> *iv, uint8_t len, bool isRetransmit, bool appendCrc16=true) = 0;
virtual uint64_t getIvId(Inverter<> *iv) = 0;
virtual uint8_t getIvGen(Inverter<> *iv) = 0;
void initPacket(uint64_t ivId, uint8_t mid, uint8_t pid) {
mTxBuf[0] = mid;

6
src/hms/hmsRadio.h

@ -44,7 +44,7 @@ class CmtRadio : public Radio {
return mCmtAvail;
}
void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit, bool isNoMI = true, uint16_t powerMax = 0) {
void sendControlPacket(Inverter<> *iv, uint8_t cmd, uint16_t *data, bool isRetransmit) {
DPRINT(DBG_INFO, F("sendControlPacket cmd: 0x"));
DBGHEXLN(cmd);
initPacket(iv->radioId.u64, TX_REQ_DEVCONTROL, SINGLE_FRAME);
@ -101,6 +101,10 @@ class CmtRadio : public Radio {
return iv->radioId.u64;
}
uint8_t getIvGen(Inverter<> *iv) {
return iv->ivGen;
}
inline void reset(bool genDtuSn) {
if(genDtuSn)
generateDtuSn();

Loading…
Cancel
Save