From 5df13c3f4967e251b14e23391d32644a179323ed Mon Sep 17 00:00:00 2001 From: Eugen Date: Fri, 20 Sep 2024 23:41:31 +0200 Subject: [PATCH] Fusion V2 RS485 SDM power meter support (RxEn, TxEn) --- include/PinMapping.h | 2 ++ lib/SdmEnergyMeter/SDM.cpp | 54 ++++++++++++++++++++++++++++++++++--- lib/SdmEnergyMeter/SDM.h | 7 +++++ src/PinMapping.cpp | 12 +++++++++ src/PowerMeterSerialSdm.cpp | 13 ++++++--- src/WebApi_device.cpp | 7 +++++ 6 files changed, 88 insertions(+), 7 deletions(-) diff --git a/include/PinMapping.h b/include/PinMapping.h index 75b27294e..8b35ac718 100644 --- a/include/PinMapping.h +++ b/include/PinMapping.h @@ -60,6 +60,8 @@ struct PinMapping_t { int8_t powermeter_rx; int8_t powermeter_tx; int8_t powermeter_dere; + int8_t powermeter_rxen; + int8_t powermeter_txen; }; class PinMappingClass { diff --git a/lib/SdmEnergyMeter/SDM.cpp b/lib/SdmEnergyMeter/SDM.cpp index 4e12d3c6e..4b75d9c6a 100644 --- a/lib/SdmEnergyMeter/SDM.cpp +++ b/lib/SdmEnergyMeter/SDM.cpp @@ -14,6 +14,14 @@ SDM::SDM(HardwareSerial& serial, long baud, int dere_pin, int config, bool swapu this->_config = config; this->_swapuart = swapuart; } +SDM::SDM(HardwareSerial &serial, long baud, int dere_pin, int re_pin, int config, bool swapuart) : sdmSer(serial) +{ + this->_baud = baud; + this->_dere_pin = dere_pin; + this->_re_pin = re_pin; + this->_config = config; + this->_swapuart = swapuart; +} #elif defined ( ESP32 ) SDM::SDM(HardwareSerial& serial, long baud, int dere_pin, int config, int8_t rx_pin, int8_t tx_pin) : sdmSer(serial) { this->_baud = baud; @@ -22,12 +30,28 @@ SDM::SDM(HardwareSerial& serial, long baud, int dere_pin, int config, int8_t rx_ this->_rx_pin = rx_pin; this->_tx_pin = tx_pin; } +SDM::SDM(HardwareSerial &serial, long baud, int dere_pin, int re_pin, int config, int8_t rx_pin, int8_t tx_pin) : sdmSer(serial) +{ + this->_baud = baud; + this->_dere_pin = dere_pin; + this->_re_pin = re_pin; + this->_config = config; + this->_rx_pin = rx_pin; + this->_tx_pin = tx_pin; +} #else SDM::SDM(HardwareSerial& serial, long baud, int dere_pin, int config) : sdmSer(serial) { this->_baud = baud; this->_dere_pin = dere_pin; this->_config = config; } +SDM::SDM(HardwareSerial &serial, long baud, int dere_pin, int re_pin, int config) : sdmSer(serial) +{ + this->_baud = baud; + this->_dere_pin = dere_pin; + this->_re_pin = re_pin; + this->_config = config; +} #endif #else #if defined ( ESP8266 ) || defined ( ESP32 ) @@ -38,11 +62,26 @@ SDM::SDM(SoftwareSerial& serial, long baud, int dere_pin, int config, int8_t rx_ this->_rx_pin = rx_pin; this->_tx_pin = tx_pin; } +SDM::SDM(SoftwareSerial &serial, long baud, int dere_pin, int re_pin, int config, int8_t rx_pin, int8_t tx_pin) : sdmSer(serial) +{ + this->_baud = baud; + this->_dere_pin = dere_pin; + this->_re_pin = re_pin; + this->_config = config; + this->_rx_pin = rx_pin; + this->_tx_pin = tx_pin; +} #else SDM::SDM(SoftwareSerial& serial, long baud, int dere_pin) : sdmSer(serial) { this->_baud = baud; this->_dere_pin = dere_pin; } +SDM::SDM(SoftwareSerial &serial, long baud, int dere_pin, int re_pin) : sdmSer(serial) +{ + this->_baud = baud; + this->_dere_pin = dere_pin; + this->_re_pin = re_pin; +} #endif #endif @@ -70,10 +109,15 @@ void SDM::begin(void) { if (_swapuart) sdmSer.swap(); #endif - if (_dere_pin != NOT_A_PIN) { - pinMode(_dere_pin, OUTPUT); //set output pin mode for DE/RE pin when used (for control MAX485) + if (_dere_pin != NOT_A_PIN) + { + pinMode(_dere_pin, OUTPUT); // set output pin mode for DE/RE pin when used (for control MAX485) + } + if (_re_pin != NOT_A_PIN) + { + pinMode(_re_pin, OUTPUT); // set output pin mode /RE pin when used (for control MAX485) } - dereSet(LOW); //set init state to receive from SDM -> DE Disable, /RE Enable (for control MAX485) + dereSet(LOW); // set init state to receive from SDM -> DE Disable, /RE Enable (for control MAX485) } float SDM::readVal(uint16_t reg, uint8_t node) { @@ -359,7 +403,9 @@ void SDM::flush(unsigned long _flushtime) { void SDM::dereSet(bool _state) { if (_dere_pin != NOT_A_PIN) - digitalWrite(_dere_pin, _state); //receive from SDM -> DE Disable, /RE Enable (for control MAX485) + digitalWrite(_dere_pin, _state); // receive from SDM -> DE Disable, /RE Enable (for control MAX485) + if (_re_pin != NOT_A_PIN) + digitalWrite(_re_pin, _state); // receive from SDM -> /RE Enable (for control MAX485) } bool SDM::validChecksum(const uint8_t* data, size_t messageLength) const { diff --git a/lib/SdmEnergyMeter/SDM.h b/lib/SdmEnergyMeter/SDM.h index dd9c5c1af..9edf9c85f 100644 --- a/lib/SdmEnergyMeter/SDM.h +++ b/lib/SdmEnergyMeter/SDM.h @@ -23,6 +23,7 @@ #if !defined ( DERE_PIN ) #define DERE_PIN NOT_A_PIN // default digital pin for control MAX485 DE/RE lines (connect DE & /RE together to this pin) + #define RE_PIN NOT_A_PIN // default digital pin for control MAX485 RE line (use DERE_PIN for DE line) #endif #if defined ( USE_HARDWARESERIAL ) @@ -324,16 +325,21 @@ class SDM { #if defined ( USE_HARDWARESERIAL ) // hardware serial #if defined ( ESP8266 ) // on esp8266 SDM(HardwareSerial& serial, long baud = SDM_UART_BAUD, int dere_pin = DERE_PIN, int config = SDM_UART_CONFIG, bool swapuart = SWAPHWSERIAL); + SDM(HardwareSerial& serial, long baud = SDM_UART_BAUD, int dere_pin = DERE_PIN, int re_pin = RE_PIN, int config = SDM_UART_CONFIG, bool swapuart = SWAPHWSERIAL); #elif defined ( ESP32 ) // on esp32 SDM(HardwareSerial& serial, long baud = SDM_UART_BAUD, int dere_pin = DERE_PIN, int config = SDM_UART_CONFIG, int8_t rx_pin = SDM_RX_PIN, int8_t tx_pin = SDM_TX_PIN); + SDM(HardwareSerial& serial, long baud = SDM_UART_BAUD, int dere_pin = DERE_PIN, int re_pin = RE_PIN, int config = SDM_UART_CONFIG, int8_t rx_pin = SDM_RX_PIN, int8_t tx_pin = SDM_TX_PIN); #else // on avr SDM(HardwareSerial& serial, long baud = SDM_UART_BAUD, int dere_pin = DERE_PIN, int config = SDM_UART_CONFIG); + SDM(HardwareSerial& serial, long baud = SDM_UART_BAUD, int dere_pin = DERE_PIN, int re_pin = RE_PIN, int config = SDM_UART_CONFIG); #endif #else // software serial #if defined ( ESP8266 ) || defined ( ESP32 ) // on esp8266/esp32 SDM(SoftwareSerial& serial, long baud = SDM_UART_BAUD, int dere_pin = DERE_PIN, int config = SDM_UART_CONFIG, int8_t rx_pin = SDM_RX_PIN, int8_t tx_pin = SDM_TX_PIN); + SDM(SoftwareSerial& serial, long baud = SDM_UART_BAUD, int dere_pin = DERE_PIN, int re_pin = RE_PIN, int config = SDM_UART_CONFIG, int8_t rx_pin = SDM_RX_PIN, int8_t tx_pin = SDM_TX_PIN); #else // on avr SDM(SoftwareSerial& serial, long baud = SDM_UART_BAUD, int dere_pin = DERE_PIN); + SDM(SoftwareSerial& serial, long baud = SDM_UART_BAUD, int dere_pin = DERE_PIN, int re_pin = RE_PIN); #endif #endif virtual ~SDM(); @@ -390,6 +396,7 @@ class SDM { #endif long _baud = SDM_UART_BAUD; int _dere_pin = DERE_PIN; + int _re_pin = RE_PIN; uint16_t readingerrcode = SDM_ERR_NO_ERROR; // 4 = timeout; 3 = not enough bytes; 2 = number of bytes OK but bytes b0,b1 or b2 wrong, 1 = crc error uint16_t msturnaround = WAITING_TURNAROUND_DELAY; uint16_t mstimeout = RESPONSE_TIMEOUT; diff --git a/src/PinMapping.cpp b/src/PinMapping.cpp index 0c4a09843..1ab17b17d 100644 --- a/src/PinMapping.cpp +++ b/src/PinMapping.cpp @@ -170,6 +170,14 @@ #define POWERMETER_PIN_DERE -1 #endif +#ifndef POWERMETER_PIN_TXEN +#define POWERMETER_PIN_TXEN -1 +#endif + +#ifndef POWERMETER_PIN_RXEN +#define POWERMETER_PIN_RXEN -1 +#endif + PinMappingClass PinMapping; PinMappingClass::PinMappingClass() @@ -236,6 +244,8 @@ PinMappingClass::PinMappingClass() _pinMapping.powermeter_rx = POWERMETER_PIN_RX; _pinMapping.powermeter_tx = POWERMETER_PIN_TX; _pinMapping.powermeter_dere = POWERMETER_PIN_DERE; + _pinMapping.powermeter_rxen = POWERMETER_PIN_RXEN; + _pinMapping.powermeter_txen = POWERMETER_PIN_TXEN; } PinMapping_t& PinMappingClass::get() @@ -321,6 +331,8 @@ bool PinMappingClass::init(const String& deviceMapping) _pinMapping.powermeter_rx = doc[i]["powermeter"]["rx"] | POWERMETER_PIN_RX; _pinMapping.powermeter_tx = doc[i]["powermeter"]["tx"] | POWERMETER_PIN_TX; _pinMapping.powermeter_dere = doc[i]["powermeter"]["dere"] | POWERMETER_PIN_DERE; + _pinMapping.powermeter_rxen = doc[i]["powermeter"]["rxen"] | POWERMETER_PIN_RXEN; + _pinMapping.powermeter_txen = doc[i]["powermeter"]["txen"] | POWERMETER_PIN_TXEN; return true; } diff --git a/src/PowerMeterSerialSdm.cpp b/src/PowerMeterSerialSdm.cpp index 40514427a..364b3dd50 100644 --- a/src/PowerMeterSerialSdm.cpp +++ b/src/PowerMeterSerialSdm.cpp @@ -29,8 +29,8 @@ bool PowerMeterSerialSdm::init() { const PinMapping_t& pin = PinMapping.get(); - MessageOutput.printf("[PowerMeterSerialSdm] rx = %d, tx = %d, dere = %d\r\n", - pin.powermeter_rx, pin.powermeter_tx, pin.powermeter_dere); + MessageOutput.printf("[PowerMeterSerialSdm] rx = %d, tx = %d, dere = %d, rxen = %d, txen = %d \r\n", + pin.powermeter_rx, pin.powermeter_tx, pin.powermeter_dere, pin.powermeter_rxen, pin.powermeter_txen); if (pin.powermeter_rx < 0 || pin.powermeter_tx < 0) { MessageOutput.println("[PowerMeterSerialSdm] invalid pin config for SDM " @@ -39,8 +39,15 @@ bool PowerMeterSerialSdm::init() } _upSdmSerial = std::make_unique(); - _upSdm = std::make_unique(*_upSdmSerial, 9600, pin.powermeter_dere, + + if(pin.powermeter_rxen > -1 && pin.powermeter_txen > -1){ + _upSdm = std::make_unique(*_upSdmSerial, 9600, pin.powermeter_rxen, pin.powermeter_txen, + SWSERIAL_8N1, pin.powermeter_rx, pin.powermeter_tx); + }else{ + _upSdm = std::make_unique(*_upSdmSerial, 9600, pin.powermeter_dere, SWSERIAL_8N1, pin.powermeter_rx, pin.powermeter_tx); + } + _upSdm->begin(); return true; diff --git a/src/WebApi_device.cpp b/src/WebApi_device.cpp index 9bed5e53e..45bfc8fb1 100644 --- a/src/WebApi_device.cpp +++ b/src/WebApi_device.cpp @@ -108,6 +108,13 @@ void WebApiDeviceClass::onDeviceAdminGet(AsyncWebServerRequest* request) huaweiPinObj["cs"] = pin.huawei_cs; huaweiPinObj["power"] = pin.huawei_power; + auto powermeterPinObj = curPin["powermeter"].to(); + powermeterPinObj["rx"] = pin.powermeter_rx; + powermeterPinObj["tx"] = pin.powermeter_tx; + powermeterPinObj["dere"] = pin.powermeter_dere; + powermeterPinObj["rxen"] = pin.powermeter_rxen; + powermeterPinObj["txen"] = pin.powermeter_txen; + WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__); }