diff --git a/lib/RS485/RS485_Driver.cpp b/lib/RS485/RS485_Driver.cpp index a5a712a..36793c9 100644 --- a/lib/RS485/RS485_Driver.cpp +++ b/lib/RS485/RS485_Driver.cpp @@ -3,7 +3,6 @@ #include #include -//#define DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE #include "utils.h" namespace drivers @@ -18,6 +17,7 @@ namespace drivers LOG_INFO("Init serial port 1"); // RS485 is hardwired to serial port 1 m_serial.begin(baud, conf, 18, 17); + m_serial.setTimeout(1000); m_serial.flush(); } @@ -112,7 +112,7 @@ namespace drivers { constexpr uint8_t func = 0x06; LOG_DEBUG("Write single register: dev[", device, "], reg[", reg, "], value[", value, "]"); - return writeInteger(device, func, reg, {value}); + return writeInteger(device, func, reg, {value}, false); } // Func 0x0F @@ -128,7 +128,7 @@ namespace drivers { constexpr uint8_t func = 0x10; LOG_DEBUG("Write multi registers: dev[", device, "], start[", reg, "], num[", values.size(), "]"); - return writeInteger(device, func, reg, values); + return writeInteger(device, func, reg, values, true); } ///////////////////////////////////////////////////////////////// @@ -150,15 +150,15 @@ namespace drivers LOG_ERROR("Failed receive readBinary response, expected[", expectedRespLen, "], received[", response.size(), "]"); return false; } +#ifdef DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE + printBytes("readBinary Response", response); +#endif // element 2 of response has the response data bytes expected const uint8_t actualRespLen(response.at(2)); if (actualRespLen != nRespDataBytes) { LOG_ERROR("Failed receive, data to short: actual[", actualRespLen, "], expected[", nRespDataBytes, "]"); -#ifdef DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE - printBytes("readBinary Response", response); -#endif return false; } @@ -198,11 +198,11 @@ namespace drivers if (!readN(expectedRespLen, response)) { LOG_ERROR("Failed receive readInteger response, expected[", expectedRespLen, "], received[", response.size(), "]"); -#ifdef DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE - printBytes("readInteger Response", response); -#endif return false; } +#ifdef DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE + printBytes("readInteger Response", response); +#endif // element 2 of response has the response data bytes expected const uint8_t actualRespLen(response.at(2)); @@ -270,11 +270,11 @@ namespace drivers if (!readN(expectedRespLen, response)) { LOG_ERROR("Failed receive writeBinary response, expected[", expectedRespLen, "], received[", response.size(), "]"); -#ifdef DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE - printBytes("writeBinary Response", response); -#endif return false; } +#ifdef DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE + printBytes("writeBinary Response", response); +#endif // compute crc of current message if (!verifyCrc(response)) @@ -283,10 +283,10 @@ namespace drivers return true; } - const bool MODBUS::writeInteger(const uint8_t device, const uint8_t func, const uint16_t reg, const std::vector &in) + const bool MODBUS::writeInteger(const uint8_t device, const uint8_t func, const uint16_t reg, const std::vector &in, const bool multi) { const uint16_t num(in.size()); - if (num == 1) + if (!multi) { if (!write(singleRequest(device, func, reg, in[0]))) { @@ -298,14 +298,14 @@ namespace drivers { // build data vector for request, inverting bytes if necessary std::vector requestData; - requestData.resize(in.size() * sizeof(uint16_t)); - auto it=requestData.begin(); - std::for_each(in.begin(), in.end(), [requestData, &it](auto inV) { + requestData.resize(in.size() * sizeof(uint16_t), 0xff); + auto it = requestData.begin(); + for (auto inV : in) + { const uint16_t beV(htobe16(inV)); - *it=highByte(beV); - *(++it)=lowByte(beV); - }); - + *(it++) = lowByte(beV); + *(it++) = highByte(beV); + } if (!write(multiRequest(device, func, reg, num, requestData))) { LOG_ERROR("Failed send writeMultiInteger command"); @@ -318,11 +318,11 @@ namespace drivers if (!readN(expectedRespLen, response)) { LOG_ERROR("Failed receive writeInteger response, expected[", expectedRespLen, "], received[", response.size(), "]"); -#ifdef DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE - printBytes("writeInteger Response", response); -#endif return false; } +#ifdef DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE + printBytes("writeInteger Response", response); +#endif // compute crc of current message if (!verifyCrc(response)) @@ -366,7 +366,7 @@ namespace drivers header.qty = htobe16(qty); header.bytes = data.size(); // 8 bit value - //const uint8_t headerBytes(sizeof(req_multi_t)); // sizeof not working because of memory padding + // const uint8_t headerBytes(sizeof(req_multi_t)); // sizeof not working because of memory padding const uint8_t headerBytes(7); const uint8_t dataBytes(data.size()); const uint8_t crcBytes(sizeof(crc_t)); @@ -380,7 +380,7 @@ namespace drivers std::vector dataOut; dataOut.resize(headerBytes + dataBytes + crcBytes); // header message + data values + crc code std::memcpy(dataOut.data(), &header, headerBytes); // copy message - std::memcpy(dataOut.data() + headerBytes, data.data(), dataBytes); // copy data + std::memcpy(dataOut.data() + headerBytes, data.data(), dataBytes); // copy data std::memcpy(dataOut.data() + headerBytes + dataBytes, &crc, crcBytes); // copy crc #ifdef DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE diff --git a/lib/RS485/RS485_Driver.h b/lib/RS485/RS485_Driver.h index 2156db1..32d6f45 100644 --- a/lib/RS485/RS485_Driver.h +++ b/lib/RS485/RS485_Driver.h @@ -1,5 +1,7 @@ #pragma once +// #define DEBUGLOG_DEFAULT_LOG_LEVEL_TRACE + #include #include #include // Reference the ESP32 built-in serial port library @@ -50,7 +52,6 @@ namespace drivers typedef uint16_t crc_t; public: - MODBUS(const uint32_t baud, const SerialConfig conf); // Func 0x01 @@ -84,7 +85,7 @@ namespace drivers const bool readBinary(const uint8_t device, const uint8_t func, const uint16_t reg, const uint16_t bits, std::vector &out); const bool readInteger(const uint8_t device, const uint8_t func, const uint16_t reg, const uint16_t num, std::vector &out); const bool writeBinary(const uint8_t device, const uint8_t func, const uint16_t reg, const std::vector &in); - const bool writeInteger(const uint8_t device, const uint8_t func, const uint16_t reg, const std::vector &in); + const bool writeInteger(const uint8_t device, const uint8_t func, const uint16_t reg, const std::vector &in, const bool multi); const bool verifyCrc(const std::vector &data); }; } diff --git a/lib/SENECA/S50140_Driver.cpp b/lib/SENECA/S50140_Driver.cpp index ef48c88..e7efd80 100644 --- a/lib/SENECA/S50140_Driver.cpp +++ b/lib/SENECA/S50140_Driver.cpp @@ -12,7 +12,7 @@ namespace drivers const S50140::powerinfo_t S50140::getAll() { - powerinfo_t info; + powerinfo_t info{MAXFLOAT}; info.v = getV(); info.a = getA(); info.pAct = getPact(); @@ -57,19 +57,36 @@ namespace drivers return readFloatReg(REG_WhPart); } - void S50140::resetTotalCounters() + void S50140::delayRequest() { - uint8_t retries(0); - const uint16_t resetAll = 0x0000; - while (retries++ < maxRetries) - { - if (m_bus.writeRegister(m_address, REG_TotCount, resetAll)) - return; - LOG_ERROR("Unable to Reset Powermeter Total Counters, device", m_address); - delay(10); + auto now = millis(); + if ((now - m_lastRequest) < minDelay) + { // minimum 500ms between requests + delay(now - m_lastRequest); } - return; + m_lastRequest = now; } + + const uint8_t S50140::getRegset() + { + std::vector value; + delayRequest(); + m_bus.readHoldingRegisters(m_address, REG_Regset, 2, value); + if (value.empty()) + return UINT8_MAX; + return value.front() + value.back(); + } + + const uint16_t S50140::getCounterStatus() + { + std::vector value; + delayRequest(); + m_bus.readHoldingRegisters(m_address, REG_PartCount, 2, value); + if (value.empty()) + return UINT16_MAX; + return value.front() + value.back(); + } + void S50140::resetPartialCounters() { uint8_t retries(0); @@ -79,15 +96,18 @@ namespace drivers while (retries++ < maxRetries) { bool ok(true); - ok &= m_bus.writeRegister(m_address, REG_TotCount, stopAll); - delay(10); - ok &= m_bus.writeRegister(m_address, REG_TotCount, resetAll); - delay(10); - ok &= m_bus.writeRegister(m_address, REG_TotCount, startAll); + delayRequest(); + LOG_WARN("Powermeter Counter STOP"); + ok &= m_bus.writeRegisters(m_address, REG_PartCount, {0x0000, stopAll}); + delayRequest(); + LOG_WARN("Powermeter Counter RESET"); + ok &= m_bus.writeRegisters(m_address, REG_PartCount, {0x0000, resetAll}); + delayRequest(); + LOG_WARN("Powermeter Counter START"); + ok &= m_bus.writeRegisters(m_address, REG_PartCount, {0x0000, startAll}); if (ok) return; LOG_ERROR("Unable to Reset Powermeter Partial Counters, device", m_address); - delay(10); } return; } @@ -99,11 +119,12 @@ namespace drivers while (retries++ < maxRetries) { + delayRequest(); if (m_bus.readHoldingRegisters(m_address, reg, dataWords, values) && values.size() == dataWords) { - floatval_t fv; // potrebbe essere il contrario, vedremo - fv.hi = values[0]; // magari va invertita ancora l'endianness - fv.lo = values[1]; + floatval_t fv; // potrebbe essere il contrario, vedremo + fv.words.lo = values[0]; // magari va invertita ancora l'endianness + fv.words.hi = values[1]; return fv.f; } LOG_ERROR("Unable to Read Powermeter values, device", m_address); diff --git a/lib/SENECA/S50140_Driver.h b/lib/SENECA/S50140_Driver.h index 5d3d188..8edb4b0 100644 --- a/lib/SENECA/S50140_Driver.h +++ b/lib/SENECA/S50140_Driver.h @@ -11,24 +11,28 @@ namespace drivers private: const uint8_t maxRetries = 5; const uint8_t dataWords = 2; + const uint16_t minDelay = 500; + const uint16_t REG_V = 0x100C; const uint16_t REG_A = 0x1016; const uint16_t REG_Pact = 0x1026; const uint16_t REG_Papp = 0x102E; const uint16_t REG_Prea = 0x1036; - const uint16_t REG_Freq = 0x1036; + const uint16_t REG_Freq = 0x1038; const uint16_t REG_WhTot = 0x1106; const uint16_t REG_WhPart = 0x1400; const uint16_t REG_Serial = 0x0500; const uint16_t REG_Regset = 0x0538; - const uint16_t REG_TotCount = 0x0516; - const uint16_t REG_PartCount = 0x0517; + const uint16_t REG_PartCount = 0x0526; typedef union { float_t f; - uint16_t hi; - uint16_t lo; + struct + { + uint16_t hi; + uint16_t lo; + } words; } floatval_t; public: @@ -59,14 +63,18 @@ namespace drivers const float_t getWhTot(); const float_t getWhPar(); - void resetTotalCounters(); + const uint8_t getRegset(); + const uint16_t getCounterStatus(); + void resetPartialCounters(); private: + void delayRequest(); float_t readFloatReg(const uint16_t reg); private: const uint8_t m_address; drivers::MODBUS &m_bus; + uint64_t m_lastRequest = 0; }; } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 6ffc7b3..02bcc3e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -59,7 +59,6 @@ void loop() auto io = digitalIO(i2c, bus, {relayBoardAddr}); delay(100); auto seneca = drivers::S50140(bus, senecadAddr); - delay(100); Network.onEvent([ð](arduino_event_id_t event, arduino_event_info_t info) { eth.onEvent(event, info); }); @@ -116,16 +115,23 @@ void loop() for (auto j(0); j < io.getOutNum(); j++) { - // io.digitalIOWrite(j, true); LOG_INFO("Input", j, io.digitalIORead(j) ? "True" : "False"); - delay(500); - // io.digitalIOWrite(j, false); + delay(50); } drivers::S50140::powerinfo_t pinfo = seneca.getAll(); - LOG_INFO("Power Info\nV:", pinfo.v, "\nA:", pinfo.a, "\nW:", pinfo.pAct, "\nWh_t:", pinfo.whTot, "\nWh_p:", pinfo.whPar); + LOG_INFO("Power Info ==> V:", pinfo.v, "- A:", pinfo.a, "- W:", pinfo.pAct, "- F:", pinfo.f, "- Wh_t:", pinfo.whTot, "- Wh_p:", pinfo.whPar); - delay(5000); + if (io.digitalIORead(0)) + { + uint8_t regset(seneca.getRegset()); + uint16_t countStat(seneca.getCounterStatus()); + LOG_INFO("Register Set: ", regset); + LOG_INFO("Counter Status: ", countStat); + seneca.resetPartialCounters(); + } + + delay(2000); } ////////////////////////////////////////