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.
This commit is contained in:
Bernhard Kirchen 2024-06-09 20:01:29 +02:00
parent 8202bb23cd
commit 6c06e71fd0
4 changed files with 16 additions and 12 deletions

View File

@ -4,6 +4,7 @@
#include <atomic> #include <atomic>
#include <mutex> #include <mutex>
#include <condition_variable> #include <condition_variable>
#include <SoftwareSerial.h>
#include "Configuration.h" #include "Configuration.h"
#include "PowerMeterProvider.h" #include "PowerMeterProvider.h"
#include "SDM.h" #include "SDM.h"
@ -49,8 +50,7 @@ private:
mutable std::mutex _valueMutex; mutable std::mutex _valueMutex;
static char constexpr _sdmSerialPortOwner[] = "SDM power meter"; std::unique_ptr<SoftwareSerial> _upSdmSerial = nullptr;
std::unique_ptr<HardwareSerial> _upSdmSerial = nullptr;
std::unique_ptr<SDM> _upSdm = nullptr; std::unique_ptr<SDM> _upSdm = nullptr;
TaskHandle_t _taskHandle = nullptr; TaskHandle_t _taskHandle = nullptr;

View File

@ -393,8 +393,18 @@ void SDM::modbusWrite(uint8_t* data, size_t messageLength) {
resptime = millis() + waitForBytesSent_ms; 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 sdmSer.write(data, messageLength); //send 8 bytes
#if !defined ( USE_HARDWARESERIAL )
xTaskResumeAll();
#endif
if (_dere_pin != NOT_A_PIN) { if (_dere_pin != NOT_A_PIN) {
const int32_t timeleft = (int32_t) (resptime - millis()); const int32_t timeleft = (int32_t) (resptime - millis());
if (timeleft > 0) { if (timeleft > 0) {

View File

@ -14,7 +14,7 @@
* define or undefine USE_HARDWARESERIAL (uncomment only one or none) * define or undefine USE_HARDWARESERIAL (uncomment only one or none)
*/ */
//#undef USE_HARDWARESERIAL //#undef USE_HARDWARESERIAL
#define USE_HARDWARESERIAL //#define USE_HARDWARESERIAL
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -23,8 +23,6 @@ PowerMeterSerialSdm::~PowerMeterSerialSdm()
_upSdmSerial->end(); _upSdmSerial->end();
_upSdmSerial = nullptr; _upSdmSerial = nullptr;
} }
SerialPortManager.freePort(_sdmSerialPortOwner);
} }
bool PowerMeterSerialSdm::init() bool PowerMeterSerialSdm::init()
@ -40,13 +38,9 @@ bool PowerMeterSerialSdm::init()
return false; return false;
} }
auto oHwSerialPort = SerialPortManager.allocatePort(_sdmSerialPortOwner); _upSdmSerial = std::make_unique<SoftwareSerial>();
if (!oHwSerialPort) { return false; }
_upSdmSerial = std::make_unique<HardwareSerial>(*oHwSerialPort);
_upSdmSerial->end(); // make sure the UART will be re-initialized
_upSdm = std::make_unique<SDM>(*_upSdmSerial, 9600, pin.powermeter_dere, _upSdm = std::make_unique<SDM>(*_upSdmSerial, 9600, pin.powermeter_dere,
SERIAL_8N1, pin.powermeter_rx, pin.powermeter_tx); SWSERIAL_8N1, pin.powermeter_rx, pin.powermeter_tx);
_upSdm->begin(); _upSdm->begin();
std::unique_lock<std::mutex> lock(_pollingMutex); std::unique_lock<std::mutex> lock(_pollingMutex);