Running a setup with a Modbus server running alongside the cloud connection. Cloud connected via WiFi, Modbus running on the Ethernet(Static IP address with gateway set to 0.0.0.0 all seems to work well.
Clear the WiFi credentials and Ethernet still on static with gateway and DNS configured, cloud connection to Particle works but the Modbus server seems stuck, PLC not reading data from it. Debug looks like the request not coming in or same request gets repeated sporadically.
Any suggestions on why this setup won't work but using the two seperate interfaces will?
Also seen problems with Modbus running on Ethernet(Static IP address 0.0.0.0 gateway) and trying to run another TCPClient application on WiFi alongside cloud, the two TCP applications seem to fight with each other even though in completely different contexts in the firmware.
That should work as long as the Ethernet has access to both the local Modbus TCP devices and the gateway to the Internet AND the gateway has a route to the Modbus TCP devices on the LAN.
In the situation where the gateway is set, it not only provides a route to the Internet, it also provides the route to the other nodes on the LAN, so the gateway needs to be able to route to the Modbus TCP devices.
When you don't have a gateway set, ARP is used to locate the devices on the same physical LAN, but there's no way to use both ARP and gateway.
I have a very similar setup with the exception of using a Boron and isolated LAN (GW = 0,0,0,0) and have seen the documentation here (TCPServer | Reference | Particle) saying TCPServer isn't supported on cellular. If the same situation exists where the Ethernet has a local LAN connection and we wish to connect to Particle through the Cellular connection. Can this also work if the TCPServer is used with only the Ethernet interface? We are seeing an established connection (SYN, SYN/ACK, MODBUS application request) but no response on the request. Wondering if it's a routing issue of some kind, or whether the problem lies in the modbus server implementation. In your response @rickkas7 , why did you say the ethernet needed access to the internet gateway? If the OP's Wifi was being used for Particle I'm trying to understand that piece. Is there a modification needed to set this up on a Boron? Can I force TCPServer to somehow use the Ethernet interface for traffic?
@GJMorrison Are you using the ArduinoModbus library for the server? Did you need to port it to get some communication working with Particle? I'm wondering if the issue on our side might be just in the server implementation. I tried stopping cellular in MANUAL mode and I still have the same issue with the TCP established but lack of application response.
You can use an isolated Ethernet with the gateway set to 0.0.0.0 to access devices on an isolated LAN. You can still access the cloud via Wi-Fi or cellular at the same time using TCPClient to access devices on the isolated Ethernet with Device OS 5.3.0 and later.
The less common situation that will cause problems is if the Ethernet is partially isolated. In the case where the Ethernet LAN does have a gateway to the Internet, but the Modbus TCP devices are not configured to use it, so they cannot access the Internet. In this case, the Particle device would need to have a gateway configured to get access to the cloud over Ethernet, but once you do that, you can no longer see the Modbus TCP devices because it will no longer do ARP to find them, but the gateway does not know how to reach them either.
If you have a fully configured Ethernet LAN with a gateway and all devices are configured to use it, you can then access both the Modbus TCP devices and the cloud via the Ethernet LAN.
Thanks for the clarification, Rick. Would situation #2 arise in a situation where there is an Ethernet LAN gateway which is not connected to the. internet, but another say, corporately managed network?
We have it working now. I think in our case we're following the first scenario in @rickkas7 's post. At first we were using the ArduinoModbus library, but have shifted to our own implementation, I think we had hit some kind of poor handling on the registers being read. I implemented the Read Holding Registers functionality in our code and used the following structure to set everything up (this is puedo-code to illustrate the chain of events for anyone else that stumbles on this):
//Before setup()
SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(MANUAL);
TCPServer server = TCPServer(502);
TCPClient client;
//Our own library for handling the TCP traffic
MyModbus modbus;
//in setup()
System.enableFeature(FEATURE_ETHERNET_DETECTION);
Cellular.off();
Ethernet.on();
Ethernet.setConfig(NetworkInterfaceConfig()
.source(NetworkInterfaceConfigSource::STATIC, AF_INET)
.address({192,168,1,99}, {255,255,255,0})
.gateway(SockAddr({0,0,0,0}))
);
Ethernet.connect();
Cellular.on();
waitFor(Cellular.isOn, 2000);
Cellular.connect();
waitFor(Cellular.ready, 30000);
server.begin();
Particle.connect();
//in loop
// Don't know if we really need this next line but it was added as we debugged the comms, might go away later
if (!client) client = server.available();
if (client){
if (client.connected()){
if (client.available()) {
modbus.handleRequest();
}
} else {
client = server.available();
}
}
Following this we're getting good MODBUS/TCP request/response on the Ethernet interface with a valid particle cloud interface over cellular. This follows the documented example here: TCPServer | Reference | Particle but everything started working better once we got rid of the off-the-shelf Arduino MODBUS library and created our own solution.
Having more problems with the Modbus setup.
Device starts up and the modbus works on ethernet and then when the wifi connects it stops working.
Setup is:
In the loop:
if (!(modbus_client.connected())) {
modbus_client = modbus_server.available();
Log.info("---------------------------Client Connect to Server");
}
This gets the modbus running OK.
After the wifi connects modbus_client.status() and modbus_client.status() both return 0 all the time.
I'm not positive, but I believe you need to specify Ethernet as the interface for TCPClient and TCPServer. Once the WiFi interface is up for the cloud connection, it will be the default interface, and I presume you can't reach the Modbus clients over Wi-Fi.
The TCPClient connect call would need to be modified to use the optional third parameter:
// TCPClient
virtual int connect(IPAddress ip, uint16_t port, network_interface_t=0);
The TCPServer is easier because it goes in the constructor:
Also note that any time the Ethernet reconnects you need to call the TCPServer begin again; it won't automatically resume listening. This is also true for WiFi. You can do this by monitoring the state of Ethernet.ready() and when it becomes unready then ready again, then you need to begin() again.
Also where's the code that implements Modbus TCP? The nanoMODBUS library only seems to implement the generic Modbus protocol and I didn't see anything that implements Particle/Arduino TCP calls for Modbus TCP.
Modbus server is working initially with:
TCPServer modbus_server = TCPServer(502,NETWORK_INTERFACE_ETHERNET);
TCPClient modbus_client;
and then
if (!(modbus_client.connected())) {
modbus_client = modbus_server.available();
}
to connect the modbus client to it.
I have WiFi.prefer(); before the Particle.connect(); so that cloud goes out the wifi.
Still after WiFi connects the modbus tcp client stalls, getting the same packet for a bit then just stops.
I am detecting the wifi connect and trying:
modbus_client.stop();
modbus_server.stop();
delay(1000);
modbus_server.begin();
after that the:
if (!(modbus_client.connected())) {
modbus_client = modbus_server.available();
}
code keeps executing but the modbus_client does not seem to connect again.
How can I tell if it is the tcp server or the tcp client at fault?
Seems I had a networking issue, both the wifi and the ethernet were on the same subnet even thought the ethernet network is isolated, once the wifi connected it must of been having routing issues. Changed the adresses on the Ethernet and it all working now.