• Libraries
  • Shop
  • Doc
  • Free Modbus
  • Support
  • Login
FieldTalk Modbus Slave Library for .NET
FieldTalk Modbus Slave Library for .NET
Introduction
What You should know about Modbus
Server Functions common to all Protocol Flavours
Serial Protocols
TCP/IP Protocols
Data Provider
Examples
Design Background
License
Namespaces
Support
Notices
Click or drag to resizeClick or drag to resize

Examples

This topic contains the following sections:

  • Serial Example
  • MODBUS/TCP Example

Serial Example

The following example tinyslave.cpp shows how to implement a small Modbus RTU slave:

C#
VB
C++
Copy
// 
// @file tinyslave.cs
// 
// A simple Modbus RTU slave program.
// 
// @if NOTICE
// 
// Copyright (c) proconX Pty Ltd. All rights reserved.
// 
// The following source file constitutes example program code and is
// intended merely to illustrate useful programming techniques.  The user
// is responsible for applying the code correctly.
// 
// THIS SOFTWARE IS PROVIDED BY PROCONX AND CONTRIBUTORS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PROCONX OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// 
// @endif
// 


using System;
using FieldTalk.Modbus.Slave;


class MyDatatable: MbusDataTableInterface
{
   private short[] localRegisters = new short[1000];
   private bool[] localCoils = new bool[1000];


   protected override bool readHoldingRegistersTable(Int32 startRef, Int16[] regArr)
   {
      Console.WriteLine("readHoldingRegisters from " + startRef + ", " + regArr.Length + " references");
      // Adjust Modbus reference counting from 1-based to 0-based
      startRef--;
      // Validate range
      if (startRef + regArr.Length > localRegisters.Length)
      {
         return false;
      }
      // Copy registers from local data array to Modbus
      for (int i = 0; i < regArr.Length; i++)
      {
         regArr[i] = localRegisters[startRef + i];
      }
      return true;
   }


   protected override bool writeHoldingRegistersTable(Int32 startRef, Int16[] regArr)
   {
      Console.WriteLine("writeHoldingRegisters from " + startRef + ", " + regArr.Length + " references");
      // Adjust Modbus reference counting from 1-based to 0-based
      startRef--;
      // Validate range
      if (startRef + regArr.Length > localRegisters.Length)
      {
         return false;
      }
      // Copy registers from Modbus to local data block
      for (int i = 0; i < regArr.Length; i++)
      {
         localRegisters[startRef + i] = regArr[i];
      }
      return true;
   }

}


class TcpSlaveApp
{
   private MbusRtuSlaveProtocol mbusServer = new MbusRtuSlaveProtocol();
   private MyDatatable dataTable = new MyDatatable();


   private void startupServer()
   {
      int result;

      result = mbusServer.addDataTable(1, dataTable); // Unit ID is 1
      if (result == BusProtocolErrors.FTALK_SUCCESS)
      {
         result = mbusServer.startupServer("COM1",
                                           19200, // Baudrate
                                           MbusSerialServerBase.SER_DATABITS_8,
                                           MbusSerialServerBase.SER_STOPBITS_1,
                                           MbusSerialServerBase.SER_PARITY_EVEN);
      }
      if (result != BusProtocolErrors.FTALK_SUCCESS)
      {
         Console.WriteLine(BusProtocolErrors.getBusProtocolErrorText(result));
         Environment.Exit(result);
      }
      Console.WriteLine("Modbus server started on serial interface " + mbusServer.portName);
   }


   private void shutdownServer()
   {
      mbusServer.shutdownServer();
   }


   private void runServer()
   {
      int result;

      do
      {
         result = mbusServer.serverLoop();
      } while (!(result != BusProtocolErrors.FTALK_SUCCESS));
      if (result != BusProtocolErrors.FTALK_SUCCESS)
      {
         Console.WriteLine(BusProtocolErrors.getBusProtocolErrorText(result));
      }
   }


