사용자 도구

사이트 도구

English

comfilepi:nmodbus4_k:index

NModbus4 사용법

산업현장에서 많이 사용하고 있는 MODBUS 프로토콜을 ComfilePi에서 동작시키는 방법을 알아보겠습니다. Nmodbus4 라이브러리를 이용하면 쉽고 간단하게 MODBUS프로토콜을 구현할 수 있습니다.

ComfilePi와 PLC 결선

ComfilePi의 RS232 COM0와 PLC의 RS232 포트에 TX-RX, RX-TX, GND-GND로 연결합니다. ComfilePi와 PLC의 RS232 결선은 아래와 같습니다.

PLC는 컴파일테크놀로지의 MSB612RA-DC 제품입니다.

NModbus4 라이브러리 추가

NModbus4 라이브러리를 Visual Studio 2017에 추가하는 방법에 대해 알아보겠습니다.

  • 1. 프로젝트를 만든 후 우측의 "솔루션 탐색기""프로젝트(ModbusExample)"에 우클릭으로 "NuGet 패키지 관리(N).."를 선택 합니다.

  • 2. "찾아보기" 선택 → 검색창에 "NModbus" 검색 → "NModbus4" 선택 → "설치" 클릭

  • 3. 출력창에서 NModbus4 라이브러리 설치 상태를 확인 할 수 있습니다.

Modbus 프로그래밍

NModbus4의 Function(함수)와 Serial Port설정에 대해 알아 보겠습니다.

  • 1. Serial Port설정 : 데스크탑 PC의 Serial Port와 ComfilePi의 Serial Port는 다릅니다. 프로젝트 코드에 아래와 같이 SerialPort를 설정 해야합니다.
  • ※ ComfilePi의 COM0"/dev/serial0", COM1"/dev/serial1"로 설정합니다.
string portName = Environment.OSVersion.Platform == PlatformID.Win32NT ? "COM0" : "/dev/serial0";
SerialPort port = new SerialPort(portName, 115200);
port.ReadTimeout = 100;
port.WriteTimeout = 100;
port.Open();
  • 2. ComfilePi를 Master로 사용시 PLC의 상태를 읽어오고 제어할 수 있는 함수입니다.
  • ※ ModbusRTU Master는 ModbusSerialMaster 클래스를 사용합니다.
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);
  • 3. NModbus4 라이브러를 이용해 만든 실행파일(.exe)을 ComfilePi에서 사용하려면 실행파일(.exe)NModbus4.dll를 ComfilePi의 '/home/pi' 위치에 복사해 사용합니다.


프로그램

ModbusRTU 프로토콜로, NModbus4를 이용한 예제 프로그램 입니다. ComfilePi를 Master로 PLC(MSB612RA-DC)를 Slave로 작성 되었습니다.

- Example 1

소스코드 다운로드 ☞ simple_modbus_example.zip

using Modbus.Device;
using System;
using System.IO.Ports;
using System.Windows.Forms;
 
namespace SimpleModbusExample
{
    public partial class Form1 : Form
    {
        const int SLAVE_ADDRESS = 1;
        const int COIL_ADDRESS = 32;
 
        public Form1()
        {
            InitializeComponent();
        }
 
        SerialPort _port;
        ModbusSerialMaster _master;
 
        private void Form1_Load(object sender, EventArgs e)
        {
            // Intialize serial port
            string portName = Environment.OSVersion.Platform == PlatformID.Win32NT ? "COM0" : "/dev/serial0";
            _port = new SerialPort(portName, 115200);
            _port.ReadTimeout = 100;
            _port.WriteTimeout = 100;
            _port.Open();
 
            // Initialize Modbus master
            _master = ModbusSerialMaster.CreateRtu(_port);
 
            // Read the current state of the output
            ReadState();
        }
 
        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            // Destroy Modbus master
            _master.Dispose();
            _master = null;
 
            // Destroy serial port
            _port.Close();
            _port.Dispose();
            _port = null;
        }
 
        private void OnButton_Click(object sender, EventArgs e)
        {
            // Turn output ON
            _master.WriteSingleCoil(SLAVE_ADDRESS, COIL_ADDRESS, true);
 
        }
 
        private void OffButton_Click(object sender, EventArgs e)
        {
            // Turn output OFF
            _master.WriteSingleCoil(SLAVE_ADDRESS, COIL_ADDRESS, false);
        }
 
        void ReadState()
        {
            // Read the current state of the output
            var state = _master.ReadCoils(SLAVE_ADDRESS, COIL_ADDRESS, 1);
 
            // Update the UI
            if (state[0])
            {
                StateLabel.Text = "On";
            }
            else
            {
                StateLabel.Text = "Off";
            }
        }
 
        private void ReadStateButton_Click(object sender, EventArgs e)
        {
            // Read the current state of the output
            ReadState();
        }
    }
}


- Example 2

소스코드 다운로드 ☞ modbus_example.zip

using System;
using System.Windows.Forms;
using System.IO.Ports;
using Modbus.Device;
using System.Threading;
 
namespace ModbusExample
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        private volatile bool _stopModbus;
        private Thread _modbusThread;
 
        private void RunModbus()
        {
            string portName = Environment.OSVersion.Platform == PlatformID.Win32NT ? "COM0" : "/dev/serial0";
            SerialPort port = new SerialPort(portName, 115200);
            port.ReadTimeout = 100;
            port.WriteTimeout = 100;
            port.Open();
 
            _stopModbus = false;
 
            ModbusSerialMaster master = ModbusSerialMaster.CreateRtu(port);
            IAsyncResult result = null;
 
            while(!_stopModbus)
            {
                // Read UI's button states and assign to device's outputs
                bool[] outputs = new bool[4];
                result = BeginInvoke(new Action(() =>
                {
                    outputs[0] = button1.IsOn;
                    outputs[1] = button2.IsOn;
                    outputs[2] = button3.IsOn;
                    outputs[3] = button4.IsOn;
                }));
 
                while (!_stopModbus && !result.IsCompleted)
                {
                    Thread.Yield();
                }
 
                if (!_stopModbus)
                {
                    try
                    {
                        master.WriteMultipleCoils(1, 32, outputs);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }
 
                // Read inputs and assign to UI's Lamps
                if (!_stopModbus)
                {
                    try
                    {
                        var inputs = master.ReadCoils(1, 8, 4);
 
                        result = BeginInvoke(new Action(() =>
                        {
                            lamp8.IsOn = inputs[3];
                            lamp9.IsOn = inputs[2];
                            lamp10.IsOn = inputs[1];
                            lamp11.IsOn = inputs[0];
                        }));
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }                    
                }
 
                while (!_stopModbus && !result.IsCompleted)
                {
                    Thread.Yield();
                }
            }
 
            master.Dispose();
 
            port.Close();
            port.Dispose();
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            _modbusThread = new Thread(RunModbus);
            _modbusThread.IsBackground = true;
            _modbusThread.Start();
        }
 
        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            _stopModbus = true;
            _modbusThread.Join();
        }
    }
}

이전 페이지로 이동

comfilepi/nmodbus4_k/index.txt · 마지막으로 수정됨: 2020/02/26 01:38 저자 Comfile Technology