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)

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;
        }
    }
}

cuwin/creating_a_cuwin_modbus_rtu_master_with_nmodbus/index.txt · Last modified: 2016/04/14 11:07 (external edit)