   public static void Main()
   {
      TcpSlaveApp app = new TcpSlaveApp();
      app.startupServer();
      app.runServer();
      app.shutdownServer();
   }

}
'
' @file tinyslave.vb
'
' A simple Modbus RTU slave program.
'
' @if NOTICE
'
' Copyright (c) proconX Pty Ltd. All rights reserved.
'
' The following source file constitutes example program code and is
' intended merely to illustrate useful programming techniques.  The user
' is responsible for applying the code correctly.
'
' THIS SOFTWARE IS PROVIDED BY PROCONX AND CONTRIBUTORS ``AS IS'' AND ANY
' EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
' IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
' PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PROCONX OR CONTRIBUTORS BE
' LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
' CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
' SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
' BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
' WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
' OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
' ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'
' @endif
'


Imports System
Imports FieldTalk.Modbus.Slave
Imports FieldTalk.Modbus.Slave.BusProtocolErrors


'''
''' Data provider class
'''
Class MyDatatable
    Inherits MbusDataTableInterface

    Private localRegisters(1000) As Short


    Protected Overrides Function readHoldingRegistersTable(ByVal startRef As Int32, ByVal regArr() As Int16) As Boolean
        Dim i As Integer

        Console.WriteLine("readHoldingRegisters from " & startRef & ", " & regArr.Length & " references")
        ' Adjust Modbus reference counting from 1-based to 0-based
        startRef = startRef - 1
        ' Validate range
        If startRef + regArr.Length > localRegisters.Length Then
            Return False
        End If
        ' Copy registers from local data array to Modbus
        For i = 0 To regArr.Length - 1
            regArr(i) = localRegisters(startRef + i)
        Next
        Return True

    End Function


    Protected Overrides Function writeHoldingRegistersTable(ByVal startRef As Int32, ByVal regArr() As Int16) As Boolean
        Dim i As Integer

        Console.WriteLine("writeHoldingRegisters from " & startRef & ", " & regArr.Length & " references")
        ' Adjust Modbus reference counting from 1-based to 0-based
        startRef = startRef - 1
        ' Validate range
        If startRef + regArr.Length > localRegisters.Length Then
            Return False
        End If
        ' Copy registers from Modbus to local data block
        For i = 0 To regArr.Length - 1
            localRegisters(startRef + i) = regArr(i)
        Next
        Return True
    End Function

End Class


'''
''' Slave thread
'''
Class TinySlaveApp

    Private mbusServer As MbusRtuSlaveProtocol = New MbusRtuSlaveProtocol
    Private dataTable As MyDatatable = New MyDatatable

    '''
    ''' Starts up server
    '''
    Private Sub startupServer()
        Dim result As Integer
        result = mbusServer.addDataTable(1, dataTable) ' Unit ID is 1
        If result = FTALK_SUCCESS Then
            result = mbusServer.startupServer("COM1:", _
                                               19200, _
                                               MbusSerialServerBase.SER_DATABITS_8, _
                                               MbusSerialServerBase.SER_STOPBITS_1, _
                                               MbusSerialServerBase.SER_PARITY_EVEN)
        End If
        If result <> FTALK_SUCCESS Then
            Console.WriteLine(getBusProtocolErrorText(result))
            Environment.Exit(result)
        End If
        Console.WriteLine("Modbus server started on serial interface " & mbusServer.portName)
    End Sub


    '''
    ''' Shutdown server
    '''
    Private Sub shutdownServer()
        mbusServer.shutdownServer()
    End Sub


    '''
    ''' Run server
    '''
    Private Sub runServer()
        Dim result As Integer
        Do
            result = mbusServer.serverLoop()
        Loop Until result <> FTALK_SUCCESS
        If result <> FTALK_SUCCESS Then
            Console.WriteLine(getBusProtocolErrorText(result))
        End If
    End Sub


    '''
    '''  Main function
    '''
    Public Shared Sub Main()
        Dim app As TinySlaveApp = New TinySlaveApp
        app.startupServer()
        app.runServer()
        app.shutdownServer()
    End Sub

