0

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?


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.

4
  • What kind of problem? The 3-line of code doesn't tell us anything. You need to elaborate more on how you create the client for each connection? Commented Jun 25, 2024 at 7:37
  • @hcheung I posted the full test code. Commented Jun 25, 2024 at 8:26
  • 1
    ModbusTCPClient modbus(ethernet); and mqtt.begin(ipMQTT, ethernet);, you are sharing the same Ethernet client for two services. Create a separate client instance for each service. Commented Jun 25, 2024 at 8:33
  • @hcheung Thank you for looking into it. Commented Jun 25, 2024 at 9:17

1 Answer 1

1

There is no API to set the count of sockets used in the Ethernet library.

The MAX_SOCK_NUM is set in Ethernet.h based on available RAM.

#if defined(RAMEND) && defined(RAMSTART) && ((RAMEND - RAMSTART) <= 2048)
#define MAX_SOCK_NUM 4
#else
#define MAX_SOCK_NUM 8
#endif

So on SAMD51 you have 8 sockets available. Your problem with MQTT and Modbus TCP is elsewhere.

btw. the W5100 can handle only 4 sockets, but that is constrained at runtime.


EDIT: In your sketch you use the same EthernetClient for both libraries. Use two separate EthernetClient objects.

EthernetClient ethernet;
EthernetClient modbusClient;
MQTTClient mqtt;
ModbusTCPClient modbus(modbusClient);
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.