Modbus TCP/IP

Hello community,

I would once again need your help. In fact, I want to connect Modbus TCP / IP gateway with an Anybus X-gateway - Modbus TCP Master / Client where I connected the network on Ethernet IP jack
the ethernet module enc28 on Modbus TCP socket
I wonder if it’s possible the link of Modbus TCP to recover the data on the analog inputs.

I configured the module enc28 using the following code:

 private static void InitializeNetwork()
         {
             Debug.Print("Initializing network...");
             NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
             if (interfaces != null && interfaces.Length > 0)
             {
                 NetworkInterface networkInterface = interfaces[0];
                 Boolean isDhcpWorked = false;

                 // dynamic IP address
                 if (networkInterface.IsDhcpEnabled == false) networkInterface.EnableDhcp();
                 // Wait for DHCP (on LWIP devices)
                 for (int i = 0; i < 5; i++)
                 {

                     networkInterface = NetworkInterface.GetAllNetworkInterfaces()[0];
                     if (networkInterface.IPAddress != "0.0.0.0")
                     {
                         isDhcpWorked = true;
                         break;
                     }

                     Debug.Print("Waiting for an IP Address...");
                     Thread.Sleep(1000);
                 }

                 if (Microsoft.SPOT.Hardware.SystemInfo.SystemID.SKU != 3)
                 {
                     if (isDhcpWorked == false)
                     {
                         // static IP address
                         networkInterface.EnableStaticIP("200.200.200.34", "255.255.255.0", "200.200.200.6");
                         networkInterface.EnableStaticDns(new[] { "200.200.200.1" });
                         Debug.Print("DHCP not enabled.");
                     }
                 }

                 Debug.Print("Network ready.");
                 Debug.Print("  IP Address: " + networkInterface.IPAddress);
                 Debug.Print("  Subnet Mask: " + networkInterface.SubnetMask);
                 Debug.Print("  Default Getway: " + networkInterface.GatewayAddress);
                 Debug.Print("  DNS Server: " + networkInterface.DnsAddresses[0]);
             }
             else
             {
                 Debug.Print("No network device found.");
             }
         }

I chose an IP address is not used

I was clear in my explanation ?

Not really :slight_smile: I did not understand the question.

@ Gus - I would like with the Modbus and module enc28 retrieve data on the analog inputs G120HDR and I do not know how to start ?

@ andre.m - Read data from analog inputs and display the data on the PC by transferring data via TCP / IP Modbus

@ andre.m - I added the project downloaded from the link you gave me in my project, is that right thing to do?

@ andre.m - you gave me a link where I could use the code share.

If I understand this code is used to implement a Modbus TCP, this is what I want.

I wish as described previously, read data from the analog inputs can then be displayed on the PC. This data transfer will be performed using the Modbus TCP network connection?

How should I use the download code?

Configure your system to read the analog inputs either periodically or when a Modbus request is received and store the result in a variable.

You need to look at the Modbus software and setup as a SLAVE. I am assuming the PC has Modbus Master software on it?

In the code, there will be a way to set the registers that the Modbus will use when it receives a request. You need to put them in either holding or status registers and also sort out the encoding.

A question springs to mind. How much knowledge of Modbus do you have?

You could use my Modbus implementation:
https://www.ghielectronics.com/community/codeshare/entry/880
It supports Modbus TCP and RTU as well as Master and slave.
Just click on the “Download latest version” to get the project.
If you click on the “Usage” link, you see some brief samples for each variant.

Using this, you do not need any knowledge about networking, and only limited knowledge of Modbus.
For Analog values you should use the InputRegisters functions.
By this 16 bit values are exchanged.
If you have more bits per value, you can split it over multiple registers.
Natively Modbus understands single bits values and 16 bit registers.

I’m currently working on an updated version, which I will post soon.
Hopefully I can manage to create a full set of samples as well.