End Class

No code example is currently available or this language may not be supported.

MODBUS/TCP Example

The following example tcpslave.cpp shows how to implement a small Modbus/TCP slave:

C#
VB
C++
Copy
// 
// @file tcpslave.cs
// 
// A simple console based example using FieldTalk in Modbus/TCP slave mode

// @if NOTICE
// 
// Copyright (c) proconX Pty Ltd. All rights reserved.
// 
// The following source file constitutes example program code and is
// intended merely to illustrate useful programming techniques.  The user
// is responsible for applying the code correctly.
// 
// THIS SOFTWARE IS PROVIDED BY PROCONX AND CONTRIBUTORS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PROCONX OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// 
// @endif
// 


using System;
using FieldTalk.Modbus.Slave;

class MyDatatable: MbusDataTableInterface
{
    private short[] localRegisters = new short[1000];
    private bool[] localCoils = new bool[1000];

    protected override bool readHoldingRegistersTable(Int32 startRef, Int16[] regArr)
    {
        MasterInfo? masterInfo = getMasterInfo(); // Retrieve optionally master meta data
        Console.WriteLine("readHoldingRegisters from {0}, {1} references using {2} by slave {3} via {4}", startRef, regArr.Length, masterInfo?.protocol, masterInfo?.slaveAddr, masterInfo?.connection);

        // Adjust Modbus reference counting from 1-based to 0-based
        startRef--;
        // Validate range
        if (startRef + regArr.Length > localRegisters.Length)
        {
            return false;
        }
        // Copy registers from local data array to Modbus
        for (int i = 0; i < regArr.Length; i++)
        {
            regArr[i] = localRegisters[startRef + i];
        }
        return true;
    }


#if ENABLE_INPUT_REGS // Set to true if input registers shall be supported
    protected override bool readInputRegistersTable(Int32 startRef, Int16[] regArr)
    {
        Console.WriteLine("readInputRegistersTable from " + startRef + ", " + regArr.Length + " references");
        // Adjust Modbus reference counting from 1-based to 0-based
        startRef--;
        // Validate range
        if (startRef + regArr.Length > localRegisters.Length)
        {
            return false;
        }
        // Copy registers from local data array to Modbus
        for (int i = 0; i < regArr.Length; i++)
        {
            regArr[i] = localRegisters[startRef + i];
        }
        return true;
    }
#endif


    protected override bool writeHoldingRegistersTable(Int32 startRef, Int16[] regArr)
    {
        Console.WriteLine("writeHoldingRegisters from " + startRef + ", " + regArr.Length + " references");
        // Adjust Modbus reference counting from 1-based to 0-based
        startRef--;
        // Validate range
        if (startRef + regArr.Length > localRegisters.Length)
        {
            return false;
        }
        // Copy registers from Modbus to local data block
        for (int i = 0; i < regArr.Length; i++)
        {
            localRegisters[startRef + i] = regArr[i];
        }
        return true;
    }


    protected override bool readCoilsTable(Int32 startRef, bool[] bitArr)
    {
        Console.WriteLine("readCoilsTable from " + startRef + ", " + bitArr.Length + " references");
        // Adjust Modbus reference counting from 1-based to 0-based
        startRef--;
        // Validate range
        if (startRef + bitArr.Length > localCoils.Length)
        {
            return false;
        }
        // Copy registers from local data array to Modbus
        for (int i = 0; i < bitArr.Length; i++)
        {
            bitArr[i] = localCoils[startRef + i];
        }
        return true;
    }


