improved bus wait with raii class that updates last access
This commit is contained in:
@@ -3,8 +3,11 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
|
|
||||||
|
#include <busdelay.h>
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
#define BUS_DELAY drivers::BusDelay(m_lastAccess, c_minDelay, "MODBUS")
|
||||||
|
|
||||||
namespace drivers
|
namespace drivers
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -80,26 +83,11 @@ namespace drivers
|
|||||||
return m_mutex;
|
return m_mutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MODBUS::delayAccess(const uint8_t device)
|
|
||||||
{
|
|
||||||
if (device == m_lastDevice)
|
|
||||||
return;
|
|
||||||
auto now = millis();
|
|
||||||
if ((now - m_lastAccess) < c_minDelay) // fixed milliseconds delay between commands to different devices
|
|
||||||
{
|
|
||||||
LOG_DEBUG("MODBUS access delay", (now - m_lastAccess), "device", device);
|
|
||||||
delay(now - m_lastAccess);
|
|
||||||
}
|
|
||||||
m_lastDevice = device;
|
|
||||||
m_lastAccess = millis();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Func 0x01
|
// Func 0x01
|
||||||
const bool MODBUS::readCoils(const uint8_t device, const uint16_t reg, const uint16_t num, std::vector<bool> &coils)
|
const bool MODBUS::readCoils(const uint8_t device, const uint16_t reg, const uint16_t num, std::vector<bool> &coils)
|
||||||
{
|
{
|
||||||
constexpr uint8_t func = 0x01;
|
constexpr uint8_t func = 0x01;
|
||||||
delayAccess(device);
|
LOG_DEBUG("Read coils: dev[", printHex(device).c_str(), "], reg[", printHex(reg).c_str(), "], num[", num, "]");
|
||||||
LOG_DEBUG("Read coils: dev[", device, "], reg[", reg, "], num[", num, "]");
|
|
||||||
return readBinary(device, func, reg, num, coils);
|
return readBinary(device, func, reg, num, coils);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,8 +95,7 @@ namespace drivers
|
|||||||
const bool MODBUS::readInputs(const uint8_t device, const uint16_t reg, const uint8_t num, std::vector<bool> &inputs)
|
const bool MODBUS::readInputs(const uint8_t device, const uint16_t reg, const uint8_t num, std::vector<bool> &inputs)
|
||||||
{
|
{
|
||||||
constexpr uint8_t func = 0x02;
|
constexpr uint8_t func = 0x02;
|
||||||
delayAccess(device);
|
LOG_DEBUG("Read multi inputs: dev[", printHex(device).c_str(), "], reg[", printHex(reg).c_str(), "], num[", num, "]");
|
||||||
LOG_DEBUG("Read multi inputs: dev[", device, "], reg[", reg, "], num[", num, "]");
|
|
||||||
return readBinary(device, func, reg, num, inputs);
|
return readBinary(device, func, reg, num, inputs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,8 +103,7 @@ namespace drivers
|
|||||||
const bool MODBUS::readHoldingRegisters(const uint8_t device, const uint16_t reg, const uint8_t num, std::vector<uint16_t> &values)
|
const bool MODBUS::readHoldingRegisters(const uint8_t device, const uint16_t reg, const uint8_t num, std::vector<uint16_t> &values)
|
||||||
{
|
{
|
||||||
constexpr uint8_t func = 0x03;
|
constexpr uint8_t func = 0x03;
|
||||||
delayAccess(device);
|
LOG_DEBUG("Read multi holding registers: dev[", printHex(device).c_str(), "], reg[", printHex(reg).c_str(), "], num[", num, "]");
|
||||||
LOG_DEBUG("Read multi holding registers: dev[", device, "], reg[", reg, "], num[", num, "]");
|
|
||||||
return readInteger(device, func, reg, num, values);
|
return readInteger(device, func, reg, num, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,8 +111,7 @@ namespace drivers
|
|||||||
const bool MODBUS::readInputRegisters(const uint8_t device, const uint16_t reg, const uint8_t num, std::vector<uint16_t> &values)
|
const bool MODBUS::readInputRegisters(const uint8_t device, const uint16_t reg, const uint8_t num, std::vector<uint16_t> &values)
|
||||||
{
|
{
|
||||||
constexpr uint8_t func = 0x04;
|
constexpr uint8_t func = 0x04;
|
||||||
delayAccess(device);
|
LOG_DEBUG("Read multi input registers: dev[", printHex(device).c_str(), "], reg[", printHex(reg).c_str(), "], num[", num, "]");
|
||||||
LOG_DEBUG("Read multi input registers: dev[", device, "], reg[", reg, "], num[", num, "]");
|
|
||||||
return readInteger(device, func, reg, num, values);
|
return readInteger(device, func, reg, num, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,8 +119,7 @@ namespace drivers
|
|||||||
const bool MODBUS::writeCoil(const uint8_t device, const uint16_t coil, const bool value)
|
const bool MODBUS::writeCoil(const uint8_t device, const uint16_t coil, const bool value)
|
||||||
{
|
{
|
||||||
constexpr uint8_t func = 0x05;
|
constexpr uint8_t func = 0x05;
|
||||||
delayAccess(device);
|
LOG_DEBUG("Write single coil: dev[", printHex(device).c_str(), "], coil[", printHex(coil).c_str(), "], value[", value ? "true" : "false", "]");
|
||||||
LOG_DEBUG("Write single coil: dev[", device, "], coil[", coil, "], value[", value ? "true" : "false", "]");
|
|
||||||
return writeBinary(device, func, coil, {value});
|
return writeBinary(device, func, coil, {value});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,8 +127,7 @@ namespace drivers
|
|||||||
const bool MODBUS::writeRegister(const uint8_t device, const uint16_t reg, const uint16_t value)
|
const bool MODBUS::writeRegister(const uint8_t device, const uint16_t reg, const uint16_t value)
|
||||||
{
|
{
|
||||||
constexpr uint8_t func = 0x06;
|
constexpr uint8_t func = 0x06;
|
||||||
delayAccess(device);
|
LOG_DEBUG("Write single register: dev[", printHex(device).c_str(), "], reg[", printHex(reg).c_str(), "], value[", value, "]");
|
||||||
LOG_DEBUG("Write single register: dev[", device, "], reg[", reg, "], value[", value, "]");
|
|
||||||
return writeInteger(device, func, reg, {value}, false);
|
return writeInteger(device, func, reg, {value}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,8 +135,7 @@ namespace drivers
|
|||||||
const bool MODBUS::writeCoils(const uint8_t device, const uint16_t coils, const std::vector<bool> &values)
|
const bool MODBUS::writeCoils(const uint8_t device, const uint16_t coils, const std::vector<bool> &values)
|
||||||
{
|
{
|
||||||
constexpr uint8_t func = 0x0F;
|
constexpr uint8_t func = 0x0F;
|
||||||
delayAccess(device);
|
LOG_DEBUG("Write multi coils: dev[", printHex(device).c_str(), "], start[", printHex(coils).c_str(), "], num[", values.size(), "]");
|
||||||
LOG_DEBUG("Write multi coils: dev[", device, "], start[", coils, "], num[", values.size(), "]");
|
|
||||||
return writeBinary(device, func, coils, values);
|
return writeBinary(device, func, coils, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,8 +143,7 @@ namespace drivers
|
|||||||
const bool MODBUS::writeRegisters(const uint8_t device, const uint16_t reg, const std::vector<uint16_t> &values)
|
const bool MODBUS::writeRegisters(const uint8_t device, const uint16_t reg, const std::vector<uint16_t> &values)
|
||||||
{
|
{
|
||||||
constexpr uint8_t func = 0x10;
|
constexpr uint8_t func = 0x10;
|
||||||
delayAccess(device);
|
LOG_DEBUG("Write multi registers: dev[", printHex(device).c_str(), "], start[", printHex(reg).c_str(), "], num[", values.size(), "]");
|
||||||
LOG_DEBUG("Write multi registers: dev[", device, "], start[", reg, "], num[", values.size(), "]");
|
|
||||||
return writeInteger(device, func, reg, values, true);
|
return writeInteger(device, func, reg, values, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,6 +153,13 @@ namespace drivers
|
|||||||
|
|
||||||
const bool MODBUS::readBinary(const uint8_t device, const uint8_t func, const uint16_t reg, const uint16_t bits, std::vector<bool> &out)
|
const bool MODBUS::readBinary(const uint8_t device, const uint8_t func, const uint16_t reg, const uint16_t bits, std::vector<bool> &out)
|
||||||
{
|
{
|
||||||
|
// Delay Bus Access between different devices
|
||||||
|
if (device != m_lastDevice)
|
||||||
|
{
|
||||||
|
LOG_WARN("MODBUS device change from ", printHex(m_lastDevice).c_str(), "to", printHex(device).c_str());
|
||||||
|
BUS_DELAY;
|
||||||
|
m_lastDevice = device;
|
||||||
|
}
|
||||||
if (!write(singleRequest(device, func, reg, bits)))
|
if (!write(singleRequest(device, func, reg, bits)))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Failed send readBinary command");
|
LOG_ERROR("Failed send readBinary command");
|
||||||
@@ -222,6 +210,13 @@ namespace drivers
|
|||||||
|
|
||||||
const bool MODBUS::readInteger(const uint8_t device, const uint8_t func, const uint16_t reg, const uint16_t num, std::vector<uint16_t> &out)
|
const bool MODBUS::readInteger(const uint8_t device, const uint8_t func, const uint16_t reg, const uint16_t num, std::vector<uint16_t> &out)
|
||||||
{
|
{
|
||||||
|
// Delay Bus Access between different devices
|
||||||
|
if (device != m_lastDevice)
|
||||||
|
{
|
||||||
|
LOG_WARN("MODBUS device change from ", printHex(m_lastDevice).c_str(), "to", printHex(device).c_str());
|
||||||
|
BUS_DELAY;
|
||||||
|
m_lastDevice = device;
|
||||||
|
}
|
||||||
if (!write(singleRequest(device, func, reg, num)))
|
if (!write(singleRequest(device, func, reg, num)))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Failed send readInteger command");
|
LOG_ERROR("Failed send readInteger command");
|
||||||
@@ -268,6 +263,13 @@ namespace drivers
|
|||||||
|
|
||||||
const bool MODBUS::writeBinary(const uint8_t device, const uint8_t func, const uint16_t reg, const std::vector<bool> &in)
|
const bool MODBUS::writeBinary(const uint8_t device, const uint8_t func, const uint16_t reg, const std::vector<bool> &in)
|
||||||
{
|
{
|
||||||
|
// Delay Bus Access between different devices
|
||||||
|
if (device != m_lastDevice)
|
||||||
|
{
|
||||||
|
LOG_WARN("MODBUS device change from ", printHex(m_lastDevice).c_str(), "to", printHex(device).c_str());
|
||||||
|
BUS_DELAY;
|
||||||
|
m_lastDevice = device;
|
||||||
|
}
|
||||||
const uint16_t bits(in.size());
|
const uint16_t bits(in.size());
|
||||||
std::vector<uint8_t> bitsOut;
|
std::vector<uint8_t> bitsOut;
|
||||||
if (bits == 1) // if single coil value must be 0x00FF[00] for on[off]
|
if (bits == 1) // if single coil value must be 0x00FF[00] for on[off]
|
||||||
@@ -320,6 +322,13 @@ namespace drivers
|
|||||||
|
|
||||||
const bool MODBUS::writeInteger(const uint8_t device, const uint8_t func, const uint16_t reg, const std::vector<uint16_t> &in, const bool multi)
|
const bool MODBUS::writeInteger(const uint8_t device, const uint8_t func, const uint16_t reg, const std::vector<uint16_t> &in, const bool multi)
|
||||||
{
|
{
|
||||||
|
// Delay Bus Access between different devices
|
||||||
|
if (device != m_lastDevice)
|
||||||
|
{
|
||||||
|
LOG_WARN("MODBUS device change from ", printHex(m_lastDevice).c_str(), "to", printHex(device).c_str());
|
||||||
|
BUS_DELAY;
|
||||||
|
m_lastDevice = device;
|
||||||
|
}
|
||||||
const uint16_t num(in.size());
|
const uint16_t num(in.size());
|
||||||
if (!multi)
|
if (!multi)
|
||||||
{
|
{
|
||||||
@@ -439,10 +448,12 @@ namespace drivers
|
|||||||
// verify crc code
|
// verify crc code
|
||||||
if (highByte(computedCrc) != crcHi || lowByte(computedCrc) != crcLo)
|
if (highByte(computedCrc) != crcHi || lowByte(computedCrc) != crcLo)
|
||||||
{
|
{
|
||||||
LOG_ERROR("Failed verify CRC code: comp[", computedCrc, "], rec[", receivedCrc, "]");
|
LOG_ERROR("Failed verify CRC code: comp[", printHex(computedCrc).c_str(), "], rec[", printHex(receivedCrc).c_str(), "]");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef BUS_DELAY
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ namespace drivers
|
|||||||
|
|
||||||
const uint8_t c_respHeaderSize = 3;
|
const uint8_t c_respHeaderSize = 3;
|
||||||
const uint8_t c_respCrcSize = 2;
|
const uint8_t c_respCrcSize = 2;
|
||||||
const uint32_t c_minDelay = 500;
|
const uint32_t c_minDelay = 250;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
|||||||
37
lib/RS485/busdelay.h
Normal file
37
lib/RS485/busdelay.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define DEBUGLOG_DEFAULT_LOG_LEVEL_INFO
|
||||||
|
|
||||||
|
#include <DebugLog.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
namespace drivers
|
||||||
|
{
|
||||||
|
|
||||||
|
class BusDelay
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BusDelay(uint32_t &lastAccess, const uint32_t minDelay, const char *title) : m_lastAccess(lastAccess)
|
||||||
|
{
|
||||||
|
const uint32_t now = millis();
|
||||||
|
const uint32_t wait = now - lastAccess;
|
||||||
|
if (wait < minDelay)
|
||||||
|
{
|
||||||
|
LOG_WARN(title, "delay", wait);
|
||||||
|
delay(wait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BusDelay(BusDelay &) = delete;
|
||||||
|
BusDelay operator=(BusDelay &) = delete;
|
||||||
|
|
||||||
|
~BusDelay()
|
||||||
|
{
|
||||||
|
m_lastAccess = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t &m_lastAccess;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
#include <S50140_Driver.h>
|
#include <S50140_Driver.h>
|
||||||
|
#include <busdelay.h>
|
||||||
|
|
||||||
|
#define BUS_DELAY drivers::BusDelay(m_lastRequest, c_minDelay, "S50140")
|
||||||
|
|
||||||
namespace drivers
|
namespace drivers
|
||||||
{
|
{
|
||||||
@@ -63,22 +66,11 @@ namespace drivers
|
|||||||
return readFloatReg(REG_WhPart);
|
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()
|
const uint8_t S50140::getRegset()
|
||||||
{
|
{
|
||||||
std::vector<uint16_t> value;
|
std::vector<uint16_t> value;
|
||||||
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
||||||
delayRequest();
|
BUS_DELAY;
|
||||||
m_bus.readHoldingRegisters(m_address, REG_Regset, 2, value);
|
m_bus.readHoldingRegisters(m_address, REG_Regset, 2, value);
|
||||||
if (value.empty())
|
if (value.empty())
|
||||||
return UINT8_MAX;
|
return UINT8_MAX;
|
||||||
@@ -89,7 +81,7 @@ namespace drivers
|
|||||||
{
|
{
|
||||||
std::vector<uint16_t> value;
|
std::vector<uint16_t> value;
|
||||||
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
||||||
delayRequest();
|
BUS_DELAY;
|
||||||
m_bus.readHoldingRegisters(m_address, REG_PartCount, 2, value);
|
m_bus.readHoldingRegisters(m_address, REG_PartCount, 2, value);
|
||||||
if (value.empty())
|
if (value.empty())
|
||||||
return UINT16_MAX;
|
return UINT16_MAX;
|
||||||
@@ -107,18 +99,24 @@ namespace drivers
|
|||||||
while (retries++ < c_maxRetries)
|
while (retries++ < c_maxRetries)
|
||||||
{
|
{
|
||||||
bool ok(true);
|
bool ok(true);
|
||||||
delayRequest();
|
{
|
||||||
LOG_WARN("Powermeter Counter STOP");
|
LOG_WARN("Powermeter Counter STOP");
|
||||||
|
BUS_DELAY;
|
||||||
ok &= m_bus.writeRegisters(m_address, REG_PartCount, {nullVal, stopAll});
|
ok &= m_bus.writeRegisters(m_address, REG_PartCount, {nullVal, stopAll});
|
||||||
delayRequest();
|
};
|
||||||
|
{
|
||||||
LOG_WARN("Powermeter Counter RESET");
|
LOG_WARN("Powermeter Counter RESET");
|
||||||
|
BUS_DELAY;
|
||||||
ok &= m_bus.writeRegisters(m_address, REG_PartCount, {nullVal, resetAll});
|
ok &= m_bus.writeRegisters(m_address, REG_PartCount, {nullVal, resetAll});
|
||||||
delayRequest();
|
};
|
||||||
|
{
|
||||||
LOG_WARN("Powermeter Counter START");
|
LOG_WARN("Powermeter Counter START");
|
||||||
|
BUS_DELAY;
|
||||||
ok &= m_bus.writeRegisters(m_address, REG_PartCount, {nullVal, startAll});
|
ok &= m_bus.writeRegisters(m_address, REG_PartCount, {nullVal, startAll});
|
||||||
|
};
|
||||||
if (ok)
|
if (ok)
|
||||||
return;
|
return;
|
||||||
LOG_ERROR("Unable to Reset Powermeter Partial Counters, device", m_address);
|
LOG_ERROR("Unable to Reset Powermeter Partial Counters, device", printHex(m_address).c_str());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -127,10 +125,9 @@ namespace drivers
|
|||||||
{
|
{
|
||||||
uint8_t retries(0);
|
uint8_t retries(0);
|
||||||
std::vector<uint16_t> values;
|
std::vector<uint16_t> values;
|
||||||
|
|
||||||
while (retries++ < c_maxRetries)
|
while (retries++ < c_maxRetries)
|
||||||
{
|
{
|
||||||
delayRequest();
|
BUS_DELAY;
|
||||||
if (m_bus.readHoldingRegisters(m_address, reg, c_dataWords, values) && values.size() == c_dataWords)
|
if (m_bus.readHoldingRegisters(m_address, reg, c_dataWords, values) && values.size() == c_dataWords)
|
||||||
{
|
{
|
||||||
floatval_t fv; // potrebbe essere il contrario, vedremo
|
floatval_t fv; // potrebbe essere il contrario, vedremo
|
||||||
@@ -138,9 +135,11 @@ namespace drivers
|
|||||||
fv.words.hi = values[1];
|
fv.words.hi = values[1];
|
||||||
return fv.f;
|
return fv.f;
|
||||||
}
|
}
|
||||||
LOG_ERROR("Unable to Read Powermeter values, device", m_address);
|
LOG_ERROR("Unable to Read Powermeter values, device", printHex(m_address).c_str());
|
||||||
}
|
}
|
||||||
return MAXFLOAT;
|
return MAXFLOAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef BUS_DELAY
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include <DebugLog.h>
|
#include <DebugLog.h>
|
||||||
#include <RS485_Driver.h>
|
#include <RS485_Driver.h>
|
||||||
|
#include <utils.h>
|
||||||
|
|
||||||
namespace drivers
|
namespace drivers
|
||||||
{
|
{
|
||||||
@@ -13,7 +14,7 @@ namespace drivers
|
|||||||
private:
|
private:
|
||||||
const uint8_t c_maxRetries = 5;
|
const uint8_t c_maxRetries = 5;
|
||||||
const uint8_t c_dataWords = 2;
|
const uint8_t c_dataWords = 2;
|
||||||
const uint32_t c_minDelay = 500;
|
const uint32_t c_minDelay = 100;
|
||||||
|
|
||||||
const uint16_t REG_V = 0x100C;
|
const uint16_t REG_V = 0x100C;
|
||||||
const uint16_t REG_A = 0x1016;
|
const uint16_t REG_A = 0x1016;
|
||||||
@@ -74,7 +75,6 @@ namespace drivers
|
|||||||
void resetPartialCounters();
|
void resetPartialCounters();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void delayRequest();
|
|
||||||
float_t readFloatReg(const uint16_t reg);
|
float_t readFloatReg(const uint16_t reg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#include <R4DCB08_Driver.h>
|
#include <R4DCB08_Driver.h>
|
||||||
|
#include <busdelay.h>
|
||||||
|
|
||||||
|
#define BUS_DELAY drivers::BusDelay(m_lastRequest, c_minDelay, "R4DCB08")
|
||||||
|
|
||||||
namespace drivers
|
namespace drivers
|
||||||
{
|
{
|
||||||
@@ -12,17 +15,6 @@ namespace drivers
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
const float R4DCB08::getTemp(const uint8_t ch)
|
||||||
{
|
{
|
||||||
uint8_t retries(0);
|
uint8_t retries(0);
|
||||||
@@ -35,12 +27,12 @@ namespace drivers
|
|||||||
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
||||||
while (retries++ < c_maxRetries)
|
while (retries++ < c_maxRetries)
|
||||||
{
|
{
|
||||||
delayRequest();
|
BUS_DELAY;
|
||||||
if (m_bus.readHoldingRegisters(m_address, REG_TEMP + ch, 1, rawT) && !rawT.empty())
|
if (m_bus.readHoldingRegisters(m_address, REG_TEMP + ch, 1, rawT) && !rawT.empty())
|
||||||
{
|
{
|
||||||
return rawT.front() / 10.0f;
|
return rawT.front() / 10.0f;
|
||||||
}
|
}
|
||||||
LOG_ERROR("Failed to Read Temperature, device", m_address, "channel", ch);
|
LOG_ERROR("Failed to Read Temperature, device", printHex(m_address).c_str(), "channel", ch);
|
||||||
rawT.clear();
|
rawT.clear();
|
||||||
}
|
}
|
||||||
return MAXFLOAT;
|
return MAXFLOAT;
|
||||||
@@ -54,7 +46,7 @@ namespace drivers
|
|||||||
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
||||||
while (retries++ < c_maxRetries)
|
while (retries++ < c_maxRetries)
|
||||||
{
|
{
|
||||||
delayRequest();
|
BUS_DELAY;
|
||||||
if (m_bus.readHoldingRegisters(m_address, REG_TEMP, getNum(), rawT) && !rawT.empty())
|
if (m_bus.readHoldingRegisters(m_address, REG_TEMP, getNum(), rawT) && !rawT.empty())
|
||||||
{
|
{
|
||||||
out.reserve(rawT.size());
|
out.reserve(rawT.size());
|
||||||
@@ -64,7 +56,7 @@ namespace drivers
|
|||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
LOG_ERROR("Failed to Read All Temperature, device", m_address);
|
LOG_ERROR("Failed to Read All Temperature, device", printHex(m_address).c_str());
|
||||||
rawT.clear();
|
rawT.clear();
|
||||||
}
|
}
|
||||||
out.clear();
|
out.clear();
|
||||||
@@ -81,13 +73,13 @@ namespace drivers
|
|||||||
{
|
{
|
||||||
while (retries++ < c_maxRetries)
|
while (retries++ < c_maxRetries)
|
||||||
{
|
{
|
||||||
delayRequest();
|
BUS_DELAY;
|
||||||
if (m_bus.writeRegister(m_address, REG_TEMPCORR + channel, v * 10)) // convert to decimal degreees to register value
|
if (m_bus.writeRegister(m_address, REG_TEMPCORR + channel, v * 10)) // convert to decimal degreees to register value
|
||||||
{
|
{
|
||||||
channel++;
|
channel++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
LOG_ERROR("Failed to Set Temperature Correction, device", m_address);
|
LOG_ERROR("Failed to Set Temperature Correction, device", printHex(m_address).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,7 +94,7 @@ namespace drivers
|
|||||||
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
||||||
while (retries++ < c_maxRetries)
|
while (retries++ < c_maxRetries)
|
||||||
{
|
{
|
||||||
delayRequest();
|
BUS_DELAY;
|
||||||
if (m_bus.readHoldingRegisters(m_address, REG_TEMPCORR, getNum(), rawV))
|
if (m_bus.readHoldingRegisters(m_address, REG_TEMPCORR, getNum(), rawV))
|
||||||
{
|
{
|
||||||
out.reserve(rawV.size());
|
out.reserve(rawV.size());
|
||||||
@@ -112,7 +104,7 @@ namespace drivers
|
|||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
LOG_ERROR("Failed to Get Temperature Correction, device", m_address);
|
LOG_ERROR("Failed to Get Temperature Correction, device", printHex(m_address).c_str());
|
||||||
rawV.clear();
|
rawV.clear();
|
||||||
}
|
}
|
||||||
out.clear();
|
out.clear();
|
||||||
@@ -129,7 +121,7 @@ namespace drivers
|
|||||||
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
||||||
while (retries++ < c_maxRetries)
|
while (retries++ < c_maxRetries)
|
||||||
{
|
{
|
||||||
delayRequest();
|
BUS_DELAY;
|
||||||
if (m_bus.readHoldingRegisters(m_address, REG_TEMP, T_MAX, rawT))
|
if (m_bus.readHoldingRegisters(m_address, REG_TEMP, T_MAX, rawT))
|
||||||
{
|
{
|
||||||
for (auto v : rawT)
|
for (auto v : rawT)
|
||||||
@@ -140,9 +132,11 @@ namespace drivers
|
|||||||
m_sensors = sensors;
|
m_sensors = sensors;
|
||||||
return m_sensors;
|
return m_sensors;
|
||||||
}
|
}
|
||||||
LOG_ERROR("Failed to Get Sensor Number, device", m_address);
|
LOG_ERROR("Failed to Get Sensor Number, device", printHex(m_address).c_str());
|
||||||
}
|
}
|
||||||
LOG_ERROR("No Temperature Sensors Detected, device", m_address);
|
LOG_ERROR("No Temperature Sensors Detected, device", printHex(m_address).c_str());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef BUS_DELAY
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include <DebugLog.h>
|
#include <DebugLog.h>
|
||||||
#include <RS485_Driver.h>
|
#include <RS485_Driver.h>
|
||||||
|
#include <utils.h>
|
||||||
|
|
||||||
namespace drivers
|
namespace drivers
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
|
||||||
void printBytes(const char title[], const std::vector<uint8_t> &b)
|
void printBytes(const char title[], const std::vector<uint8_t> &b)
|
||||||
{
|
{
|
||||||
Serial0.flush();
|
Serial0.flush();
|
||||||
@@ -48,3 +47,17 @@ const std::string printBoolVec(const std::vector<bool> &vals)
|
|||||||
}
|
}
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string printHex(const uint8_t val)
|
||||||
|
{
|
||||||
|
std::string buf(5, '\0');
|
||||||
|
sprintf(buf.data(), "0x%02x", val);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string printHex(const uint16_t val)
|
||||||
|
{
|
||||||
|
std::string buf(7, '\0');
|
||||||
|
sprintf(buf.data(), "0x%04x", val);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
@@ -16,3 +16,7 @@ void printBytes(const char title[], const std::vector<uint16_t> &b);
|
|||||||
void printBool(const char title[], const std::vector<bool> &vals);
|
void printBool(const char title[], const std::vector<bool> &vals);
|
||||||
|
|
||||||
const std::string printBoolVec(const std::vector<bool> &vals);
|
const std::string printBoolVec(const std::vector<bool> &vals);
|
||||||
|
|
||||||
|
const std::string printHex(const uint8_t val);
|
||||||
|
|
||||||
|
const std::string printHex(const uint16_t val);
|
||||||
|
|||||||
@@ -32,11 +32,12 @@ namespace commands
|
|||||||
ArduinoJson::JsonDocument response;
|
ArduinoJson::JsonDocument response;
|
||||||
const auto pinfo = dev.seneca.getAll();
|
const auto pinfo = dev.seneca.getAll();
|
||||||
response["cmd"] = "getHPpower";
|
response["cmd"] = "getHPpower";
|
||||||
auto values = response["params"].to<JsonObject>();
|
auto values = response["values"].to<JsonObject>();
|
||||||
values["power"] = pinfo.pAct;
|
values["power"] = pinfo.pAct;
|
||||||
values["current"] = pinfo.a;
|
values["current"] = pinfo.a;
|
||||||
|
values["voltage"] = pinfo.v;
|
||||||
values["energy"] = pinfo.whPar;
|
values["energy"] = pinfo.whPar;
|
||||||
LOG_INFO("getHPpower -> power", pinfo.pAct, "current", pinfo.a, "energy", pinfo.whPar);
|
LOG_INFO("getHPpower -> power", pinfo.pAct, "current", pinfo.a, "voltage", pinfo.v, "energy", pinfo.whPar);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#define DEBUGLOG_DEFAULT_LOG_LEVEL_INFO
|
||||||
|
|
||||||
#include <DebugLog.h>
|
#include <DebugLog.h>
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
|||||||
20
src/main.cpp
20
src/main.cpp
@@ -1,3 +1,5 @@
|
|||||||
|
#define DEBUGLOG_DEFAULT_LOG_LEVEL_INFO
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <DebugLog.h>
|
#include <DebugLog.h>
|
||||||
#include <DebugLogEnable.h>
|
#include <DebugLogEnable.h>
|
||||||
@@ -57,7 +59,7 @@ void loop()
|
|||||||
std::function<void(const ArduinoJson::JsonDocument &)> commandsCallback =
|
std::function<void(const ArduinoJson::JsonDocument &)> commandsCallback =
|
||||||
[&mqtt, &devices](const ArduinoJson::JsonDocument &doc)
|
[&mqtt, &devices](const ArduinoJson::JsonDocument &doc)
|
||||||
{
|
{
|
||||||
if (!doc["cmd"].is<std::string>() || !doc["params"].is<ArduinoJson::JsonObject>())
|
if (!doc["cmd"].is<std::string>())
|
||||||
{
|
{
|
||||||
LOG_ERROR("Invalid Json Command");
|
LOG_ERROR("Invalid Json Command");
|
||||||
return;
|
return;
|
||||||
@@ -123,19 +125,19 @@ void loop()
|
|||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
const uint32_t start(millis());
|
||||||
const std::string timeStr(rtc.getTimeStr());
|
const std::string timeStr(rtc.getTimeStr());
|
||||||
LOG_INFO("[", k++, "] Loop - Current Datetime", timeStr.c_str());
|
LOG_INFO("[", k++, "] Loop - Current Datetime", timeStr.c_str());
|
||||||
|
|
||||||
{
|
{
|
||||||
ArduinoJson::JsonDocument poll;
|
ArduinoJson::JsonDocument poll;
|
||||||
poll["cmd"] = "POLL";
|
poll["cmd"] = "POLL";
|
||||||
auto params = poll["params"].to<ArduinoJson::JsonObject>();
|
auto params = poll["values"].to<ArduinoJson::JsonObject>();
|
||||||
params["time"] = timeStr;
|
params["time"] = timeStr;
|
||||||
params["number"] = k;
|
params["number"] = k;
|
||||||
mqtt.publish(conf.m_mqttPublish["answers"], poll);
|
mqtt.publish(conf.m_mqttPublish["answers"], poll);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
ArduinoJson::JsonDocument ti;
|
ArduinoJson::JsonDocument ti;
|
||||||
auto tempinfo = tmp.getTempAll();
|
auto tempinfo = tmp.getTempAll();
|
||||||
@@ -145,16 +147,6 @@ void loop()
|
|||||||
mqtt.publish(conf.m_mqttPublish["temperatures"], ti);
|
mqtt.publish(conf.m_mqttPublish["temperatures"], ti);
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
|
||||||
ArduinoJson::JsonDocument pi;
|
|
||||||
auto powerinfo = seneca.getAll();
|
|
||||||
pi["power"] = powerinfo.pAct;
|
|
||||||
pi["current"] = powerinfo.a;
|
|
||||||
pi["energy"] = powerinfo.whPar;
|
|
||||||
pi["voltage"] = powerinfo.v;
|
|
||||||
mqtt.publish(conf.m_mqttPublish["heatpump"], pi);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (io.digitalInRead(0)) // ROSSO - Config Reset
|
if (io.digitalInRead(0)) // ROSSO - Config Reset
|
||||||
{
|
{
|
||||||
LOG_WARN("Config RESET!");
|
LOG_WARN("Config RESET!");
|
||||||
@@ -171,7 +163,7 @@ void loop()
|
|||||||
esp_restart();
|
esp_restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
delay(conf.m_globalLoopDelay); // to avoid too fast loop
|
delay(conf.m_globalLoopDelay - (start - millis())); // to avoid too fast loop, keep precise timing computing loop time
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////
|
////////////////////////////////////////
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#include <remoteIO.h>
|
#include <remoteIO.h>
|
||||||
|
#include <busdelay.h>
|
||||||
|
|
||||||
|
#define BUS_DELAY drivers::BusDelay(m_lastRequest, c_minDelay, "remoteIO")
|
||||||
|
|
||||||
remoteIO::remoteIO(const uint8_t address, drivers::MODBUS &bus) : m_address(address), m_initialized(false), m_bus(bus)
|
remoteIO::remoteIO(const uint8_t address, drivers::MODBUS &bus) : m_address(address), m_initialized(false), m_bus(bus)
|
||||||
{
|
{
|
||||||
@@ -21,23 +24,12 @@ remoteIO::~remoteIO()
|
|||||||
resetAll(false);
|
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)
|
const bool remoteIO::setOut(const channel_t ch, const bool value)
|
||||||
{
|
{
|
||||||
if (!m_initialized)
|
if (!m_initialized)
|
||||||
return false;
|
return false;
|
||||||
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
||||||
delayRequest();
|
BUS_DELAY;
|
||||||
LOG_DEBUG("Write Channel", ch, "->", value ? "True" : "False");
|
LOG_DEBUG("Write Channel", ch, "->", value ? "True" : "False");
|
||||||
return m_bus.writeCoil(m_address, REG_COILS + ch, value);
|
return m_bus.writeCoil(m_address, REG_COILS + ch, value);
|
||||||
}
|
}
|
||||||
@@ -47,7 +39,7 @@ const bool remoteIO::toggleOut(const channel_t ch)
|
|||||||
if (!m_initialized)
|
if (!m_initialized)
|
||||||
return false;
|
return false;
|
||||||
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
||||||
delayRequest();
|
BUS_DELAY;
|
||||||
std::vector<bool> value;
|
std::vector<bool> value;
|
||||||
if (!m_bus.readCoils(m_address, REG_COILS + ch, 1, value))
|
if (!m_bus.readCoils(m_address, REG_COILS + ch, 1, value))
|
||||||
return false;
|
return false;
|
||||||
@@ -60,7 +52,7 @@ const bool remoteIO::setOutPort(const std::vector<bool> values)
|
|||||||
if (!m_initialized)
|
if (!m_initialized)
|
||||||
return false;
|
return false;
|
||||||
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
||||||
delayRequest();
|
BUS_DELAY;
|
||||||
LOG_DEBUG("Write Port", CH_MAX);
|
LOG_DEBUG("Write Port", CH_MAX);
|
||||||
return m_bus.writeCoils(m_address, REG_COILS, values);
|
return m_bus.writeCoils(m_address, REG_COILS, values);
|
||||||
}
|
}
|
||||||
@@ -70,7 +62,7 @@ const bool remoteIO::getOut(const channel_t ch, bool &value)
|
|||||||
if (!m_initialized)
|
if (!m_initialized)
|
||||||
return false;
|
return false;
|
||||||
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
||||||
delayRequest();
|
BUS_DELAY;
|
||||||
std::vector<bool> values;
|
std::vector<bool> values;
|
||||||
if (!m_bus.readCoils(m_address, REG_COILS + ch, 1, values))
|
if (!m_bus.readCoils(m_address, REG_COILS + ch, 1, values))
|
||||||
return false;
|
return false;
|
||||||
@@ -84,7 +76,7 @@ const bool remoteIO::getOutPort(std::vector<bool> &values)
|
|||||||
if (!m_initialized)
|
if (!m_initialized)
|
||||||
return false;
|
return false;
|
||||||
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
||||||
delayRequest();
|
BUS_DELAY;
|
||||||
LOG_DEBUG("Read Port", CH_MAX);
|
LOG_DEBUG("Read Port", CH_MAX);
|
||||||
return m_bus.readCoils(m_address, REG_COILS, CH_MAX, values);
|
return m_bus.readCoils(m_address, REG_COILS, CH_MAX, values);
|
||||||
}
|
}
|
||||||
@@ -94,7 +86,7 @@ const bool remoteIO::getIn(const channel_t input, bool &value)
|
|||||||
if (!m_initialized)
|
if (!m_initialized)
|
||||||
return false;
|
return false;
|
||||||
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
||||||
delayRequest();
|
BUS_DELAY;
|
||||||
std::vector<bool> values;
|
std::vector<bool> values;
|
||||||
if (!m_bus.readInputs(m_address, REG_INPUT + input, 1, values))
|
if (!m_bus.readInputs(m_address, REG_INPUT + input, 1, values))
|
||||||
return false;
|
return false;
|
||||||
@@ -108,7 +100,7 @@ const bool remoteIO::getInPort(std::vector<bool> &values)
|
|||||||
if (!m_initialized)
|
if (!m_initialized)
|
||||||
return false;
|
return false;
|
||||||
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
std::lock_guard<std::mutex> lock(m_bus.getMutex());
|
||||||
delayRequest();
|
BUS_DELAY;
|
||||||
LOG_DEBUG("Read Inputs", CH_MAX);
|
LOG_DEBUG("Read Inputs", CH_MAX);
|
||||||
return m_bus.readInputs(m_address, REG_INPUT, CH_MAX, values);
|
return m_bus.readInputs(m_address, REG_INPUT, CH_MAX, values);
|
||||||
}
|
}
|
||||||
@@ -118,3 +110,5 @@ void remoteIO::resetAll(const bool value)
|
|||||||
LOG_DEBUG("Reset All ->", value ? "True" : "False");
|
LOG_DEBUG("Reset All ->", value ? "True" : "False");
|
||||||
m_bus.writeCoil(m_address, REG_ALLCOILS, value);
|
m_bus.writeCoil(m_address, REG_ALLCOILS, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef BUS_DELAY
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include <DebugLog.h>
|
#include <DebugLog.h>
|
||||||
#include <RS485_Driver.h>
|
#include <RS485_Driver.h>
|
||||||
|
#include <utils.h>
|
||||||
|
|
||||||
class remoteIO
|
class remoteIO
|
||||||
{
|
{
|
||||||
@@ -44,9 +45,6 @@ public:
|
|||||||
|
|
||||||
void resetAll(const bool value);
|
void resetAll(const bool value);
|
||||||
|
|
||||||
private:
|
|
||||||
void delayRequest();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_initialized;
|
bool m_initialized;
|
||||||
drivers::MODBUS &m_bus;
|
drivers::MODBUS &m_bus;
|
||||||
|
|||||||
Reference in New Issue
Block a user