From 20713c9ffbf378a968bb77222616d40d77509dc1 Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Wed, 23 Aug 2023 10:45:58 +0200 Subject: [PATCH 1/5] MI - first update on HW detection see https://github.com/lumapu/ahoy/issues/1111 --- src/hm/hmDefines.h | 6 +++++- src/hm/miPayload.h | 37 ++++++++++++++++++++++++------------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h index 3c63aa9e..edf1fc99 100644 --- a/src/hm/hmDefines.h +++ b/src/hm/hmDefines.h @@ -25,7 +25,7 @@ enum {FLD_UDC = 0, FLD_IDC, FLD_PDC, FLD_YD, FLD_YW, FLD_YT, FLD_FW_BUILD_MONTH_DAY, FLD_FW_BUILD_HOUR_MINUTE, FLD_BOOTLOADER_VER, FLD_ACT_ACTIVE_PWR_LIMIT, FLD_PART_NUM, FLD_HW_VERSION, FLD_GRID_PROFILE_CODE, FLD_GRID_PROFILE_VERSION, /*FLD_ACT_REACTIVE_PWR_LIMIT, FLD_ACT_PF,*/ FLD_LAST_ALARM_CODE, FLD_MP}; - + const char* const fields[] = {"U_DC", "I_DC", "P_DC", "YieldDay", "YieldWeek", "YieldTotal", "U_AC", "U_AC_1N", "U_AC_2N", "U_AC_3N", "UAC_12", "UAC_23", "UAC_31", "I_AC", "IAC_1", "I_AC_2", "I_AC_3", "P_AC", "F_AC", "Temp", "PF_AC", "Efficiency", "Irradiation","Q_AC", @@ -260,6 +260,10 @@ typedef struct { } devInfo_t; const devInfo_t devInfo[] = { + // MI 2nd gen + { 0x13118f, 600 }, + + // MI 3rd gen { 0x100230, 1500 }, diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index fb909663..efb6102b 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -219,12 +219,13 @@ case InverterDevInform_All: rec->assign = (byteAssign_t *)InfoAssignment; rec->pyldLen = HMINFO_PAYLOAD_LEN; break; + const byteAssign_t InfoAssignment[] = { { FLD_FW_VERSION, UNIT_NONE, CH0, 0, 2, 1 }, { FLD_FW_BUILD_YEAR, UNIT_NONE, CH0, 2, 2, 1 }, { FLD_FW_BUILD_MONTH_DAY, UNIT_NONE, CH0, 4, 2, 1 }, { FLD_FW_BUILD_HOUR_MINUTE, UNIT_NONE, CH0, 6, 2, 1 }, - { FLD_HW_ID, UNIT_NONE, CH0, 8, 2, 1 } + { FLD_BOOTLOADER_VER, UNIT_NONE, CH0, 8, 2, 1 } }; */ @@ -237,27 +238,37 @@ const byteAssign_t InfoAssignment[] = { mPayload[iv->id].gotFragment = true; if(mSerialDebug) { DPRINT_IVID(DBG_INFO, iv->id); - DPRINT(DBG_INFO,F("HW_VER is ")); - DBGPRINTLN(String((p->packet[24] << 8) + p->packet[25])); + DPRINT(DBG_INFO,F("HW_VER is ")); + DBGPRINTLN(String((p->packet[24] << 8) + p->packet[25])); } + record_t<> *rec = iv->getRecordStruct(InverterDevInform_Simple); // choose the record structure + rec->ts = mPayload[iv->id].ts; + iv->setValue(1, rec, (uint16_t) ((p->packet[24] << 8) + p->packet[25])/1); + //28737 } else if ( p->packet[9] == 0x01 || p->packet[9] == 0x10 ) {//second frame for MI, 3rd gen. answers in 0x10 DPRINT_IVID(DBG_INFO, iv->id); if ( p->packet[9] == 0x01 ) { DBGPRINTLN(F("got 2nd frame (hw info)")); - DPRINT(DBG_INFO,F("HW_PartNo ")); - DBGPRINTLN(String((uint32_t) (((p->packet[10] << 8) | p->packet[11]) << 8 | p->packet[12]) << 8 | p->packet[13])); + DPRINT(DBG_INFO,F("HW_PartNo ")); + DBGPRINTLN(String((uint32_t) (((p->packet[10] << 8) | p->packet[11]) << 8 | p->packet[12]) << 8 | p->packet[13])); mPayload[iv->id].gotFragment = true; - iv->setValue(iv->getPosByChFld(0, FLD_YT, rec), rec, (float) ((p->packet[20] << 8) + p->packet[21])/1); + record_t<> *rec = iv->getRecordStruct(InverterDevInform_Simple); // choose the record structure + rec->ts = mPayload[iv->id].ts; + /*for (uint8_t i = 0; i < 5; i++) { + iv->setValue(i, rec, (float) ((p->packet[(10+2*i)] << 8) + p->packet[(11+2*i)])/1); + }*/ + iv->setValue(0, rec, (uint32_t) ((((p->packet[10] << 8) | p->packet[11]) << 8 | p->packet[12]) << 8 | p->packet[13])/1); + if(mSerialDebug) { - DPRINT(DBG_INFO,F("HW_FB_TLmValue ")); - DBGPRINTLN(String((p->packet[14] << 8) + p->packet[15])); - DPRINT(DBG_INFO,F("HW_FB_ReSPRT ")); - DBGPRINTLN(String((p->packet[16] << 8) + p->packet[17])); - DPRINT(DBG_INFO,F("HW_GridSamp_ResValule ")); - DBGPRINTLN(String((p->packet[18] << 8) + p->packet[19])); + DPRINT(DBG_INFO,F("HW_FB_TLmValue ")); + DBGPRINTLN(String((p->packet[14] << 8) + p->packet[15])); + DPRINT(DBG_INFO,F("HW_FB_ReSPRT ")); + DBGPRINTLN(String((p->packet[16] << 8) + p->packet[17])); + DPRINT(DBG_INFO,F("HW_GridSamp_ResValule ")); + DBGPRINTLN(String((p->packet[18] << 8) + p->packet[19])); DPRINT(DBG_INFO,F("HW_ECapValue ")); DBGPRINTLN(String((p->packet[20] << 8) + p->packet[21])); - } + } } else { DBGPRINTLN(F("3rd gen. inverter!")); // see table in OpenDTU code, DevInfoParser.cpp devInfo[] } From 5fc80f660a64f249d25d7dc8e4efd395ae5f2500 Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Wed, 23 Aug 2023 18:28:44 +0200 Subject: [PATCH 2/5] Add files via upload --- src/hm/hmInverter.h | 2 +- src/hm/miPayload.h | 32 ++++++++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 75ab9ec4..dc6c9779 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -210,7 +210,7 @@ class Inverter { enqueCommand(InverterDevInform_Simple); // hardware version enqueCommand(RealTimeRunData_Debug); // live data } else if (ivGen == IV_MI){ - if (getFwVersion() == 0) + if (getFwVersion() == 0 || getHwVersion() == 0) enqueCommand(InverterDevInform_All); // firmware version; might not work, esp. for 1/2 ch hardware if (type == INV_TYPE_4CH) { enqueCommand(0x36); diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index efb6102b..a16cbe21 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -243,20 +243,26 @@ const byteAssign_t InfoAssignment[] = { } record_t<> *rec = iv->getRecordStruct(InverterDevInform_Simple); // choose the record structure rec->ts = mPayload[iv->id].ts; - iv->setValue(1, rec, (uint16_t) ((p->packet[24] << 8) + p->packet[25])/1); + iv->setValue(1, rec, (uint32_t) ((p->packet[24] << 8) + p->packet[25])); //28737 } else if ( p->packet[9] == 0x01 || p->packet[9] == 0x10 ) {//second frame for MI, 3rd gen. answers in 0x10 DPRINT_IVID(DBG_INFO, iv->id); if ( p->packet[9] == 0x01 ) { DBGPRINTLN(F("got 2nd frame (hw info)")); + /* according to xlsx (different start byte -1!) + byte[11] to byte[14] HW_PN + byte[15] byte[16] HW_FB_TLmValue + byte[17] byte[18] HW_FB_ReSPRT + byte[19] byte[20] HW_GridSamp_ResValule + byte[21] byte[22] HW_ECapValue + byte[23] to byte[26] Matching_APPFW_PN + */ + DPRINT(DBG_INFO,F("HW_PartNo ")); DBGPRINTLN(String((uint32_t) (((p->packet[10] << 8) | p->packet[11]) << 8 | p->packet[12]) << 8 | p->packet[13])); mPayload[iv->id].gotFragment = true; record_t<> *rec = iv->getRecordStruct(InverterDevInform_Simple); // choose the record structure rec->ts = mPayload[iv->id].ts; - /*for (uint8_t i = 0; i < 5; i++) { - iv->setValue(i, rec, (float) ((p->packet[(10+2*i)] << 8) + p->packet[(11+2*i)])/1); - }*/ iv->setValue(0, rec, (uint32_t) ((((p->packet[10] << 8) | p->packet[11]) << 8 | p->packet[12]) << 8 | p->packet[13])/1); if(mSerialDebug) { @@ -268,6 +274,8 @@ const byteAssign_t InfoAssignment[] = { DBGPRINTLN(String((p->packet[18] << 8) + p->packet[19])); DPRINT(DBG_INFO,F("HW_ECapValue ")); DBGPRINTLN(String((p->packet[20] << 8) + p->packet[21])); + DPRINT(DBG_INFO,F("Matching_APPFW_PN ")); + DBGPRINTLN(String((uint32_t) (((p->packet[22] << 8) | p->packet[23]) << 8 | p->packet[24]) << 8 | p->packet[25])); } } else { DBGPRINTLN(F("3rd gen. inverter!")); // see table in OpenDTU code, DevInfoParser.cpp devInfo[] @@ -276,6 +284,22 @@ const byteAssign_t InfoAssignment[] = { } else if ( p->packet[9] == 0x12 ) {//3rd frame DPRINT_IVID(DBG_INFO, iv->id); DBGPRINTLN(F("got 3rd frame (hw info)")); + /* according to xlsx (different start byte -1!) + byte[11] byte[12] APPFW_MINVER + byte[13] byte[14] HWInfoAddr + byte[15] byte[16] PNInfoCRC_gusv + byte[15] byte[16] PNInfoCRC_gusv + */ + if(mSerialDebug) { + DPRINT(DBG_INFO,F("APPFW_MINVER ")); + DBGPRINTLN(String((p->packet[10] << 8) + p->packet[11])); + DPRINT(DBG_INFO,F("HWInfoAddr ")); + DBGPRINTLN(String((p->packet[12] << 8) + p->packet[13])); + DPRINT(DBG_INFO,F("PNInfoCRC_gusv ")); + DBGPRINTLN(String((p->packet[14] << 8) + p->packet[15])); + DPRINT(DBG_INFO,F("PNInfoCRC_gusv (pt. 2?) ")); + DBGPRINTLN(String((p->packet[16] << 8) + p->packet[17])); + } iv->setQueuedCmdFinished(); mPayload[iv->id].complete = true; mStat->rxSuccess++; From f9857b52ab41f47c4418eac4519685f53f81fed1 Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Thu, 24 Aug 2023 10:10:47 +0200 Subject: [PATCH 3/5] MI - assure HW part no is there --- src/hm/hmInverter.h | 9 +++++++-- src/hm/miPayload.h | 4 +++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index dc6c9779..d00e9e5d 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -210,8 +210,13 @@ class Inverter { enqueCommand(InverterDevInform_Simple); // hardware version enqueCommand(RealTimeRunData_Debug); // live data } else if (ivGen == IV_MI){ - if (getFwVersion() == 0 || getHwVersion() == 0) - enqueCommand(InverterDevInform_All); // firmware version; might not work, esp. for 1/2 ch hardware + if (getFwVersion() == 0) { + enqueCommand(InverterDevInform_All); // hard- and firmware version + } else { + record_t<> *rec = getRecordStruct(InverterDevInform_Simple); + if (getChannelFieldValue(CH0, FLD_PART_NUM, rec) == 0) + enqueCommand(InverterDevInform_All); // hard- and firmware version for missing HW part nr, delivered by frame 1 + } if (type == INV_TYPE_4CH) { enqueCommand(0x36); } else { diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index a16cbe21..c96e9896 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -243,7 +243,8 @@ const byteAssign_t InfoAssignment[] = { } record_t<> *rec = iv->getRecordStruct(InverterDevInform_Simple); // choose the record structure rec->ts = mPayload[iv->id].ts; - iv->setValue(1, rec, (uint32_t) ((p->packet[24] << 8) + p->packet[25])); + iv->setValue(1, rec, (uint32_t) ((p->packet[24] << 8) + p->packet[25])/1); + notify(InverterDevInform_All, iv); //28737 } else if ( p->packet[9] == 0x01 || p->packet[9] == 0x10 ) {//second frame for MI, 3rd gen. answers in 0x10 DPRINT_IVID(DBG_INFO, iv->id); @@ -277,6 +278,7 @@ const byteAssign_t InfoAssignment[] = { DPRINT(DBG_INFO,F("Matching_APPFW_PN ")); DBGPRINTLN(String((uint32_t) (((p->packet[22] << 8) | p->packet[23]) << 8 | p->packet[24]) << 8 | p->packet[25])); } + notify(InverterDevInform_Simple, iv); } else { DBGPRINTLN(F("3rd gen. inverter!")); // see table in OpenDTU code, DevInfoParser.cpp devInfo[] } From 3105cd43808c824ba6f7481d9d30bf3eb87447e0 Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Fri, 25 Aug 2023 08:45:43 +0200 Subject: [PATCH 4/5] HW info triggers next request immediate request prod. data if HW info was received --- src/hm/hmInverter.h | 3 +++ src/hm/hmPayload.h | 3 +++ src/hm/miPayload.h | 7 +++++-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index d00e9e5d..8ce964e9 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -339,6 +339,9 @@ class Inverter { DPRINT(DBG_INFO, "alarm ID incremented to "); DBGPRINTLN(String(alarmMesIndex)); enqueCommand(AlarmData); +// ivSendHighPrio(id); +// if(mHighPrioIv == NULL) // process the request immediately if possible +// mHighPrioIv = iv; } } } diff --git a/src/hm/hmPayload.h b/src/hm/hmPayload.h index 441981cf..3d8692e4 100644 --- a/src/hm/hmPayload.h +++ b/src/hm/hmPayload.h @@ -338,6 +338,9 @@ class HmPayload { yield(); } } + if( (InverterDevInform_All == mPayload[iv->id].txCmd) && (mHighPrioIv == NULL) ) // process next request immediately if possible + mHighPrioIv = iv; + } else { DPRINT(DBG_ERROR, F("plausibility check failed, expected ")); DBGPRINT(String(rec->pyldLen)); diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index c96e9896..ecef1330 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -193,6 +193,8 @@ class MiPayload { record_t<> *rec = iv->getRecordStruct(InverterDevInform_All); // choose the record structure rec->ts = mPayload[iv->id].ts; mPayload[iv->id].gotFragment = true; + if(mHighPrioIv == NULL) // process next request immediately if possible + mHighPrioIv = iv; /* Polling the device software and hardware version number command @@ -244,7 +246,7 @@ const byteAssign_t InfoAssignment[] = { record_t<> *rec = iv->getRecordStruct(InverterDevInform_Simple); // choose the record structure rec->ts = mPayload[iv->id].ts; iv->setValue(1, rec, (uint32_t) ((p->packet[24] << 8) + p->packet[25])/1); - notify(InverterDevInform_All, iv); + //notify(InverterDevInform_All, iv); //28737 } else if ( p->packet[9] == 0x01 || p->packet[9] == 0x10 ) {//second frame for MI, 3rd gen. answers in 0x10 DPRINT_IVID(DBG_INFO, iv->id); @@ -278,7 +280,8 @@ const byteAssign_t InfoAssignment[] = { DPRINT(DBG_INFO,F("Matching_APPFW_PN ")); DBGPRINTLN(String((uint32_t) (((p->packet[22] << 8) | p->packet[23]) << 8 | p->packet[24]) << 8 | p->packet[25])); } - notify(InverterDevInform_Simple, iv); + //notify(InverterDevInform_Simple, iv); + notify(InverterDevInform_All, iv); } else { DBGPRINTLN(F("3rd gen. inverter!")); // see table in OpenDTU code, DevInfoParser.cpp devInfo[] } From c0bb7403f365d58a28230f3d6423138e7ce67590 Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Wed, 30 Aug 2023 14:48:40 +0200 Subject: [PATCH 5/5] MI - add model codes thx to beegee3 in https://github.com/lumapu/ahoy/issues/1111#issuecomment-1698100571 Only MI-600 (0x001311) is tested! --- src/hm/hmDefines.h | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h index edf1fc99..cef64fc1 100644 --- a/src/hm/hmDefines.h +++ b/src/hm/hmDefines.h @@ -260,9 +260,20 @@ typedef struct { } devInfo_t; const devInfo_t devInfo[] = { - // MI 2nd gen - { 0x13118f, 600 }, - + // MI 2nd gen; only 0x001311 is tested, + // others (starting with MI-250) according to https://github.com/lumapu/ahoy/issues/1111#issuecomment-1698100571 + { 0x000111, 250 }, + { 0x000311, 300 }, + { 0x000411, 350 }, + { 0x001111, 500 }, + { 0x001311, 600 }, + { 0x001321, 600 }, + { 0x001421, 700 }, + { 0x001411, 700 }, + { 0x002111, 1000 }, + { 0x002311, 1200 }, + { 0x002511, 1500 }, + { 0x002411, 1500 }, // MI 3rd gen { 0x100230, 1500 },