    protected override bool writeCoilsTable(Int32 startRef, bool[] bitArr)
    {
        Console.WriteLine("writeCoilsTable from " + startRef + ", " + bitArr.Length + " references");
        // Adjust Modbus reference counting from 1-based to 0-based
        startRef--;
        // Validate range
        if (startRef + bitArr.Length > localCoils.Length)
        {
            return false;
        }
        // Copy registers from Modbus to local data block
        for (int i = 0; i < bitArr.Length; i++)
        {
            localCoils[startRef + i] = bitArr[i];
        }
        return true;
    }


#if ENABLE_ENRON_REGS // Set to true if Enron mode is required   
    private Int32[] enronData = new Int32[4000];

    protected override bool readEnronRegistersTable(int startRef, Int32[] regArr)
    {
        Console.WriteLine("readEnronRegistersTable from " + startRef + ", " + regArr.Length + " references");
        // Adjust Modbus reference counting from 1-based to 0-based
        startRef--;

        // 
        // Validate start address range
        // Note: In this example, we have 2000 references at 5000 and 2000 references at 7000.
        // 
        if ((startRef < 5000) || (startRef >= 9000))
            return false;
        else
            startRef -=5000;
        if (startRef + regArr.Length > enronData.Length)
        {
            return false;
        }
        // Copy registers from local data array to Modbus
        for (int i = 0; i < regArr.Length; i++)
        {
            regArr[i] = enronData[startRef + i];
        }
        return true;
    }


    protected override bool writeEnronRegistersTable(Int32 startRef, Int32[] regArr)
    {
        Console.WriteLine("writeEnronRegistersTable from " + startRef + ", " + regArr.Length + " references");
        // Adjust Modbus reference counting from 1-based to 0-based
        startRef--;

        // 
        // Validate start address range
        // Note: In this example, we have 2000 references at 5000 and 2000 references at 7000.
        // 
        if ((startRef < 5000) || (startRef >= 9000))
            return false;
        else
            startRef -= 5000;
        if (startRef + regArr.Length > enronData.Length)
        {
            return false;
        }
        // Copy registers from Modbus to local data block
        for (int i = 0; i < regArr.Length; i++)
        {
            enronData[startRef + i] = regArr[i];
        }
        return true;
    }
#endif



}


class TcpSlaveApp
{
    private MbusTcpSlaveProtocol mbusServer = new MbusTcpSlaveProtocol();
    private MyDatatable dataTable = new MyDatatable();


    private void startupServer()
    {
       int result;

       result = mbusServer.addDataTable(1, dataTable); // Unit ID is 1
       if (result == BusProtocolErrors.FTALK_SUCCESS)
       {
           result = mbusServer.startupServer();
       }
       if (result != BusProtocolErrors.FTALK_SUCCESS)
       {
           Console.WriteLine(BusProtocolErrors.getBusProtocolErrorText(result));
           Environment.Exit(result);
       }
       Console.WriteLine("Modbus server started on TCP interface.");
    }


    private void shutdownServer()
    {
       mbusServer.shutdownServer();
   }


    private void runServer()
    {
       int result;

       do
       {
           result = mbusServer.serverLoop();
       } while (!(result != BusProtocolErrors.FTALK_SUCCESS));
       if (result != BusProtocolErrors.FTALK_SUCCESS)
       {
           Console.WriteLine(BusProtocolErrors.getBusProtocolErrorText(result));
       }
    }


    public static void Main()
    {
        TcpSlaveApp app = new TcpSlaveApp();
        app.startupServer();
        app.runServer();
        app.shutdownServer();
    }

}
'
' @file tcpslave.vb
'
' A simple console based example using FieldTalk in Modbus/TCP slave mode
'
' @if NOTICE
'
' Copyright (c) proconX Pty Ltd. All rights reserved.
'
' The following source file constitutes example program code and is
' intended merely to illustrate useful programming techniques.  The user
' is responsible for applying the code correctly.
'
' THIS SOFTWARE IS PROVIDED BY PROCONX AND CONTRIBUTORS ``AS IS'' AND ANY
' EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
' IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
' PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PROCONX OR CONTRIBUTORS BE
' LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
' CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
' SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
' BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
' WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
' OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
' ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'
' @endif
'


