User Tools

Site Tools

한국어

cuwin:creating_a_cuwin_modbus_rtu_master_with_nmodbus:index

Creating a CUWIN Modbus RTU Master with NModbus

In this document we'll use the CUWIN as a Modbus master, and a CUBLOC-based MSB612RA-DC as a Modbus slave.

Create the Modbus Slave

Configure the serial settings in MSB Logic.

Nothing else is needed in Ladder Logic except and ENDing rung.

Connecting the CUWIN to the MSB612RA-DC

For this exercise we will use the CUWIN CWV070 as the Modbus master.

Connect the CUWIN's RS-232 COM1 port to the MSB612RA-DC RS-232 Ch1 port.

Create the Modbus Master

NModbus

NModbus is a free and open source implementation of the Modbus protocol for the .Net Framework and .Net Compact Framework. It is currently hosted at https://code.google.com/p/nmodbus/ but there are also other forks on GitHub.

Download the NModbus binaries.

After downloading and extracting the NModbus binaries from the repository, there will be two folders inside the “bin” folder: net and netcf. net is for the .Net Framework, and netcf is for the .Net Compact Framework. The CUWIN is a .Net Compact Framework device, so netcf is the appropriate folder.

Programming the CUWIN

Add a reference to the Modbus.dll file in netcf folder introduced above.

Add a using declaration to the source file that will contain the Modbus Master code.

using Modbus.Device;

Create a new SerialPort on COM1 with the same serial settings as the Modbus slave.

_serialPort = new SerialPort("COM1", 115200);
_serialPort.Open();

Initialize a new ModbusSerialMaster with the _serialPort as its transport.

_modbusMaster = ModbusSerialMaster.CreateRtu(_serialPort);
_modbusMaster.Transport.ReadTimeout = 500;
_modbusMaster.Transport.WriteTimeout = 500;
_modbusMaster.Transport.Retries = 0;

Then call any of the given methods to query a Modbus slave:

bool[] ReadCoils(byte slaveAddress, ushort startAddress, ushort numberOfPoints);
 
ushort[] ReadHoldingRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints);
 
ushort[] ReadInputRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints);
 
bool[] ReadInputs(byte slaveAddress, ushort startAddress, ushort numberOfPoints);
 
ushort[] ReadWriteMultipleRegisters(byte slaveAddress, ushort startReadAddress, 
         ushort numberOfPointsToRead, ushort startWriteAddress, ushort[] writeData);
 
void WriteMultipleCoils(byte slaveAddress, ushort startAddress, bool[] data);
 
void WriteMultipleRegisters(byte slaveAddress, ushort startAddress, ushort[] data);
 
void WriteSingleCoil(byte slaveAddress, ushort coilAddress, bool value);
 
void WriteSingleRegister(byte slaveAddress, ushort registerAddress, ushort value);

Sample Project

The following sample project will toggle MSB624RA-DC's relay 32 (at address 32) and read from the MSB624RA-DC's analog input (at address 276). Refer to the following table for the MSB624RA-DCs Modbus memory map.

Word (Holding/Input Registers)
Function Codes: 3, 4, 6, 16
Address (base 10) Data Region (base 10)
0 ~ 255 D Region (D0 ~ D255)
256 ~ 355 Y Region (Y0 ~ Y99)
ADC Result Y20 ~ Y27 (276 ~ 283)
1000 ~ 1255 T Region (T0 ~ T255)
2000 ~ 2255 C Region (C0 ~ C255)
3000 ~ 3255 WM Region (WM0 ~ WM255)
Bit (Coil, Input Status)
Function Codes: 1, 2, 4, 15
Address (base 10) Data Region (base 10)
0 ~ 127 P Region (P0 ~ P127)
4096 ~ 6143 M Region (M0 ~ M2047)

C# Source Code

Download the C# Project Files

using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using Modbus.Device;
using System.IO.Ports;
 
