improved bus wait with raii class that updates last access
This commit is contained in:
@@ -3,8 +3,11 @@
|
||||
#include <cstring>
|
||||
#include <endian.h>
|
||||
|
||||
#include <busdelay.h>
|
||||
#include "utils.h"
|
||||
|
||||
#define BUS_DELAY drivers::BusDelay(m_lastAccess, c_minDelay, "MODBUS")
|
||||
|
||||
namespace drivers
|
||||
{
|
||||
|
||||
@@ -80,26 +83,11 @@ namespace drivers
|
||||
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
|
||||
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;
|
||||
delayAccess(device);
|
||||
LOG_DEBUG("Read coils: dev[", device, "], reg[", reg, "], num[", num, "]");
|
||||
LOG_DEBUG("Read coils: dev[", printHex(device).c_str(), "], reg[", printHex(reg).c_str(), "], num[", num, "]");
|
||||
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)
|
||||
{
|
||||
constexpr uint8_t func = 0x02;
|
||||
delayAccess(device);
|
||||
LOG_DEBUG("Read multi inputs: dev[", device, "], reg[", reg, "], num[", num, "]");
|
||||
LOG_DEBUG("Read multi inputs: dev[", printHex(device).c_str(), "], reg[", printHex(reg).c_str(), "], num[", num, "]");
|
||||
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)
|
||||
{
|
||||
constexpr uint8_t func = 0x03;
|
||||
delayAccess(device);
|
||||
LOG_DEBUG("Read multi holding registers: dev[", device, "], reg[", reg, "], num[", num, "]");
|
||||
LOG_DEBUG("Read multi holding registers: dev[", printHex(device).c_str(), "], reg[", printHex(reg).c_str(), "], num[", num, "]");
|
||||
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)
|
||||
{
|
||||
constexpr uint8_t func = 0x04;
|
||||
delayAccess(device);
|
||||
LOG_DEBUG("Read multi input registers: dev[", device, "], reg[", reg, "], num[", num, "]");
|
||||
LOG_DEBUG("Read multi input registers: dev[", printHex(device).c_str(), "], reg[", printHex(reg).c_str(), "], num[", num, "]");
|
||||
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)
|
||||
{
|
||||
constexpr uint8_t func = 0x05;
|
||||
delayAccess(device);
|
||||
LOG_DEBUG("Write single coil: dev[", device, "], coil[", coil, "], value[", value ? "true" : "false", "]");
|
||||
LOG_DEBUG("Write single coil: dev[", printHex(device).c_str(), "], coil[", printHex(coil).c_str(), "], value[", value ? "true" : "false", "]");
|
||||
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)
|
||||
{
|
||||
constexpr uint8_t func = 0x06;
|
||||
delayAccess(device);
|
||||
LOG_DEBUG("Write single register: dev[", device, "], reg[", reg, "], value[", value, "]");
|
||||
LOG_DEBUG("Write single register: dev[", printHex(device).c_str(), "], reg[", printHex(reg).c_str(), "], value[", value, "]");
|
||||
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)
|
||||
{
|
||||
constexpr uint8_t func = 0x0F;
|
||||
delayAccess(device);
|
||||
LOG_DEBUG("Write multi coils: dev[", device, "], start[", coils, "], num[", values.size(), "]");
|
||||
LOG_DEBUG("Write multi coils: dev[", printHex(device).c_str(), "], start[", printHex(coils).c_str(), "], num[", values.size(), "]");
|
||||
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)
|
||||
{
|
||||
constexpr uint8_t func = 0x10;
|
||||
delayAccess(device);
|
||||
LOG_DEBUG("Write multi registers: dev[", device, "], start[", reg, "], num[", values.size(), "]");
|
||||
LOG_DEBUG("Write multi registers: dev[", printHex(device).c_str(), "], start[", printHex(reg).c_str(), "], num[", values.size(), "]");
|
||||
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)
|
||||
{
|
||||
// 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)))
|
||||
{
|
||||
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)
|
||||
{
|
||||
// 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)))
|
||||
{
|
||||
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)
|
||||
{
|
||||
// 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());
|
||||
std::vector<uint8_t> bitsOut;
|
||||
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)
|
||||
{
|
||||
// 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());
|
||||
if (!multi)
|
||||
{
|
||||
@@ -439,10 +448,12 @@ namespace drivers
|
||||
// verify crc code
|
||||
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 true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#undef BUS_DELAY
|
||||
|
||||
Reference in New Issue
Block a user