Added mutex to MODBUS and I@c for mutithreading

This commit is contained in:
Emanuele Trabattoni
2025-07-14 11:29:16 +02:00
parent 7e02f3cef2
commit bdf3b9b41a
7 changed files with 26 additions and 16 deletions

BIN
docs/mi004700-i-e.pdf Normal file

Binary file not shown.

View File

@@ -24,7 +24,7 @@
namespace drivers
{
class Ethernet
class Ethernet : public ETHClass
{
public:

View File

@@ -3,21 +3,20 @@
namespace drivers
{
I2C::I2C()
I2C::I2C(): m_initialized(true)
{
Wire.begin(I2C_SDA_PIN, I2C_SCL_PIN);
isInitialized = true;
}
I2C::~I2C()
{
Wire.end();
isInitialized = true;
m_initialized = false;
}
const bool I2C::read(const uint8_t deviceAddr, const uint8_t deviceReg, const uint8_t len, std::vector<uint8_t> &data)
{
//busy.try_lock();
std::lock_guard<std::mutex> lock(m_mutex);
Wire.beginTransmission(deviceAddr);
Wire.write(deviceReg);
switch (Wire.endTransmission(true))
@@ -45,13 +44,12 @@ namespace drivers
{
data[i] = static_cast<uint8_t>(Wire.read());
}
//busy.unlock();
return true;
}
const bool I2C::write(const uint8_t deviceAddr, const uint8_t deviceReg, const std::vector<uint8_t> &data)
{
//busy.lock();
std::lock_guard<std::mutex> lock(m_mutex);
Wire.beginTransmission(deviceAddr);
Wire.write(deviceReg);
for (auto d : data)
@@ -73,7 +71,6 @@ namespace drivers
LOG_ERROR("Unknown Error");
return false;
}
//busy.unlock();
return true;
}

View File

@@ -14,16 +14,16 @@ namespace drivers
class I2C
{
private:
bool isInitialized = false;
//std::mutex busy;
public:
I2C(void);
~I2C(void);
const bool read(const uint8_t deviceAddr, const uint8_t deviceReg, const uint8_t len, std::vector<uint8_t> &data);
const bool write(const uint8_t deviceAddr, const uint8_t deviceReg, const std::vector<uint8_t> &data);
private:
bool m_initialized;
std::mutex m_mutex;
};
}

View File

@@ -71,6 +71,7 @@ namespace drivers
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;
std::lock_guard<std::mutex> lock(m_mutex);
LOG_DEBUG("Read coils: dev[", device, "], reg[", reg, "], num[", num, "]");
return readBinary(device, func, reg, num, coils);
}
@@ -79,6 +80,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;
std::lock_guard<std::mutex> lock(m_mutex);
LOG_DEBUG("Read multi inputs: dev[", device, "], reg[", reg, "], num[", num, "]");
return readBinary(device, func, reg, num, inputs);
}
@@ -87,6 +89,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;
std::lock_guard<std::mutex> lock(m_mutex);
LOG_DEBUG("Read multi holding registers: dev[", device, "], reg[", reg, "], num[", num, "]");
return readInteger(device, func, reg, num, values);
}
@@ -95,6 +98,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;
std::lock_guard<std::mutex> lock(m_mutex);
LOG_DEBUG("Read multi input registers: dev[", device, "], reg[", reg, "], num[", num, "]");
return readInteger(device, func, reg, num, values);
}
@@ -103,6 +107,7 @@ namespace drivers
const bool MODBUS::writeCoil(const uint8_t device, const uint16_t coil, const bool value)
{
constexpr uint8_t func = 0x05;
std::lock_guard<std::mutex> lock(m_mutex);
LOG_DEBUG("Write single coil: dev[", device, "], coil[", coil, "], value[", value ? "true" : "false", "]");
return writeBinary(device, func, coil, {value});
}
@@ -111,6 +116,7 @@ namespace drivers
const bool MODBUS::writeRegister(const uint8_t device, const uint16_t reg, const uint16_t value)
{
constexpr uint8_t func = 0x06;
std::lock_guard<std::mutex> lock(m_mutex);
LOG_DEBUG("Write single register: dev[", device, "], reg[", reg, "], value[", value, "]");
return writeInteger(device, func, reg, {value}, false);
}
@@ -119,6 +125,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;
std::lock_guard<std::mutex> lock(m_mutex);
LOG_DEBUG("Write multi coils: dev[", device, "], start[", coils, "], num[", values.size(), "]");
return writeBinary(device, func, coils, values);
}
@@ -127,6 +134,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;
std::lock_guard<std::mutex> lock(m_mutex);
LOG_DEBUG("Write multi registers: dev[", device, "], start[", reg, "], num[", values.size(), "]");
return writeInteger(device, func, reg, values, true);
}

View File

@@ -7,6 +7,7 @@
#include <HardwareSerial.h> // Reference the ESP32 built-in serial port library
#include <CRC16.h>
#include <memory>
#include <mutex>
namespace drivers
{
@@ -80,6 +81,7 @@ namespace drivers
private:
CRC16 m_crc;
std::mutex m_mutex;
const std::vector<uint8_t> singleRequest(const uint8_t device, const uint8_t func, const uint16_t reg, const uint16_t data);
const std::vector<uint8_t> multiRequest(const uint8_t device, const uint8_t func, const uint16_t reg, const uint16_t qty, const std::vector<uint8_t> &data);
const bool readBinary(const uint8_t device, const uint8_t func, const uint16_t reg, const uint16_t bits, std::vector<bool> &out);

View File

@@ -24,11 +24,14 @@ void callback(char *topic, uint8_t *payload, unsigned int length)
void myTask(void *mqtt)
{
while (true)
auto client = (PubSubClient *)(mqtt);
while (client->connected())
{
((PubSubClient *)(mqtt))->loop();
client->loop();
vTaskDelay(pdMS_TO_TICKS(100));
}
LOG_ERROR("Mqtt Loop Ended, client disconnected");
vTaskDelete(NULL); // delete the current task
};
/////////////// GLOBALS ///////////////
@@ -42,7 +45,7 @@ void loop()
{
const uint8_t tempBoardAddr(0xAA);
const uint8_t relayBoardAddr(0x01);
const uint8_t senecadAddr(0xBB);
const uint8_t senecaMeterAddr(0xBB);
const uint8_t baseRegister(0x00);
uint16_t k(0);
uint8_t ethRetries(0);
@@ -58,7 +61,7 @@ void loop()
delay(100);
auto io = digitalIO(i2c, bus, {relayBoardAddr});
delay(100);
auto seneca = drivers::S50140(bus, senecadAddr);
auto seneca = drivers::S50140(bus, senecaMeterAddr);
Network.onEvent([&eth](arduino_event_id_t event, arduino_event_info_t info)
{ eth.onEvent(event, info); });