Thank you for your answers!
I am currently studying TCP / IP Modbus trying to understand how my KNOWLEDGE is limited but I try to deepen my knowledge and experience.

I’ll try the code you suggested me

@ Reinhard Ostermeier - ModbusTcpInterface(Host)
The “Host” is the IP address?

IP address or host name.
But if you want to create a Modbus TCP device you need to do as follows:

// provide access to MyModbusDevice via TCP
 var device = new MyModbusDevice(248);
 val listener = ModbusTcpInterface.StartDeviceListener(device);
// ...
 listener.Dispose();

where MyModbusDevice looks like this:

// implement slave device
public class MyModbusDevice : ModbusDevice
{
    public MyModbusDevice(byte deviceAddress, object syncObject = null)
       : base(deviceAddress, syncObject)
    { }

    public MyModbusDevice(IModbusInterface intf, byte deviceAddress, object syncObject = null)
       : base(intf, deviceAddress, syncObject)
    { }

    protected override string OnGetDeviceIdentification(ModbusObjectId objectId)
    {
       switch (objectId)
       {
          case ModbusObjectId.VendorName:
             return "MeManufacturer";
          case ModbusObjectId.ProductCode:
             return "1";
          case ModbusObjectId.MajorMinorRevision:
             return "1.0";
          case ModbusObjectId.VendorUrl:
             return "http://www.MeManufacturer.org";
          case ModbusObjectId.ProductName:
             return "MyModbusDevice";
          case ModbusObjectId.ModelName:
             return "1";
          case ModbusObjectId.UserApplicationName:
             return "MyModbusApplication";
       }
       return null;
    }

    protected override ModbusConformityLevel GetConformityLevel()
    {
       return ModbusConformityLevel.Regular;
    }

    protected override ModbusErrorCode OnWriteSingleCoil(bool isBroadcast, ushort address, bool value)
    {
       if (false) // check address here
       {
          return ModbusErrorCode.IllegalDataAddress;
       }
       
       // set coil value here
       
       return ModbusErrorCode.NoError;
    }

    protected override ModbusErrorCode OnReadCoils(bool isBroadcast, ushort startAddress, ushort coilCount, byte[] coils)
    {
       if (false) // check coil count here
       {
          return ModbusErrorCode.IllegalDataValue;
       }
       if (false) // check address here
       {
          return ModbusErrorCode.IllegalDataAddress;
       }

       // write coil values into parameter coils here
       
       return ModbusErrorCode.NoError;
    }
    
    // override any On<ModusFunction> methods here
}

@ Reinhard Ostermeier - Yes that’s what I did but why 248?

Normaly there is only one device on a TCP Connection. The device is already identified by it’s IP address/host Name.
Since the “normal” device addresses range from 1 to 247, you use 248 for a TCP device.

The next Version of my Driver will contain an TCP/RTU Gateway.
This is a TCP Device connected with an RTU Master.
All device addresses between 1 and 247 will be redirected to the RTU bus (a SerialPort in fact).
248 is the TCP device itself.

@ Reinhard Ostermeier - Thank you for your help

@ Reinhard Ostermeier - You put “val listener” is really “val” and not “var”?

@ MVeloso4 - Most likely yes. This sample code was created by copy/paste + some additions typed directly into the submission editor.
I will created real working samples within my 3 week vacation starting next week (eventually :whistle: )

@ Reinhard Ostermeier - you know how to know the address associated with the analog input register?

You can lay out the addresses for your device as you wish.
You can also have a single address space for everything (coils, input pins, input registers and holding registers) or a separate address space for each one.
In fact the addresses does not need to be represented in real memory.
You can put a switch in the override of the MyModbusDevice class and return different values for each address, or read the analog input there directly.
You should look at the general Modbus spec, to get an idea how it was originally thought:

have a look at page 6 and 7.

@ Reinhard Ostermeier - Is it possible if you do not mind having a short example to see an analog input in G120HDR?
I have difficulty to see the operation