Skip to main content
added 2503 characters in body
Source Link

Here is the code snippet:

#include <fmt.h>
#include <P1AM.h>
#include <Ethernet.h>
#include <MQTT.h>
#include <ArduinoModbus.h>

using namespace std;

#define HOST_NAME "WIZnet"
uint8_t macPLC[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
uint8_t ipPLC[] = {192, 168, 0, 41};  
uint8_t ipModbus[] = {192, 168, 0, 43};  
char    ipMQTT[] = "192.168.0.42";
int     unitID = 98;

EthernetClient ethernet;
MQTTClient mqtt;
ModbusTCPClient modbus(ethernet);
int n = 0;

void messageReceived(MQTTClient *client, char topic[], char bytes[], int length) {
  if (length == 8) {
    int32_t commandID;
    float   commandArg;

    memcpy(&commandID, &bytes[0], sizeof(commandID));
    memcpy(&commandArg, &bytes[4], sizeof(commandArg));

    Serial.println(fmt::format("{} {}", commandID, commandArg).c_str());
  }
  else
    Serial.println("wrong length!!!");
}


void servoSetup() {
  modbus.coilWrite(unitID, 0x00C, 1);
}


void setup(){ // the setup routine runs once:
  P1.configWD(10000, 1);
  P1.startWD();
  Serial.begin(115200);  //initialize serial communication at 115200 bits per second 

  while (!P1.init()) 
    delay(1); //Wait for Modules to Sign on   
  
  Ethernet.begin(macPLC, ipPLC);
  mqtt.begin(ipMQTT, ethernet);
  modbus.setTimeout(500);

  if (!modbus.begin(ipModbus, 502)) 
    Serial.println("Failed to start Modbus TCP client!");
  else
    Serial.println("Connected to Modbus TCP client.");

  P1.petWD();

  while (!mqtt.connect(ipMQTT)) {
    Serial.print(".");
    delay(1000);
  }

  Serial.println("\nConnected to MQTT broker.");
  mqtt.subscribe("plc", 2);
  mqtt.onMessageAdvanced(messageReceived);
  servoSetup();

  delay(2000);
}


void loop() {
  P1.petWD();
  Serial.println(mqtt.loop());
  Serial.println(n++);
  int addr = 0x2407;

  if (!modbus.holdingRegisterWrite(unitID, addr, n)) 
    Serial.println(fmt::format("Modbus write failed: {}", modbus.lastError()).c_str());

  delay(1000);
  if (auto result = modbus.holdingRegisterRead(unitID, addr); result < 0) 
    Serial.println(fmt::format("Modbus read failed: {}", modbus.lastError()).c_str());
  else
    Serial.println(fmt::format("holdingRegisterRead: {}", result).c_str());
  delay(1000);
}

In this case, Modbus-TCP writes and reads have no effect, mqtt.loop() returns 0 and messageReceived() callback is not called. If I comment out MQTT or Modbus-TCP client, the code behaves as expected.


Here is the code snippet:

#include <fmt.h>
#include <P1AM.h>
#include <Ethernet.h>
#include <MQTT.h>
#include <ArduinoModbus.h>

using namespace std;

#define HOST_NAME "WIZnet"
uint8_t macPLC[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
uint8_t ipPLC[] = {192, 168, 0, 41};  
uint8_t ipModbus[] = {192, 168, 0, 43};  
char    ipMQTT[] = "192.168.0.42";
int     unitID = 98;

EthernetClient ethernet;
MQTTClient mqtt;
ModbusTCPClient modbus(ethernet);
int n = 0;

void messageReceived(MQTTClient *client, char topic[], char bytes[], int length) {
  if (length == 8) {
    int32_t commandID;
    float   commandArg;

    memcpy(&commandID, &bytes[0], sizeof(commandID));
    memcpy(&commandArg, &bytes[4], sizeof(commandArg));

    Serial.println(fmt::format("{} {}", commandID, commandArg).c_str());
  }
  else
    Serial.println("wrong length!!!");
}


void servoSetup() {
  modbus.coilWrite(unitID, 0x00C, 1);
}


void setup(){ // the setup routine runs once:
  P1.configWD(10000, 1);
  P1.startWD();
  Serial.begin(115200);  //initialize serial communication at 115200 bits per second 

  while (!P1.init()) 
    delay(1); //Wait for Modules to Sign on   
  
  Ethernet.begin(macPLC, ipPLC);
  mqtt.begin(ipMQTT, ethernet);
  modbus.setTimeout(500);

  if (!modbus.begin(ipModbus, 502)) 
    Serial.println("Failed to start Modbus TCP client!");
  else
    Serial.println("Connected to Modbus TCP client.");

  P1.petWD();

  while (!mqtt.connect(ipMQTT)) {
    Serial.print(".");
    delay(1000);
  }

  Serial.println("\nConnected to MQTT broker.");
  mqtt.subscribe("plc", 2);
  mqtt.onMessageAdvanced(messageReceived);
  servoSetup();

  delay(2000);
}


void loop() {
  P1.petWD();
  Serial.println(mqtt.loop());
  Serial.println(n++);
  int addr = 0x2407;

  if (!modbus.holdingRegisterWrite(unitID, addr, n)) 
    Serial.println(fmt::format("Modbus write failed: {}", modbus.lastError()).c_str());

  delay(1000);
  if (auto result = modbus.holdingRegisterRead(unitID, addr); result < 0) 
    Serial.println(fmt::format("Modbus read failed: {}", modbus.lastError()).c_str());
  else
    Serial.println(fmt::format("holdingRegisterRead: {}", result).c_str());
  delay(1000);
}

In this case, Modbus-TCP writes and reads have no effect, mqtt.loop() returns 0 and messageReceived() callback is not called. If I comment out MQTT or Modbus-TCP client, the code behaves as expected.

Source Link

How to make MQTT and ArduinoModbus libraries working on the same Ethernet port?

I have a SAMD51P20 based Arduino PLC with WIZnet W5500 based Ethernet shield. I'm using these libraries:

#include <Ethernet.h>
#include <MQTT.h>
#include <ArduinoModbus.h>

MQTT and Modbus-TCP clients run fine individually, but running them at the same time creates problems with both of them.

Is there a software solution to this problem, e.g. using separate sockets for MQTT and Modbus-TCP. WIZnet W5500 has 8 sockets available, but I don't see an API to select a socket for MQTT and Modbus-TCP client.

If not software, is there a hardware solution?