Skip to content

Commit

Permalink
improved send algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
SW-Niko authored and schlimmchen committed Oct 24, 2024
1 parent f58fccf commit ef009c6
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 45 deletions.
114 changes: 76 additions & 38 deletions lib/VeDirectFrameHandler/VeDirectMpptController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,46 +109,17 @@ void VeDirectMpptController::frameValidEvent() {

void VeDirectMpptController::loop()
{
// Copy from the "VE.Direct Protocol" documentation
// For firmware version v1.52 and below, when no VE.Direct queries are sent to the device, the
// charger periodically sends human readable (TEXT) data to the serial port. For firmware
// versions v1.53 and above, the charger always periodically sends TEXT data to the serial port.
// --> We just use hex commands for firmware >= 1.53 to keep text messages alive
// Note: First we send queries (timing improvement)
if (_canSend && (_tmpFrame.getFwVersionAsInteger() >= 153)) {

// It seems some commands get lost if we send to fast the next command.
// maybe we produce an overflow on the MPPT receive buffer or we have to wait for the MPPT answer
// before we can send the next command.
// We only send a new query in VE.Direct idle state and if no query is pending
// In case we do not get an answer we send the next query from the queue after a timeout of 500ms
// Note: _sendTimeout will be set to 0 after receiving an answer, see function hexDataHandler()
auto millisTime = millis();
if (isStateIdle() && ((millisTime - _sendTimeStamp) > _sendTimeout)) {

for (auto idx = 0; idx < _hexQueue.size(); ++idx) {

// we check if it is time to update a value
if ((millisTime - _hexQueue[idx]._lastSendTime) > (_hexQueue[idx]._readPeriod * 1000)) {
sendHexCommand(VeDirectHexCommand::GET, _hexQueue[idx]._hexRegister);
_hexQueue[idx]._lastSendTime = millisTime;
_sendTimeStamp = millisTime;

// we need this information to check if we get an answer, see hexDataHandler()
_sendTimeout = 500;
_sendQueueNr = idx;
break;
}
}

}
// First we send HEX-Commands (timing improvement)
if (isHexCommandPossible()) {
sendNextHexCommandFromQueue();
}

// Second we read the messages
// Second we read Text- and HEX-Messages
VeDirectFrameHandler::loop();

// Third we check if hex data is outdated
// Note: Room for improvement, longer data valid time for slow changing values
// Third we check if HEX-Data is outdated
// Note: Room for improvement, longer data valid time for slow changing values?
if (!isHexCommandPossible()) { return; }
auto resetTimestamp = [this](auto& pair) {
if (pair.first > 0 && (millis() - pair.first) > (10 * 1000)) {
pair.first = 0;
Expand Down Expand Up @@ -180,9 +151,10 @@ bool VeDirectMpptController::hexDataHandler(VeDirectHexData const &data) {

auto regLog = static_cast<uint16_t>(data.addr);

// we check if we get we right answer to our query
if ((data.rsp == VeDirectHexResponse::GET) && (data.addr == _hexQueue[_sendQueueNr]._hexRegister))
// we check whether the answer matches a previously asked query
if ((data.rsp == VeDirectHexResponse::GET) && (data.addr == _hexQueue[_sendQueueNr]._hexRegister)) {
_sendTimeout = 0;
}

switch (data.addr) {
case VeDirectHexRegister::ChargeControllerTemperature:
Expand Down Expand Up @@ -302,3 +274,69 @@ bool VeDirectMpptController::hexDataHandler(VeDirectHexData const &data) {

return false;
}


/*
* isHexCommandPossible()
* return: true = yes we can use Hex-Commands
*/
bool VeDirectMpptController::isHexCommandPossible(void) {

// Copy from the "VE.Direct Protocol" documentation
// For firmware version v1.52 and below, when no VE.Direct queries are sent to the device, the
// charger periodically sends human readable (TEXT) data to the serial port. For firmware
// versions v1.53 and above, the charger always periodically sends TEXT data to the serial port.
// --> We just use hex commands for firmware >= 1.53 to keep text messages alive
// Note: First we send queries (timing improvement)
//return (_canSend && (_tmpFrame.getFwVersionAsInteger() >= 153));
return true;
}


/*
* sendNextHexCommandFromQueue()
* send one Hex Commands from the Hex Command Queue
* handel's the received hex data from the MPPT
*/
void VeDirectMpptController::sendNextHexCommandFromQueue(void) {

// It seems some commands get lost if we send to fast the next command.
// maybe we produce an overflow on the MPPT receive buffer or we have to wait for the MPPT answer
// before we can send the next command.
// We only send a new query in VE.Direct idle state and if no query is pending
// In case we do not get an answer we send the next query from the queue after a timeout of 500ms
// Note: _sendTimeout will be set to 0 after receiving an answer, see function hexDataHandler()
auto millisTime = millis();
if (isStateIdle() && ((millisTime - _hexQueue[_sendQueueNr]._lastSendTime) > _sendTimeout)) {

// we do 2 loops, first for high prio commands and second for low prio commands
bool prio = true;
for (auto idy = 0; idy < 2; ++idy) {

// we start searching the queue with the next queue index
auto idx = _sendQueueNr + 1;
if (idx >= _hexQueue.size()) { idx = 0; }

do {
// we check if it is time to send the command again
if (((prio && (_hexQueue[idx]._readPeriod == HIGH_PRIO_COMMAND)) ||
(!prio && (_hexQueue[idx]._readPeriod != HIGH_PRIO_COMMAND))) &&
(millisTime - _hexQueue[idx]._lastSendTime) > (_hexQueue[idx]._readPeriod * 1000)) {

sendHexCommand(VeDirectHexCommand::GET, _hexQueue[idx]._hexRegister);
_hexQueue[idx]._lastSendTime = millisTime;

// we need this information to check if we get an answer, see hexDataHandler()
_sendTimeout = 500;
_sendQueueNr = idx;
return;
}

++idx;
if (idx == _hexQueue.size()) { idx = 0; }
} while (idx != _sendQueueNr);

prio = false; // second loop for low prio commands
}
}
}
14 changes: 8 additions & 6 deletions lib/VeDirectFrameHandler/VeDirectMpptController.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ class MovingAverage {

struct VeDirectHexQueue {
VeDirectHexRegister _hexRegister; // hex register
int8_t _readPeriod; // time period in sec until we send the command again
int32_t _lastSendTime; // time stamp in milli sec of last send
uint8_t _readPeriod; // time period in sec until we send the command again
uint32_t _lastSendTime; // time stamp in milli sec of last send
};

class VeDirectMpptController : public VeDirectFrameHandler<veMpptStruct> {
Expand All @@ -57,14 +57,16 @@ class VeDirectMpptController : public VeDirectFrameHandler<veMpptStruct> {
bool hexDataHandler(VeDirectHexData const &data) final;
bool processTextDataDerived(std::string const& name, std::string const& value) final;
void frameValidEvent() final;
void sendNextHexCommandFromQueue(void);
bool isHexCommandPossible(void);
MovingAverage<float, 5> _efficiency;

int32_t _sendTimeStamp = 0; // timestamp of last command
int32_t _sendTimeout = 0; // timeout until we send the next command from the queue
int8_t _sendQueueNr = 0; // actual queue position;
uint32_t _sendTimeout = 0; // timeout until we send the next command from the queue
size_t _sendQueueNr = 0; // actual queue position;

// for slow changing values we use a send time period of 4 sec
std::array<VeDirectHexQueue, 5> _hexQueue { VeDirectHexRegister::NetworkTotalDcInputPower, 1, 0,
#define HIGH_PRIO_COMMAND 1
std::array<VeDirectHexQueue, 5> _hexQueue { VeDirectHexRegister::NetworkTotalDcInputPower, HIGH_PRIO_COMMAND, 0,
VeDirectHexRegister::ChargeControllerTemperature, 4, 0,
VeDirectHexRegister::SmartBatterySenseTemperature, 4, 0,
VeDirectHexRegister::BatteryFloatVoltage, 4, 0,
Expand Down
3 changes: 2 additions & 1 deletion src/VictronMppt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,9 @@ float VictronMpptClass::getOutputVoltage() const
int16_t VictronMpptClass::getStateOfOperation() const
{
for (const auto& upController : _controllers) {
if (upController->isDataValid())
if (upController->isDataValid()) {
return static_cast<int16_t>(upController->getData().currentState_CS);
}
}

return -1;
Expand Down

0 comments on commit ef009c6

Please sign in to comment.