diff --git a/lib/RS485/RS485_Driver.cpp b/lib/RS485/RS485_Driver.cpp index 040c68e..992d1f2 100644 --- a/lib/RS485/RS485_Driver.cpp +++ b/lib/RS485/RS485_Driver.cpp @@ -66,6 +66,18 @@ namespace drivers LOG_INFO("Init MODBUS Master Mode"); m_crc.reset(CRC16_MODBUS_POLYNOME, CRC16_MODBUS_INITIAL, CRC16_MODBUS_XOR_OUT, CRC16_MODBUS_REV_IN, CRC16_MAXIM_REV_OUT); m_lastAccess = millis(); + m_lastDevice = 0; + } + + // Get transaction lock + std::unique_lock MODBUS::getLock() + { + return std::unique_lock(m_mutex); + } + + std::mutex &MODBUS::getMutex() + { + return m_mutex; } void MODBUS::delayAccess(const uint8_t device) @@ -74,12 +86,12 @@ namespace drivers return; auto now = millis(); if ((now - m_lastAccess) < c_minDelay) // fixed milliseconds delay between commands to different devices - { // minimum m_lastRequest between requests - LOG_WARN("MODBUS access delay", now - m_lastAccess, "device", device); + { + LOG_WARN("MODBUS access delay", (now - m_lastAccess), "device", device); delay(now - m_lastAccess); } - m_lastAccess = millis(); m_lastDevice = device; + m_lastAccess = millis(); } // Func 0x01 diff --git a/lib/RS485/RS485_Driver.h b/lib/RS485/RS485_Driver.h index de807d8..275996f 100644 --- a/lib/RS485/RS485_Driver.h +++ b/lib/RS485/RS485_Driver.h @@ -34,7 +34,7 @@ namespace drivers const uint8_t c_respHeaderSize = 3; const uint8_t c_respCrcSize = 2; - const uint16_t c_minDelay = 10; + const uint32_t c_minDelay = 500; typedef struct { @@ -62,9 +62,8 @@ namespace drivers MODBUS &operator=(const MODBUS &) = delete; // Get transaction lock - std::unique_lock getLock() { - return std::unique_lock(m_mutex); - } + std::unique_lock getLock(); + std::mutex &getMutex(); // Func 0x01 const bool readCoils(const uint8_t device, const uint16_t reg, const uint16_t num, std::vector &coils); diff --git a/lib/SENECA/S50140_Driver.cpp b/lib/SENECA/S50140_Driver.cpp index 858c3a0..5152ef2 100644 --- a/lib/SENECA/S50140_Driver.cpp +++ b/lib/SENECA/S50140_Driver.cpp @@ -9,10 +9,11 @@ namespace drivers S50140::~S50140() { } - + const S50140::powerinfo_t S50140::getAll() { powerinfo_t info{MAXFLOAT}; + std::lock_guard lock(m_bus.getMutex()); info.v = getV(); info.a = getA(); info.pAct = getPact(); @@ -24,79 +25,71 @@ namespace drivers info.whPar = getWhPar(); return info; } - + const float_t S50140::getV() { - auto lock = m_bus.getLock(); return readFloatReg(REG_V); } const float_t S50140::getA() { - auto lock = m_bus.getLock(); return readFloatReg(REG_A); } const float_t S50140::getPact() { - auto lock = m_bus.getLock(); return readFloatReg(REG_Pact); } const float_t S50140::getPapp() { - auto lock = m_bus.getLock(); return readFloatReg(REG_Papp); } const float_t S50140::getPrea() { - auto lock = m_bus.getLock(); return readFloatReg(REG_Prea); } const float_t S50140::getPf() { - auto lock = m_bus.getLock(); return readFloatReg(REG_Pf); } const float_t S50140::getF() { - auto lock = m_bus.getLock(); return readFloatReg(REG_Freq); } const float_t S50140::getWhTot() { - auto lock = m_bus.getLock(); return readFloatReg(REG_WhTot); } const float_t S50140::getWhPar() { - auto lock = m_bus.getLock(); return readFloatReg(REG_WhPart); } - + void S50140::delayRequest() { auto now = millis(); if ((now - m_lastRequest) < c_minDelay) { // minimum m_lastRequest between requests + LOG_DEBUG("S50140 delay request", (now-m_lastRequest)); delay(now - m_lastRequest); } m_lastRequest = millis(); } - + const uint8_t S50140::getRegset() { std::vector value; + std::lock_guard lock(m_bus.getMutex()); delayRequest(); - auto lock = m_bus.getLock(); m_bus.readHoldingRegisters(m_address, REG_Regset, 2, value); if (value.empty()) - return UINT8_MAX; + return UINT8_MAX; return value.front() + value.back(); } const uint16_t S50140::getCounterStatus() { std::vector value; + std::lock_guard lock(m_bus.getMutex()); delayRequest(); - auto lock = m_bus.getLock(); m_bus.readHoldingRegisters(m_address, REG_PartCount, 2, value); if (value.empty()) return UINT16_MAX; @@ -110,11 +103,11 @@ namespace drivers constexpr uint16_t resetAll = 0x0A03; constexpr uint16_t stopAll = 0x0A02; constexpr uint16_t startAll = 0x0A01; + std::lock_guard lock(m_bus.getMutex()); while (retries++ < c_maxRetries) { bool ok(true); delayRequest(); - auto lock = m_bus.getLock(); LOG_WARN("Powermeter Counter STOP"); ok &= m_bus.writeRegisters(m_address, REG_PartCount, {nullVal, stopAll}); delayRequest(); diff --git a/lib/SENECA/S50140_Driver.h b/lib/SENECA/S50140_Driver.h index b63bd29..7d27770 100644 --- a/lib/SENECA/S50140_Driver.h +++ b/lib/SENECA/S50140_Driver.h @@ -13,7 +13,7 @@ namespace drivers private: const uint8_t c_maxRetries = 5; const uint8_t c_dataWords = 2; - const uint16_t c_minDelay = 500; + const uint32_t c_minDelay = 500; const uint16_t REG_V = 0x100C; const uint16_t REG_A = 0x1016; @@ -80,6 +80,6 @@ namespace drivers private: const uint8_t m_address; drivers::MODBUS &m_bus; - uint64_t m_lastRequest; + uint32_t m_lastRequest; }; } \ No newline at end of file diff --git a/lib/TEMP/R4DCB08_Driver.cpp b/lib/TEMP/R4DCB08_Driver.cpp index bc3d59d..6baca72 100644 --- a/lib/TEMP/R4DCB08_Driver.cpp +++ b/lib/TEMP/R4DCB08_Driver.cpp @@ -5,12 +5,24 @@ namespace drivers R4DCB08::R4DCB08(drivers::MODBUS &bus, const uint8_t address) : m_address(address), m_bus(bus), m_sensors(0) { m_sensors = getNum(); + m_lastRequest = millis(); } R4DCB08::~R4DCB08() { } + void R4DCB08::delayRequest() + { + auto now = millis(); + if ((now - m_lastRequest) < c_minDelay) + { // minimum m_lastRequest between requests + LOG_DEBUG("R4DCB08 delay request", (now-m_lastRequest)); + delay(now - m_lastRequest); + } + m_lastRequest = millis(); + } + const float R4DCB08::getTemp(const uint8_t ch) { uint8_t retries(0); @@ -20,16 +32,16 @@ namespace drivers LOG_ERROR("Invalid Temperature Channel number", ch); return MAXFLOAT; } - auto lock = m_bus.getLock(); - while (retries++ < maxRetries) + std::lock_guard lock(m_bus.getMutex()); + while (retries++ < c_maxRetries) { + delayRequest(); if (m_bus.readHoldingRegisters(m_address, REG_TEMP + ch, 1, rawT) && !rawT.empty()) { return rawT.front() / 10.0f; } LOG_ERROR("Failed to Read Temperature, device", m_address, "channel", ch); rawT.clear(); - delay(50); } return MAXFLOAT; } @@ -39,9 +51,10 @@ namespace drivers uint8_t retries(0); std::vector rawT; std::vector out; - auto lock = m_bus.getLock(); - while (retries++ < maxRetries) + std::lock_guard lock(m_bus.getMutex()); + while (retries++ < c_maxRetries) { + delayRequest(); if (m_bus.readHoldingRegisters(m_address, REG_TEMP, getNum(), rawT) && !rawT.empty()) { out.reserve(rawT.size()); @@ -53,7 +66,6 @@ namespace drivers } LOG_ERROR("Failed to Read All Temperature, device", m_address); rawT.clear(); - delay(50); } out.clear(); return out; @@ -64,20 +76,18 @@ namespace drivers uint8_t retries(0); uint8_t channel(0); corr.resize(getNum()); // max number of temperature correction values is equal to number of sensors - - auto lock = m_bus.getLock(); + std::lock_guard lock(m_bus.getMutex()); for (auto v : corr) { - while (retries++ < maxRetries) + while (retries++ < c_maxRetries) { + delayRequest(); if (m_bus.writeRegister(m_address, REG_TEMPCORR + channel, v * 10)) // convert to decimal degreees to register value { channel++; - delay(50); break; } LOG_ERROR("Failed to Set Temperature Correction, device", m_address); - delay(50); } } } @@ -89,9 +99,10 @@ namespace drivers std::vector out; rawV.reserve(getNum()); - while (retries++ < maxRetries) + std::lock_guard lock(m_bus.getMutex()); + while (retries++ < c_maxRetries) { - auto lock = m_bus.getLock(); + delayRequest(); if (m_bus.readHoldingRegisters(m_address, REG_TEMPCORR, getNum(), rawV)) { out.reserve(rawV.size()); @@ -103,7 +114,6 @@ namespace drivers } LOG_ERROR("Failed to Get Temperature Correction, device", m_address); rawV.clear(); - delay(50); } out.clear(); return out; @@ -116,9 +126,10 @@ namespace drivers uint8_t retries(0); uint8_t sensors(0); std::vector rawT; - while (retries++ < maxRetries) + std::lock_guard lock(m_bus.getMutex()); + while (retries++ < c_maxRetries) { - auto lock = m_bus.getLock(); + delayRequest(); if (m_bus.readHoldingRegisters(m_address, REG_TEMP, T_MAX, rawT)) { for (auto v : rawT) @@ -130,7 +141,6 @@ namespace drivers return m_sensors; } LOG_ERROR("Failed to Get Sensor Number, device", m_address); - delay(50); } LOG_ERROR("No Temperature Sensors Detected, device", m_address); return 0; diff --git a/lib/TEMP/R4DCB08_Driver.h b/lib/TEMP/R4DCB08_Driver.h index 0adee3d..401473c 100644 --- a/lib/TEMP/R4DCB08_Driver.h +++ b/lib/TEMP/R4DCB08_Driver.h @@ -25,7 +25,9 @@ namespace drivers T_MAX }; - const uint8_t maxRetries = 5; + private: + const uint8_t c_maxRetries = 5; + const uint32_t c_minDelay = 500; const uint16_t REG_TEMP = 0x0000; const uint16_t REG_TEMPCORR = 0x0008; @@ -41,9 +43,13 @@ namespace drivers const uint8_t getNum(); + private: + void delayRequest(); + private: const uint8_t m_address; uint8_t m_sensors; MODBUS &m_bus; + uint32_t m_lastRequest; }; } diff --git a/src/digitalIO.cpp b/src/digitalIO.cpp index 3b2e054..00180de 100644 --- a/src/digitalIO.cpp +++ b/src/digitalIO.cpp @@ -146,7 +146,7 @@ const uint8_t digitalIO::getInNum() void digitalIO::writeLocal(const uint8_t ch, const bool value) { uint8_t retries(0); - while (retries++ < maxRetries) + while (retries++ < c_maxRetries) { if (m_localOuts.setOut(ch, value)) { @@ -166,7 +166,7 @@ void digitalIO::writeLocalPort(const std::vector &values) if (values[i]) decValue |= High << i; } - while (retries++ < maxRetries) + while (retries++ < c_maxRetries) { if (m_localOuts.setPort(decValue)) { @@ -182,7 +182,7 @@ void digitalIO::writeRemote(const uint8_t ch, const bool value) uint8_t retries(0); const uint8_t selectedRemote(floor(ch / (float)remoteIO::CH_MAX)); const uint8_t selectedChannel(ch % remoteIO::CH_MAX); - while (retries++ < maxRetries) + while (retries++ < c_maxRetries) { if (m_remotes[selectedRemote].setOut((remoteIO::channel_t)selectedChannel, value)) { @@ -196,7 +196,7 @@ void digitalIO::writeRemote(const uint8_t ch, const bool value) void digitalIO::writeRemotePort(const std::vector &values) { uint8_t retries(0); - while (retries++ < maxRetries) + while (retries++ < c_maxRetries) { bool ok(true); for (uint8_t i(0); i < values.size(); i += remoteIO::CH_MAX) @@ -228,7 +228,7 @@ const bool digitalIO::readLocalOut(const uint8_t ch) { bool value(false); uint8_t retries(0); - while (retries++ < maxRetries) + while (retries++ < c_maxRetries) { if (m_localOuts.readOut(ch, value)) { @@ -256,7 +256,7 @@ const std::vector digitalIO::readLocalOutPort() uint8_t retries(0); uint8_t state(0); std::vector values(getLocalOutNum()); - while (retries++ < maxRetries) + while (retries++ < c_maxRetries) { if (m_localOuts.readPort(state)) { @@ -279,7 +279,7 @@ const bool digitalIO::readRemoteIn(const uint8_t ch) const uint8_t selectedRemote(floor(ch / 8.0f)); const uint8_t selectedChannel(ch % remoteIO::CH_MAX); bool value; - while (retries++ < maxRetries) + while (retries++ < c_maxRetries) { if (m_remotes[selectedRemote].getIn((remoteIO::channel_t)selectedChannel, value)) { @@ -297,7 +297,7 @@ const bool digitalIO::readRemoteOut(const uint8_t ch) const uint8_t selectedRemote(floor(ch / (float)remoteIO::CH_MAX)); const uint8_t selectedChannel(ch % remoteIO::CH_MAX); bool value; - while (retries++ < maxRetries) + while (retries++ < c_maxRetries) { if (m_remotes[selectedRemote].getOut((remoteIO::channel_t)selectedChannel, value)) { @@ -314,7 +314,7 @@ const std::vector digitalIO::readRemoteInPort() uint8_t retries(0); std::vector values; values.reserve(getRemoteInNum()); - while (retries++ < maxRetries) + while (retries++ < c_maxRetries) { bool ok(true); for (uint8_t i(0); i < getRemoteInNum(); i += remoteIO::CH_MAX) @@ -343,7 +343,7 @@ const std::vector digitalIO::readRemoteOutPort() uint8_t retries(0); std::vector values; values.reserve(getRemoteOutNum()); - while (retries++ < maxRetries) + while (retries++ < c_maxRetries) { bool ok(true); for (uint8_t i(0); i < getRemoteOutNum(); i += remoteIO::CH_MAX) diff --git a/src/digitalIO.h b/src/digitalIO.h index b17dc2f..1b29666 100644 --- a/src/digitalIO.h +++ b/src/digitalIO.h @@ -28,7 +28,7 @@ private: DI_MAX }; - const uint8_t maxRetries = 5; + const uint8_t c_maxRetries = 5; public: digitalIO(drivers::I2C &i2c, drivers::MODBUS &bus, std::vector remotes); diff --git a/src/main.cpp b/src/main.cpp index a33ac04..efb4ff3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -140,17 +140,8 @@ void loop() { LOG_INFO("Temperature channel", i++, "->", v); } - i = 0; - delay(10); - for (auto v : tmp.getCorrection()) - { - LOG_INFO("Temperature correction channel", i++, "tc", v); - } - - delay(100); - drivers::S50140::powerinfo_t pinfo = seneca.getAll(); - LOG_INFO("Power Info ==> V:", pinfo.v, "- A:", pinfo.a, "- W:", pinfo.pAct, "- F:", pinfo.f, "- Wh_t:", pinfo.whTot, "- Wh_p:", pinfo.whPar); - + + LOG_INFO("Read Red"); if (io.digitalInRead(0)) // rosso { std::vector v1 = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}; @@ -159,13 +150,11 @@ void loop() LOG_INFO("SET Digital Outputs V1: ", printBoolVec(v1).c_str()); io.digitalOutWritePort(v1); - delay(100); LOG_INFO("GET Digital Outputs V1: ", printBoolVec(io.digitalOutReadPort()).c_str()); delay(2000); LOG_INFO("SET Digital Outputs V2: ", printBoolVec(v2).c_str()); io.digitalOutWritePort(v2); - delay(100); LOG_INFO("GET Digital Outputs V2: ", printBoolVec(io.digitalOutReadPort()).c_str()); delay(2000); @@ -173,9 +162,10 @@ void loop() delay(2000); io.digitalOutWritePort(v0); + delay(2000); } - delay(100); + LOG_INFO("Read Blue"); if (io.digitalInRead(8)) // blu { if (!buzzing) @@ -192,17 +182,22 @@ void loop() } LOG_INFO("Buzzing -> ", buzzing ? "True" : "False"); } - + + LOG_INFO("Read Green"); if (io.digitalInRead(9)) { // verde conf.resetConfig(); } - + + LOG_INFO("Read Yellow"); if (io.digitalInRead(10)) { // giallo esp_restart(); } + drivers::S50140::powerinfo_t pinfo = seneca.getAll(); + 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(conf.m_globalLoopDelay); } diff --git a/src/remoteIO.cpp b/src/remoteIO.cpp index c7781f2..66d69e8 100644 --- a/src/remoteIO.cpp +++ b/src/remoteIO.cpp @@ -4,13 +4,14 @@ remoteIO::remoteIO(const uint8_t address, drivers::MODBUS &bus) : m_address(addr { LOG_INFO("Initializing relay module"); std::vector response; - auto lock = m_bus.getLock(); + std::lock_guard lock(m_bus.getMutex()); if (!m_bus.readHoldingRegisters(m_address, REG_VERSION, 1, response)) { LOG_ERROR("Unable to inizialize relay module"); }; LOG_INFO("Software version", std::to_string(response.at(0) / 100.0f).c_str()); m_initialized = true; + m_lastRequest = millis(); resetAll(false); } @@ -20,11 +21,23 @@ remoteIO::~remoteIO() resetAll(false); } +void remoteIO::delayRequest() +{ + auto now = millis(); + if ((now - m_lastRequest) < c_minDelay) + { // minimum m_lastRequest between requests + LOG_DEBUG("remoteIO delay request", (now - m_lastRequest)); + delay(now - m_lastRequest); + } + m_lastRequest = millis(); +} + const bool remoteIO::setOut(const channel_t ch, const bool value) { if (!m_initialized) return false; - auto lock = m_bus.getLock(); + std::lock_guard lock(m_bus.getMutex()); + delayRequest(); LOG_DEBUG("Write Channel", ch, "->", value ? "True" : "False"); return m_bus.writeCoil(m_address, REG_COILS + ch, value); } @@ -33,7 +46,8 @@ const bool remoteIO::toggleOut(const channel_t ch) { if (!m_initialized) return false; - auto lock = m_bus.getLock(); + std::lock_guard lock(m_bus.getMutex()); + delayRequest(); std::vector value; if (!m_bus.readCoils(m_address, REG_COILS + ch, 1, value)) return false; @@ -45,7 +59,8 @@ const bool remoteIO::setOutPort(const std::vector values) { if (!m_initialized) return false; - auto lock = m_bus.getLock(); + std::lock_guard lock(m_bus.getMutex()); + delayRequest(); LOG_DEBUG("Write Port", CH_MAX); return m_bus.writeCoils(m_address, REG_COILS, values); } @@ -54,7 +69,8 @@ const bool remoteIO::getOut(const channel_t ch, bool &value) { if (!m_initialized) return false; - auto lock = m_bus.getLock(); + std::lock_guard lock(m_bus.getMutex()); + delayRequest(); std::vector values; if (!m_bus.readCoils(m_address, REG_COILS + ch, 1, values)) return false; @@ -67,7 +83,8 @@ const bool remoteIO::getOutPort(std::vector &values) { if (!m_initialized) return false; - auto lock = m_bus.getLock(); + std::lock_guard lock(m_bus.getMutex()); + delayRequest(); LOG_DEBUG("Read Port", CH_MAX); return m_bus.readCoils(m_address, REG_COILS, CH_MAX, values); } @@ -76,7 +93,8 @@ const bool remoteIO::getIn(const channel_t input, bool &value) { if (!m_initialized) return false; - auto lock = m_bus.getLock(); + std::lock_guard lock(m_bus.getMutex()); + delayRequest(); std::vector values; if (!m_bus.readInputs(m_address, REG_INPUT + input, 1, values)) return false; @@ -89,7 +107,8 @@ const bool remoteIO::getInPort(std::vector &values) { if (!m_initialized) return false; - auto lock = m_bus.getLock(); + std::lock_guard lock(m_bus.getMutex()); + delayRequest(); LOG_DEBUG("Read Inputs", CH_MAX); return m_bus.readInputs(m_address, REG_INPUT, CH_MAX, values); } diff --git a/src/remoteIO.h b/src/remoteIO.h index 1ee49b1..d31ca4b 100644 --- a/src/remoteIO.h +++ b/src/remoteIO.h @@ -8,9 +8,21 @@ class remoteIO { public: - typedef enum {CH1, CH2, CH3, CH4, CH5, CH6, CH7, CH8, CH_MAX} channel_t; + typedef enum + { + CH1, + CH2, + CH3, + CH4, + CH5, + CH6, + CH7, + CH8, + CH_MAX + } channel_t; private: + const uint32_t c_minDelay = 100; const uint16_t REG_VERSION = 0x8000; const uint16_t REG_COILS = 0x0000; const uint16_t REG_INPUT = 0x0000; @@ -32,8 +44,12 @@ public: void resetAll(const bool value); +private: + void delayRequest(); + private: bool m_initialized; drivers::MODBUS &m_bus; const uint8_t m_address; + uint32_t m_lastRequest; };