Examples |
This topic contains the following sections:
The following example tinyslave.cpp shows how to implement a small Modbus RTU slave:
// // @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.
The following example tcpslave.cpp shows how to implement a small Modbus/TCP slave:
// // @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.