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

View File

@ -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) {

View File

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

View File

@ -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<HardwareSerial>(*oHwSerialPort);
_upSdmSerial->end(); // make sure the UART will be re-initialized
_upSdmSerial = std::make_unique<SoftwareSerial>();
_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();
std::unique_lock<std::mutex> lock(_pollingMutex);