diff --git a/README.md b/README.md index 005fd28f..6d105faa 100644 --- a/README.md +++ b/README.md @@ -24,38 +24,41 @@ Like to show your own build? Just send me a Pull Request. ## Currently supported Inverters -| Model | Required RF Module | DC Inputs | MPP-Tracker | AC Phases | -| --------------------| ------------------ | --------- | ----------- | --------- | -| Hoymiles HM-300 | NRF24L01+ | 1 | 1 | 1 | -| Hoymiles HM-350 | NRF24L01+ | 1 | 1 | 1 | -| Hoymiles HM-400 | NRF24L01+ | 1 | 1 | 1 | -| Hoymiles HM-600 | NRF24L01+ | 2 | 2 | 1 | -| Hoymiles HM-700 | NRF24L01+ | 2 | 2 | 1 | -| Hoymiles HM-800 | NRF24L01+ | 2 | 2 | 1 | -| Hoymiles HM-1000 | NRF24L01+ | 4 | 2 | 1 | -| Hoymiles HM-1200 | NRF24L01+ | 4 | 2 | 1 | -| Hoymiles HM-1500 | NRF24L01+ | 4 | 2 | 1 | -| Hoymiles HMS-300 | CMT2300A | 1 | 1 | 1 | -| Hoymiles HMS-350 | CMT2300A | 1 | 1 | 1 | -| Hoymiles HMS-400 | CMT2300A | 1 | 1 | 1 | -| Hoymiles HMS-450 | CMT2300A | 1 | 1 | 1 | -| Hoymiles HMS-500 | CMT2300A | 1 | 1 | 1 | -| Hoymiles HMS-600 | CMT2300A | 2 | 2 | 1 | -| Hoymiles HMS-700 | CMT2300A | 2 | 2 | 1 | -| Hoymiles HMS-800 | CMT2300A | 2 | 2 | 1 | -| Hoymiles HMS-900 | CMT2300A | 2 | 2 | 1 | -| Hoymiles HMS-1000 | CMT2300A | 2 | 2 | 1 | -| Hoymiles HMS-1600 | CMT2300A | 4 | 4 | 1 | -| Hoymiles HMS-1800 | CMT2300A | 4 | 4 | 1 | -| Hoymiles HMS-2000 | CMT2300A | 4 | 4 | 1 | -| Hoymiles HMT-1800 | CMT2300A | 6 | 3 | 3 | -| Hoymiles HMT-2250 | CMT2300A | 6 | 3 | 3 | -| Solenso SOL-H350 | NRF24L01+ | 1 | 1 | 1 | -| Solenso SOL-H400 | NRF24L01+ | 1 | 1 | 1 | -| Solenso SOL-H800 | NRF24L01+ | 2 | 2 | 1 | -| TSUN TSOL-M350 | NRF24L01+ | 1 | 1 | 1 | -| TSUN TSOL-M800 | NRF24L01+ | 2 | 2 | 1 | -| TSUN TSOL-M1600 | NRF24L01+ | 4 | 2 | 1 | +| Model | Required RF Module | DC Inputs | MPP-Tracker | AC Phases | +| ---------------------| ------------------ | --------- | ----------- | --------- | +| Hoymiles HM-300-1T | NRF24L01+ | 1 | 1 | 1 | +| Hoymiles HM-350-1T | NRF24L01+ | 1 | 1 | 1 | +| Hoymiles HM-400-1T | NRF24L01+ | 1 | 1 | 1 | +| Hoymiles HM-600-2T | NRF24L01+ | 2 | 2 | 1 | +| Hoymiles HM-700-2T | NRF24L01+ | 2 | 2 | 1 | +| Hoymiles HM-800-2T | NRF24L01+ | 2 | 2 | 1 | +| Hoymiles HM-1000-4T | NRF24L01+ | 4 | 2 | 1 | +| Hoymiles HM-1200-4T | NRF24L01+ | 4 | 2 | 1 | +| Hoymiles HM-1500-4T | NRF24L01+ | 4 | 2 | 1 | +| Hoymiles HMS-300-1T | CMT2300A | 1 | 1 | 1 | +| Hoymiles HMS-350-1T | CMT2300A | 1 | 1 | 1 | +| Hoymiles HMS-400-1T | CMT2300A | 1 | 1 | 1 | +| Hoymiles HMS-450-1T | CMT2300A | 1 | 1 | 1 | +| Hoymiles HMS-500-1T | CMT2300A | 1 | 1 | 1 | +| Hoymiles HMS-600-2T | CMT2300A | 2 | 2 | 1 | +| Hoymiles HMS-700-2T | CMT2300A | 2 | 2 | 1 | +| Hoymiles HMS-800-2T | CMT2300A | 2 | 2 | 1 | +| Hoymiles HMS-900-2T | CMT2300A | 2 | 2 | 1 | +| Hoymiles HMS-1000-2T | CMT2300A | 2 | 2 | 1 | +| Hoymiles HMS-1600-4T | CMT2300A | 4 | 4 | 1 | +| Hoymiles HMS-1800-4T | CMT2300A | 4 | 4 | 1 | +| Hoymiles HMS-2000-4T | CMT2300A | 4 | 4 | 1 | +| Hoymiles HMT-1600-4T | CMT2300A | 4 | 4 | 3 | +| Hoymiles HMT-1800-4T | CMT2300A | 4 | 4 | 3 | +| Hoymiles HMT-2000-4T | CMT2300A | 4 | 4 | 3 | +| Hoymiles HMT-1800-6T | CMT2300A | 6 | 3 | 3 | +| Hoymiles HMT-2250-6T | CMT2300A | 6 | 3 | 3 | +| Solenso SOL-H350 | NRF24L01+ | 1 | 1 | 1 | +| Solenso SOL-H400 | NRF24L01+ | 1 | 1 | 1 | +| Solenso SOL-H800 | NRF24L01+ | 2 | 2 | 1 | +| TSUN TSOL-M350 | NRF24L01+ | 1 | 1 | 1 | +| TSUN TSOL-M800 | NRF24L01+ | 2 | 2 | 1 | +| TSUN TSOL-M1600 | NRF24L01+ | 4 | 2 | 1 | **TSUN compatibility remark:** Compatibility with OpenDTU is most likly related to the serial number of the inverter. Current findings indicate that TSUN inverters with a serial number starting with "11" are supported, whereby inverters with a serial number starting with "10" are not. diff --git a/lib/Hoymiles/src/Hoymiles.cpp b/lib/Hoymiles/src/Hoymiles.cpp index 6d9a0806..595a096d 100644 --- a/lib/Hoymiles/src/Hoymiles.cpp +++ b/lib/Hoymiles/src/Hoymiles.cpp @@ -8,6 +8,7 @@ #include "inverters/HMS_1CHv2.h" #include "inverters/HMS_2CH.h" #include "inverters/HMS_4CH.h" +#include "inverters/HMT_4CH.h" #include "inverters/HMT_6CH.h" #include "inverters/HM_1CH.h" #include "inverters/HM_2CH.h" @@ -140,7 +141,9 @@ void HoymilesClass::loop() std::shared_ptr HoymilesClass::addInverter(const char* name, uint64_t serial) { std::shared_ptr i = nullptr; - if (HMT_6CH::isValidSerial(serial)) { + if (HMT_4CH::isValidSerial(serial)) { + i = std::make_shared(_radioCmt.get(), serial); + } else if (HMT_6CH::isValidSerial(serial)) { i = std::make_shared(_radioCmt.get(), serial); } else if (HMS_4CH::isValidSerial(serial)) { i = std::make_shared(_radioCmt.get(), serial); diff --git a/lib/Hoymiles/src/inverters/HMT_4CH.cpp b/lib/Hoymiles/src/inverters/HMT_4CH.cpp new file mode 100644 index 00000000..d30a404b --- /dev/null +++ b/lib/Hoymiles/src/inverters/HMT_4CH.cpp @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2023 Thomas Basler and others + */ +#include "HMT_4CH.h" + +static const byteAssign_t byteAssignment[] = { + { TYPE_DC, CH0, FLD_UDC, UNIT_V, 2, 2, 10, false, 1 }, + { TYPE_DC, CH0, FLD_IDC, UNIT_A, 4, 2, 100, false, 2 }, + { TYPE_DC, CH0, FLD_PDC, UNIT_W, 8, 2, 10, false, 1 }, + { TYPE_DC, CH0, FLD_YT, UNIT_KWH, 12, 4, 1000, false, 3 }, + { TYPE_DC, CH0, FLD_YD, UNIT_WH, 20, 2, 1, false, 0 }, + { TYPE_DC, CH0, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH0, CMD_CALC, false, 3 }, + + { TYPE_DC, CH1, FLD_UDC, UNIT_V, 2, 2, 10, false, 1 }, + { TYPE_DC, CH1, FLD_IDC, UNIT_A, 6, 2, 100, false, 2 }, + { TYPE_DC, CH1, FLD_PDC, UNIT_W, 10, 2, 10, false, 1 }, + { TYPE_DC, CH1, FLD_YT, UNIT_KWH, 16, 4, 1000, false, 3 }, + { TYPE_DC, CH1, FLD_YD, UNIT_WH, 22, 2, 1, false, 0 }, + { TYPE_DC, CH1, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH1, CMD_CALC, false, 3 }, + + { TYPE_DC, CH2, FLD_UDC, UNIT_V, 24, 2, 10, false, 1 }, + { TYPE_DC, CH2, FLD_IDC, UNIT_A, 26, 2, 100, false, 2 }, + { TYPE_DC, CH2, FLD_PDC, UNIT_W, 30, 2, 10, false, 1 }, + { TYPE_DC, CH2, FLD_YT, UNIT_KWH, 34, 4, 1000, false, 3 }, + { TYPE_DC, CH2, FLD_YD, UNIT_WH, 42, 2, 1, false, 0 }, + { TYPE_DC, CH2, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH2, CMD_CALC, false, 3 }, + + { TYPE_DC, CH3, FLD_UDC, UNIT_V, 24, 2, 10, false, 1 }, + { TYPE_DC, CH3, FLD_IDC, UNIT_A, 28, 2, 100, false, 2 }, + { TYPE_DC, CH3, FLD_PDC, UNIT_W, 32, 2, 10, false, 1 }, + { TYPE_DC, CH3, FLD_YT, UNIT_KWH, 38, 4, 1000, false, 3 }, + { TYPE_DC, CH3, FLD_YD, UNIT_WH, 44, 2, 1, false, 0 }, + { TYPE_DC, CH3, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH3, CMD_CALC, false, 3 }, + + { TYPE_AC, CH0, FLD_UAC, UNIT_V, 74, 2, 10, false, 1 }, // dummy + { TYPE_AC, CH0, FLD_UAC_1N, UNIT_V, 68, 2, 10, false, 1 }, + { TYPE_AC, CH0, FLD_UAC_2N, UNIT_V, 70, 2, 10, false, 1 }, + { TYPE_AC, CH0, FLD_UAC_3N, UNIT_V, 72, 2, 10, false, 1 }, + { TYPE_AC, CH0, FLD_UAC_12, UNIT_V, 74, 2, 10, false, 1 }, + { TYPE_AC, CH0, FLD_UAC_23, UNIT_V, 76, 2, 10, false, 1 }, + { TYPE_AC, CH0, FLD_UAC_31, UNIT_V, 78, 2, 10, false, 1 }, + { TYPE_AC, CH0, FLD_F, UNIT_HZ, 80, 2, 100, false, 2 }, + { TYPE_AC, CH0, FLD_PAC, UNIT_W, 82, 2, 10, false, 1 }, + { TYPE_AC, CH0, FLD_Q, UNIT_VAR, 84, 2, 10, true, 1 }, + { TYPE_AC, CH0, FLD_IAC, UNIT_A, 86, 2, 100, false, 2 }, // dummy + { TYPE_AC, CH0, FLD_IAC_1, UNIT_A, 86, 2, 100, false, 2 }, + { TYPE_AC, CH0, FLD_IAC_2, UNIT_A, 88, 2, 100, false, 2 }, + { TYPE_AC, CH0, FLD_IAC_3, UNIT_A, 90, 2, 100, false, 2 }, + { TYPE_AC, CH0, FLD_PF, UNIT_NONE, 92, 2, 1000, false, 3 }, + + { TYPE_INV, CH0, FLD_T, UNIT_C, 94, 2, 10, true, 1 }, + { TYPE_INV, CH0, FLD_EVT_LOG, UNIT_NONE, 96, 2, 1, false, 0 }, + + { TYPE_AC, CH0, FLD_YD, UNIT_WH, CALC_YD_CH0, 0, CMD_CALC, false, 0 }, + { TYPE_AC, CH0, FLD_YT, UNIT_KWH, CALC_YT_CH0, 0, CMD_CALC, false, 3 }, + { TYPE_AC, CH0, FLD_PDC, UNIT_W, CALC_PDC_CH0, 0, CMD_CALC, false, 1 }, + { TYPE_AC, CH0, FLD_EFF, UNIT_PCT, CALC_EFF_CH0, 0, CMD_CALC, false, 3 } +}; + +HMT_4CH::HMT_4CH(HoymilesRadio* radio, uint64_t serial) + : HMT_Abstract(radio, serial) {}; + +bool HMT_4CH::isValidSerial(uint64_t serial) +{ + // serial >= 0x136100000000 && serial <= 0x136199999999 + uint16_t preSerial = (serial >> 32) & 0xffff; + return preSerial == 0x1361; +} + +String HMT_4CH::typeName() +{ + return F("HMT-1600/1800/2000-4T"); +} + +const byteAssign_t* HMT_4CH::getByteAssignment() +{ + return byteAssignment; +} + +uint8_t HMT_4CH::getByteAssignmentSize() +{ + return sizeof(byteAssignment) / sizeof(byteAssignment[0]); +} diff --git a/lib/Hoymiles/src/inverters/HMT_4CH.h b/lib/Hoymiles/src/inverters/HMT_4CH.h new file mode 100644 index 00000000..7358dd45 --- /dev/null +++ b/lib/Hoymiles/src/inverters/HMT_4CH.h @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#pragma once + +#include "HMT_Abstract.h" + +class HMT_4CH : public HMT_Abstract { +public: + explicit HMT_4CH(HoymilesRadio* radio, uint64_t serial); + static bool isValidSerial(uint64_t serial); + String typeName(); + const byteAssign_t* getByteAssignment(); + uint8_t getByteAssignmentSize(); +}; \ No newline at end of file diff --git a/lib/Hoymiles/src/inverters/README.md b/lib/Hoymiles/src/inverters/README.md index 90b2951e..c080a735 100644 --- a/lib/Hoymiles/src/inverters/README.md +++ b/lib/Hoymiles/src/inverters/README.md @@ -8,5 +8,6 @@ | HMS_1CH | HMS-300/350/400/450/500-1T | 1124 | | HMS_1CHv2 | HMS-500-1T v2 | 1125 | | HMS_2CH | HMS-600/700/800/900/1000-2T | 1144 | -| HMS_4CH | HMS-1600/1800/2000 | 1164 | +| HMS_4CH | HMS-1600/1800/2000-4T | 1164 | +| HMT_4CH | HMT-1600/1800/2000-4T | 1361 | | HMT_6CH | HMT-1800/2250-6T | 1382 |