namespace NModbusTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        ModbusSerialMaster _modbusMaster;
        SerialPort _serialPort;
        const int SLAVE_ADDRESS = 1;
 
        private void Form1_Load(object sender, EventArgs e)
        {
            _serialPort = new SerialPort("COM1", 115200);
            _serialPort.Open();
 
            _modbusMaster = ModbusSerialMaster.CreateRtu(_serialPort);
            _modbusMaster.Transport.ReadTimeout = 500;
            _modbusMaster.Transport.WriteTimeout = 500;
            _modbusMaster.Transport.Retries = 0;
 
        }
 
        void ReportError(string s)
        {
            MessageBox.Show(s);
        }
 
        private void ReadADC()
        {
            try
            {
                ushort[] result = _modbusMaster.ReadInputRegisters(SLAVE_ADDRESS, 276, 1);
                _adcLabel.Text = result[0].ToString();
            }
            catch (Exception ex)
            {
                ReportError(ex.Message);
            }
        }
 
        private void ReadDigitalOutput()
        {
            try
            {
                bool[] result = _modbusMaster.ReadCoils(SLAVE_ADDRESS, 32, 1);
                if (result[0])
                {
                    _digitalOutLabel.Text = "ON";
                }
                else
                {
                    _digitalOutLabel.Text = "OFF";
                }
            }
            catch (Exception ex)
            {
                ReportError(ex.Message);
            }
        }
 
        private void WriteDigitalOutput(bool on)
        {
            try
            {
                _modbusMaster.WriteSingleCoil(SLAVE_ADDRESS, 32, on);
            }
            catch (Exception ex)
            {
                ReportError(ex.Message);
            }
        }
 
        private void _digitalOutReadButton_Click(object sender, EventArgs e)
        {
            ReadDigitalOutput();
        }
 
        private void _onButton_Click(object sender, EventArgs e)
        {
            WriteDigitalOutput(true);
        }
 
        private void _offButton_Click(object sender, EventArgs e)
        {
            WriteDigitalOutput(false);
        }
 
        private void _adcReadButton_Click(object sender, EventArgs e)
        {
            ReadADC();
        }
 
        private void Form1_Closing(object sender, CancelEventArgs e)
        {
            _modbusMaster.Dispose();
            _modbusMaster = null;
 
            _serialPort.Close();
            _serialPort.Dispose();
            _serialPort = null;
        }
    }
}

VB.NET Source Code

Download the VB.Net Project Files

Imports System
Imports System.Linq
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Text
Imports System.Windows.Forms
Imports System.Threading
Imports Modbus.Device
Imports System.IO.Ports
 
Public Class Form1
 
    Private _modbusMaster As ModbusSerialMaster
    Private _serialPort As SerialPort
    Const SLAVE_ADDRESS As Integer = 1
 
 
    Private Sub ReportError(ByVal s As String)
        MessageBox.Show(s)
    End Sub
 
    Private Sub ReadADC()
        Try
            Dim result As UShort() = _modbusMaster.ReadInputRegisters(SLAVE_ADDRESS, 276, 1)
            _adcLabel.Text = result(0).ToString()
        Catch ex As Exception
            ReportError(ex.Message)
        End Try
    End Sub
 
    Private Sub ReadDigitalOutput()
        Try
            Dim result As Boolean() = _modbusMaster.ReadCoils(SLAVE_ADDRESS, 32, 1)
 
            If result(0) Then
                _digitalOutLabel.Text = "ON"
            Else
                _digitalOutLabel.Text = "OFF"
            End If
 
        Catch ex As Exception
            ReportError(ex.Message)
        End Try
    End Sub
 
    Private Sub WriteDigitalOutput(ByVal [on] As Boolean)
        Try
            _modbusMaster.WriteSingleCoil(SLAVE_ADDRESS, 32, [on])
        Catch ex As Exception
            ReportError(ex.Message)
        End Try
    End Sub
 
    Private Sub _digitalOutReadButton_Click(ByVal sender As Object, ByVal e As EventArgs)
        ReadDigitalOutput()
    End Sub
 
    Private Sub _onButton_Click(ByVal sender As Object, ByVal e As EventArgs)
        WriteDigitalOutput(True)
    End Sub
 
    Private Sub _offButton_Click(ByVal sender As Object, ByVal e As EventArgs)
        WriteDigitalOutput(False)
    End Sub
 
    Private Sub _adcReadButton_Click(ByVal sender As Object, ByVal e As EventArgs)
        ReadADC()
    End Sub
 
    Private Sub Form1_Closing(ByVal sender As Object, ByVal e As CancelEventArgs)
        _modbusMaster.Dispose()
        _modbusMaster = Nothing
        _serialPort.Close()
        _serialPort.Dispose()
        _serialPort = Nothing
    End Sub
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        _serialPort = New SerialPort("COM1", 115200)
        _serialPort.Open()
        _modbusMaster = ModbusSerialMaster.CreateRtu(_serialPort)
        _modbusMaster.Transport.ReadTimeout = 500
        _modbusMaster.Transport.WriteTimeout = 500
        _modbusMaster.Transport.Retries = 0
    End Sub
End Class

Demonstration Video

cuwin/creating_a_cuwin_modbus_rtu_master_with_nmodbus/index.txt · Last modified: 2022/08/29 09:59 by COMFILE Technology