Imports System
Imports FieldTalk.Modbus.Slave
Imports FieldTalk.Modbus.Slave.BusProtocolErrors


'''
''' Data provider class
'''
Class MyDatatable
    Inherits MbusDataTableInterface

    Private localRegisters(1000) As Short


    Protected Overrides Function readHoldingRegistersTable(ByVal startRef As Int32, ByVal regArr() As Int16) As Boolean
        Dim i As Integer

        Console.WriteLine("readHoldingRegisters from " & startRef & ", " & regArr.Length & " references")
        ' Adjust Modbus reference counting from 1-based to 0-based
        startRef = startRef - 1
        ' Validate range
        If startRef + regArr.Length > localRegisters.Length Then
            Return False
        End If
        ' Copy registers from local data array to Modbus
        For i = 0 To regArr.Length - 1
            regArr(i) = localRegisters(startRef + i)
        Next
        Return True

    End Function


    Protected Overrides Function writeHoldingRegistersTable(ByVal startRef As Int32, ByVal regArr() As Int16) As Boolean
        Dim i As Integer
        Console.WriteLine("writeHoldingRegisters from " & startRef & ", " & regArr.Length & " references")
        ' Adjust Modbus reference counting from 1-based to 0-based
        startRef = startRef - 1
        ' Validate range
        If startRef + regArr.Length > localRegisters.Length Then
            Return False
        End If
        ' Copy registers from Modbus to local data block
        For i = 0 To regArr.Length - 1
            localRegisters(startRef + i) = regArr(i)
        Next
        Return True
    End Function

End Class


'''
''' Slave thread
'''
Class TcpSlaveApp

    Private mbusServer As MbusTcpSlaveProtocol = New MbusTcpSlaveProtocol
    Private dataTable As MyDatatable = New MyDatatable

    '''
    ''' Starts up server
    '''
    Private Sub startupServer()
        Dim result As Integer
        result = mbusServer.addDataTable(1, dataTable) ' Unit ID is 1
        If result = FTALK_SUCCESS Then
            result = mbusServer.startupServer()
        End If
        If result <> FTALK_SUCCESS Then
            Console.WriteLine(getBusProtocolErrorText(result))
            Environment.Exit(result)
        End If
        Console.WriteLine("Modbus server started on TCP interface.")
    End Sub


    '''
    ''' Shutdown server
    '''
    Private Sub shutdownServer()
        mbusServer.shutdownServer()
    End Sub


    '''
    ''' Run server
    '''
    Private Sub runServer()
        Dim result As Integer
        Do
            result = mbusServer.serverLoop()
        Loop Until result <> FTALK_SUCCESS
        If result <> FTALK_SUCCESS Then
            Console.WriteLine(getBusProtocolErrorText(result))
        End If
    End Sub


    '''
    '''  Main function
    '''
    Public Shared Sub Main()
        Dim app As TcpSlaveApp = New TcpSlaveApp
        app.startupServer()
        app.runServer()
        app.shutdownServer()
    End Sub

End Class

No code example is currently available or this language may not be supported.

FieldTalk Modbus Slave Library for .NET
Library version 2.11.0
Speak to the Experts
Modbus Organization Member logo

We are member of the Modbus Organization, Inc.

Buy with Confidence
30-day money back guarantee All our FieldTalk web sales are backed by a 30-day Money Back Guarantee.
We Accept
Bank VISA MasterCard PayPal
Customer Info
  • Info & Contact
  • Customer Login
  • Terms of Service
  • Terms of Sale
  • Privacy Policy
© 2005-2025 proconX Pty Ltd. All rights reserved. proconX and FieldTalk are trademarks of proconX Pty Ltd.
All other trademarks and registered trademarks appearing on www.modbusdriver.com are the property of their respective owners.