From 6c06e71fd032755066604d98ef20dc98a96fb89d Mon Sep 17 00:00:00 2001 From: Bernhard Kirchen Date: Sun, 9 Jun 2024 20:01:29 +0200 Subject: [PATCH] Feature: SDM power meter: switch to software serial a 9600 baud serial interface does not need a hardware UART. these changes switch the SDM power meter implementation to use a software serial instance instead. this is desirable as hardware UARTs are scarce and users need them for JK BMS and VE.Direct interfaces. --- include/PowerMeterSerialSdm.h | 4 ++-- lib/SdmEnergyMeter/SDM.cpp | 12 +++++++++++- lib/SdmEnergyMeter/SDM_Config_User.h | 2 +- src/PowerMeterSerialSdm.cpp | 10 ++-------- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/include/PowerMeterSerialSdm.h b/include/PowerMeterSerialSdm.h index b6ff987fb..941d2132e 100644 --- a/include/PowerMeterSerialSdm.h +++ b/include/PowerMeterSerialSdm.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "Configuration.h" #include "PowerMeterProvider.h" #include "SDM.h" @@ -49,8 +50,7 @@ class PowerMeterSerialSdm : public PowerMeterProvider { mutable std::mutex _valueMutex; - static char constexpr _sdmSerialPortOwner[] = "SDM power meter"; - std::unique_ptr _upSdmSerial = nullptr; + std::unique_ptr _upSdmSerial = nullptr; std::unique_ptr _upSdm = nullptr; TaskHandle_t _taskHandle = nullptr; diff --git a/lib/SdmEnergyMeter/SDM.cpp b/lib/SdmEnergyMeter/SDM.cpp index 6488e2471..4e12d3c6e 100644 --- a/lib/SdmEnergyMeter/SDM.cpp +++ b/lib/SdmEnergyMeter/SDM.cpp @@ -393,8 +393,18 @@ void SDM::modbusWrite(uint8_t* data, size_t messageLength) { resptime = millis() + waitForBytesSent_ms; } +#if !defined ( USE_HARDWARESERIAL ) + // prevent scheduler from messing up the serial message. this task shall only + // be scheduled after the whole serial message was transmitted. + vTaskSuspendAll(); +#endif + sdmSer.write(data, messageLength); //send 8 bytes - + +#if !defined ( USE_HARDWARESERIAL ) + xTaskResumeAll(); +#endif + if (_dere_pin != NOT_A_PIN) { const int32_t timeleft = (int32_t) (resptime - millis()); if (timeleft > 0) { diff --git a/lib/SdmEnergyMeter/SDM_Config_User.h b/lib/SdmEnergyMeter/SDM_Config_User.h index 7d8e75b86..bd8d4358c 100644 --- a/lib/SdmEnergyMeter/SDM_Config_User.h +++ b/lib/SdmEnergyMeter/SDM_Config_User.h @@ -14,7 +14,7 @@ * define or undefine USE_HARDWARESERIAL (uncomment only one or none) */ //#undef USE_HARDWARESERIAL -#define USE_HARDWARESERIAL +//#define USE_HARDWARESERIAL //------------------------------------------------------------------------------ diff --git a/src/PowerMeterSerialSdm.cpp b/src/PowerMeterSerialSdm.cpp index 75487cd61..fea191b54 100644 --- a/src/PowerMeterSerialSdm.cpp +++ b/src/PowerMeterSerialSdm.cpp @@ -23,8 +23,6 @@ PowerMeterSerialSdm::~PowerMeterSerialSdm() _upSdmSerial->end(); _upSdmSerial = nullptr; } - - SerialPortManager.freePort(_sdmSerialPortOwner); } bool PowerMeterSerialSdm::init() @@ -40,13 +38,9 @@ bool PowerMeterSerialSdm::init() return false; } - auto oHwSerialPort = SerialPortManager.allocatePort(_sdmSerialPortOwner); - if (!oHwSerialPort) { return false; } - - _upSdmSerial = std::make_unique(*oHwSerialPort); - _upSdmSerial->end(); // make sure the UART will be re-initialized + _upSdmSerial = std::make_unique(); _upSdm = std::make_unique(*_upSdmSerial, 9600, pin.powermeter_dere, - SERIAL_8N1, pin.powermeter_rx, pin.powermeter_tx); + SWSERIAL_8N1, pin.powermeter_rx, pin.powermeter_tx); _upSdm->begin(); std::unique_lock lock(_pollingMutex);